diff --git a/bindings/java/src/org/sleuthkit/datamodel/Image.java b/bindings/java/src/org/sleuthkit/datamodel/Image.java index 20386458994056eec2a6515b0c309be87d53acf6..539c0708583c4f3458041d715486946d62bdd6c6 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Image.java +++ b/bindings/java/src/org/sleuthkit/datamodel/Image.java @@ -119,6 +119,10 @@ protected Image(SleuthkitCase db, long obj_id, long type, long ssize, String nam * @throws TskCoreException */ public synchronized long getImageHandle() throws TskCoreException { + if (paths.length == 0) { + throw new TskCoreException("Image has no associated paths"); + } + if (imageHandle == 0) { imageHandle = SleuthkitJNI.openImage(paths, (int)ssize); } @@ -150,6 +154,11 @@ public void finalize() throws Throwable { @Override public int read(byte[] buf, long offset, long len) throws TskCoreException { + // If there are no paths, don't attempt to read the image + if (paths.length == 0) { + return 0; + } + // read from the image return SleuthkitJNI.readImg(getImageHandle(), buf, offset, len); } diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index 847eaf4677d7e04af1ba47265c9a0b6dc3abcc3f..6ae044265c8e35ccd353d2c876d6dfa012e4b180 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -5089,10 +5089,14 @@ public LocalDirectory addLocalDirectory(long parentId, String directoryName, Cas CaseDbConnection connection = transaction.getConnection(); AbstractFile parent = getAbstractFileById(parentId, connection); String parentPath; - if (parent.getParent() == null && parent.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) { - parentPath = "/"; + if (parent != null) { + if (parent.getParent() == null && parent.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) { + parentPath = "/"; + } else { + parentPath = parent.getParentPath() + parent.getName() + "/"; //NON-NLS + } } else { - parentPath = parent.getParentPath() + parent.getName() + "/"; //NON-NLS + parentPath = "/"; } // Insert a row for the local directory into the tsk_objects table. @@ -5238,7 +5242,229 @@ public LocalFilesDataSource addLocalFilesDataSource(String deviceId, String root releaseSingleUserCaseWriteLock(); } } + + /** + * Add an image to the database. + * + * @param type Type of image + * @param sectorSize Sector size + * @param size Image size + * @param displayName Display name for the image + * @param imagePaths Image path(s) + * @param timezone Time zone + * @param md5 MD5 hash + * @param sha1 SHA1 hash + * @param sha256 SHA256 hash + * @param deviceId Device ID + * @param transaction Case DB transaction + * + * @return the newly added Image + * + * @throws TskCoreException + */ + public Image addImage(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName, List<String> imagePaths, + String timezone, String md5, String sha1, String sha256, + String deviceId, + CaseDbTransaction transaction) throws TskCoreException { + acquireSingleUserCaseWriteLock(); + Statement statement = null; + try { + // Insert a row for the Image into the tsk_objects table. + CaseDbConnection connection = transaction.getConnection(); + long newObjId = addObject(0, TskData.ObjectType.IMG.getObjectType(), connection); + + // Add a row to tsk_image_info + // INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name) + PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_INFO); + preparedStatement.clearParameters(); + preparedStatement.setLong(1, newObjId); + preparedStatement.setShort(2, (short)type.getValue()); + preparedStatement.setLong(3, sectorSize); + preparedStatement.setString(4, timezone); + preparedStatement.setLong(5, size); + preparedStatement.setString(6, md5); + preparedStatement.setString(7, sha1); + preparedStatement.setString(8, sha256); + preparedStatement.setString(9, displayName); + connection.executeUpdate(preparedStatement); + + // If there are paths, add them to tsk_image_names + for (int i = 0; i < imagePaths.size(); i++) { + preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME); + preparedStatement.clearParameters(); + preparedStatement.setLong(1, newObjId); + preparedStatement.setString(2, imagePaths.get(i)); + preparedStatement.setLong(3, i); + connection.executeUpdate(preparedStatement); + } + + // Add a row to data_source_info + statement = connection.createStatement(); + statement.executeUpdate("INSERT INTO data_source_info (obj_id, device_id, time_zone) " + + "VALUES(" + newObjId + ", '" + deviceId + "', '" + timezone + "');"); + + // Create the new Image object + return new Image(this, newObjId, type.getValue(), deviceId, sectorSize, displayName, + imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, size); + } catch (SQLException ex) { + if (! imagePaths.isEmpty()) { + throw new TskCoreException(String.format("Error adding image with path %s to database", imagePaths.get(0)), ex); + } else { + throw new TskCoreException(String.format("Error adding image with display name %s to database", displayName), ex); + } + } finally { + closeStatement(statement); + releaseSingleUserCaseWriteLock(); + } + } + + /** + * Add a volume system to the database. + * + * @param parentObjId Object ID of the volume system's parent + * @param type Type of volume system + * @param imgOffset Image offset + * @param blockSize Block size + * @param transaction Case DB transaction + * + * @return the newly added VolumeSystem + * + * @throws TskCoreException + */ + public VolumeSystem addVolumeSystem(long parentObjId, TskData.TSK_VS_TYPE_ENUM type, long imgOffset, + long blockSize, CaseDbTransaction transaction) throws TskCoreException{ + acquireSingleUserCaseWriteLock(); + try { + // Insert a row for the VolumeSystem into the tsk_objects table. + CaseDbConnection connection = transaction.getConnection(); + long newObjId = addObject(parentObjId, TskData.ObjectType.VS.getObjectType(), connection); + + // Add a row to tsk_vs_info + // INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) + PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_INFO); + preparedStatement.clearParameters(); + preparedStatement.setLong(1, newObjId); + preparedStatement.setShort(2, (short)type.getVsType()); + preparedStatement.setLong(3, imgOffset); + preparedStatement.setLong(4, blockSize); + connection.executeUpdate(preparedStatement); + + // Create the new VolumeSystem object + return new VolumeSystem(this, newObjId, "", type.getVsType(), imgOffset, blockSize); + } catch (SQLException ex) { + throw new TskCoreException(String.format("Error creating volume system with parent ID %d and image offset %d", + parentObjId, imgOffset), ex); + } finally { + releaseSingleUserCaseWriteLock(); + } + } + /** + * Add a volume to the database + * + * @param parentObjId Object ID of the volume's parent + * @param addr Address of the volume + * @param start Start of the volume + * @param length Length of the volume + * @param desc Description of the volume + * @param flags Flags + * @param transaction Case DB transaction + * + * @return the newly created Volume + * + * @throws TskCoreException + */ + public Volume addVolume(long parentObjId, long addr, long start, long length, String desc, + long flags, CaseDbTransaction transaction) throws TskCoreException{ + acquireSingleUserCaseWriteLock(); + Statement statement = null; + try { + // Insert a row for the Volume into the tsk_objects table. + CaseDbConnection connection = transaction.getConnection(); + long newObjId = addObject(parentObjId, TskData.ObjectType.VOL.getObjectType(), connection); + + // Add a row to tsk_vs_parts + // INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags) + PreparedStatement preparedStatement; + if (this.dbType == DbType.POSTGRESQL) { + preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_POSTGRESQL); + } else { + preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_SQLITE); + } + preparedStatement.clearParameters(); + preparedStatement.setLong(1, newObjId); + preparedStatement.setLong(2, addr); + preparedStatement.setLong(3, start); + preparedStatement.setLong(4, length); + preparedStatement.setString(5, desc); + preparedStatement.setShort(6, (short)flags); + connection.executeUpdate(preparedStatement); + + // Create the new Volume object + return new Volume(this, newObjId, addr, start, length, flags, desc); + } catch (SQLException ex) { + throw new TskCoreException(String.format("Error creating volume with address %d and parent ID %d", addr, parentObjId), ex); + } finally { + closeStatement(statement); + releaseSingleUserCaseWriteLock(); + } + } + + /** + * Add a FileSystem to the database. + * + * @param parentObjId Object ID of the file system's parent + * @param imgOffset Offset in the image + * @param type Type of file system + * @param blockSize Block size + * @param blockCount Block count + * @param rootInum root inum + * @param firstInum first inum + * @param lastInum last inum + * @param displayName display name + * @param transaction Case DB transaction + * + * @return the newly created FileSystem + * + * @throws TskCoreException + */ + public FileSystem addFileSystem(long parentObjId, long imgOffset, TskData.TSK_FS_TYPE_ENUM type, long blockSize, long blockCount, + long rootInum, long firstInum, long lastInum, String displayName, + CaseDbTransaction transaction) throws TskCoreException{ + acquireSingleUserCaseWriteLock(); + Statement statement = null; + try { + // Insert a row for the FileSystem into the tsk_objects table. + CaseDbConnection connection = transaction.getConnection(); + long newObjId = addObject(parentObjId, TskData.ObjectType.FS.getObjectType(), connection); + + // Add a row to tsk_fs_info + // INSERT INTO tsk_fs_info (obj_id, img_offset, fs_type, block_size, block_count, root_inum, first_inum, last_inum, display_name) + PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FS_INFO); + preparedStatement.clearParameters(); + preparedStatement.setLong(1, newObjId); + preparedStatement.setLong(2, imgOffset); + preparedStatement.setShort(3, (short)type.getValue()); + preparedStatement.setLong(4, blockSize); + preparedStatement.setLong(5, blockCount); + preparedStatement.setLong(6, rootInum); + preparedStatement.setLong(7, firstInum); + preparedStatement.setLong(8, lastInum); + preparedStatement.setString(9, displayName); + connection.executeUpdate(preparedStatement); + + // Create the new FileSystem object + return new FileSystem(this, newObjId, displayName, imgOffset, type, blockSize, blockCount, rootInum, + firstInum, lastInum); + } catch (SQLException ex) { + throw new TskCoreException(String.format("Error creating file system with image offset %d and parent ID %d", + imgOffset, parentObjId), ex); + } finally { + closeStatement(statement); + releaseSingleUserCaseWriteLock(); + } + } + /** * Get IDs of the virtual folder roots (at the same level as image), used * for containers such as for local files. @@ -9770,7 +9996,15 @@ private enum PREPARED_STATEMENT { UPDATE_FILE_NAME("UPDATE tsk_files SET name = ? WHERE obj_id = ?"), UPDATE_IMAGE_NAME("UPDATE tsk_image_info SET display_name = ? WHERE obj_id = ?"), DELETE_IMAGE_NAME("DELETE FROM tsk_image_names WHERE obj_id = ?"), - INSERT_IMAGE_NAME("INSERT INTO tsk_image_names (obj_id, name, sequence) VALUES (?, ?, ?)"); + INSERT_IMAGE_NAME("INSERT INTO tsk_image_names (obj_id, name, sequence) VALUES (?, ?, ?)"), + INSERT_IMAGE_INFO("INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)" + + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"), + INSERT_VS_INFO("INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (?, ?, ?, ?)"), + INSERT_VS_PART_SQLITE("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags) VALUES (?, ?, ?, ?, ?, ?)"), + INSERT_VS_PART_POSTGRESQL("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, descr, flags) VALUES (?, ?, ?, ?, ?, ?)"), + INSERT_FS_INFO("INSERT INTO tsk_fs_info (obj_id, img_offset, fs_type, block_size, block_count, root_inum, first_inum, last_inum, display_name)" + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); + private final String sql;