diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.cpp b/bindings/java/jni/dataModel_SleuthkitJNI.cpp index cea4f13ecc7166fc59847f2d2eca7cbd4e9c7b54..8a745e327bc3b05c0624774e0ffc09f115da781d 100644 --- a/bindings/java/jni/dataModel_SleuthkitJNI.cpp +++ b/bindings/java/jni/dataModel_SleuthkitJNI.cpp @@ -1684,7 +1684,7 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_readFsNat(JNIEnv * env, */ JNIEXPORT jint JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_readFileNat(JNIEnv * env, - jclass obj, jlong a_file_handle, jbyteArray jbuf, jlong offset, jlong len) + jclass obj, jlong a_file_handle, jbyteArray jbuf, jlong offset, jint offset_type, jlong len) { //use fixed size stack-allocated buffer if possible char fixed_buf [FIXED_BUF_SIZE]; @@ -1711,9 +1711,16 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_readFileNat(JNIEnv * env, TSK_FS_ATTR * tsk_fs_attr = file_handle->fs_attr; + TSK_FS_FILE_READ_FLAG_ENUM readFlag = TSK_FS_FILE_READ_FLAG_NONE; + TSK_OFF_T readOffset = (TSK_OFF_T) offset; + if(offset_type == TSK_FS_FILE_READ_OFFSET_TYPE_START_OF_SLACK){ + readFlag = TSK_FS_FILE_READ_FLAG_SLACK; + readOffset += tsk_fs_attr->size; + } + //read attribute - ssize_t bytesread = tsk_fs_attr_read(tsk_fs_attr, (TSK_OFF_T) offset, buf, (size_t) len, - TSK_FS_FILE_READ_FLAG_NONE); + ssize_t bytesread = tsk_fs_attr_read(tsk_fs_attr, readOffset, buf, (size_t) len, + readFlag); if (bytesread == -1) { if (dynBuf) { free(buf); diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.h b/bindings/java/jni/dataModel_SleuthkitJNI.h index 97e77e530924568f3314041319089ebc459afd75..bd4ff63b7cb863507fa68b0ab7643de880c1370c 100644 --- a/bindings/java/jni/dataModel_SleuthkitJNI.h +++ b/bindings/java/jni/dataModel_SleuthkitJNI.h @@ -330,10 +330,10 @@ JNIEXPORT jint JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_readFsNat /* * Class: org_sleuthkit_datamodel_SleuthkitJNI * Method: readFileNat - * Signature: (J[BJJ)I + * Signature: (J[BJIJ)I */ JNIEXPORT jint JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_readFileNat - (JNIEnv *, jclass, jlong, jbyteArray, jlong, jlong); + (JNIEnv *, jclass, jlong, jbyteArray, jlong, jint, jlong); /* * Class: org_sleuthkit_datamodel_SleuthkitJNI diff --git a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java index 173456c28f10fc5040b182fc756f2af24c956cb1..2629402a13907e570c93ada69ce28be09b49f59f 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java +++ b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java @@ -41,7 +41,7 @@ */ public abstract class AbstractFile extends AbstractContent { - protected final TskData.TSK_DB_FILES_TYPE_ENUM fileType; + protected TskData.TSK_DB_FILES_TYPE_ENUM fileType; protected final TSK_FS_NAME_TYPE_ENUM dirType; protected final TSK_FS_META_TYPE_ENUM metaType; protected final TSK_FS_NAME_FLAG_ENUM dirFlag; @@ -610,6 +610,20 @@ public boolean isFile() { return metaType.equals(TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG); } + + /** + * Is this object a slack file + * + * @return true if a slack file, false otherwise + */ + public boolean isSlackFile() { + return fileType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK); + } + + // TEMP TEMP TEMP + public void setFileType(TskData.TSK_DB_FILES_TYPE_ENUM type){ + fileType = type; + } /** * Is this object a directory diff --git a/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java b/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java index 409bb2d58d72d8aa1d6bf7a63e528fbfa403e064..46da0f4fc21bc6cbbc5b79c0df21594f2f352460 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java +++ b/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java @@ -120,6 +120,15 @@ public interface ContentVisitor<T> { * @return result of the visit */ T visit(LocalFile df); + + /** + * Act on (visit) a SlackFile content object + * + * @param sf slack file to visit / act on + * + * @return result of the visit + */ + T visit(SlackFile sf); /** * The default content visitor - quickest method for implementing a custom @@ -184,5 +193,10 @@ public T visit(DerivedFile df) { public T visit(LocalFile lf) { return defaultVisit(lf); } + + @Override + public T visit(SlackFile sf) { + return defaultVisit(sf); + } } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/FsContent.java b/bindings/java/src/org/sleuthkit/datamodel/FsContent.java index 8f62d06686b15d829a2b3b8fa91baa9dbd0de10d..76f9ba04776fa761b97d569d334b1816afc4c488 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/FsContent.java +++ b/bindings/java/src/org/sleuthkit/datamodel/FsContent.java @@ -170,7 +170,7 @@ public FileSystem getFileSystem() throws TskCoreException { * @throws TskCoreException if there is a problem opening the handle. */ @SuppressWarnings("deprecation") - private void loadFileHandle() throws TskCoreException { + void loadFileHandle() throws TskCoreException { if (fileHandle == 0) { synchronized (this) { if (fileHandle == 0) { diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index ba1f9237d4a92336f21dd62b558c3793d8623532..7a3777ddd249d025fe50f41509e51be25c54b04a 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -5179,8 +5179,10 @@ private List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnecti final LocalFile lf; lf = localFile(rs, connection, AbstractContent.UNKNOWN_ID); results.add(lf); + } else if (type == TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()) { + final SlackFile sf = slackFile(rs, null); + results.add(sf); } - } //end for each resultSet } catch (SQLException e) { logger.log(Level.SEVERE, "Error getting abstract files from result set", e); //NON-NLS @@ -5214,6 +5216,10 @@ org.sleuthkit.datamodel.File file(ResultSet rs, FileSystem fs) throws SQLExcepti (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS rs.getString("md5"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS rs.getString("parent_path"), rs.getString("mime_type")); //NON-NLS + if(TSK_DB_FILES_TYPE_ENUM.valueOf(rs.getShort("type")).equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)){ + System.out.println("Have a slack file - this shouldn't be happening " + f.getName()); + f.setFileType(TSK_DB_FILES_TYPE_ENUM.SLACK); + } f.setFileSystem(fs); return f; } @@ -5366,6 +5372,34 @@ LocalFile localFile(ResultSet rs, CaseDbConnection connection, long parentId) th localPath, encodingType); return file; } + + /** + * Create a Slack File object from the result set containing query results on + * tsk_files table + * + * @param rs the result set + * @param fs parent file system + * + * @return a newly create Slack File + * + * @throws SQLException + */ + org.sleuthkit.datamodel.SlackFile slackFile(ResultSet rs, FileSystem fs) throws SQLException { + org.sleuthkit.datamodel.SlackFile f = new org.sleuthkit.datamodel.SlackFile(this, rs.getLong("obj_id"), //NON-NLS + rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS + TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS + rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS + TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS + TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS + TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS + rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS + rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS + (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS + rs.getString("md5"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS + rs.getString("parent_path"), rs.getString("mime_type")); //NON-NLS + f.setFileSystem(fs); + return f; + } /** * Returns the list of abstractFile objects from a result of selecting many @@ -5425,6 +5459,11 @@ List<Content> fileChildren(ResultSet rs, CaseDbConnection connection, long paren children.add(lf); break; } + case SLACK: { + final SlackFile sf = slackFile(rs, null); + children.add(sf); + break; + } default: break; } diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java index 8f4b003cdbbe2ff2259bb3556ffc22509da5b9ad..66f3265255e8ed051c9fd12866c36d1c99c208c8 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java @@ -141,6 +141,15 @@ public interface SleuthkitItemVisitor<T> { * @return result of the visit */ T visit(LocalFile lf); + + /** + * Act on (visit) a SlackFile content object + * + * @param sf slack file to visit / act on + * + * @return result of the visit + */ + T visit(SlackFile sf); /** * The default visitor - quickest method for implementing a custom visitor. @@ -214,5 +223,10 @@ public T visit(DerivedFile df) { public T visit(LocalFile lf) { return defaultVisit(lf); } + + @Override + public T visit(SlackFile sf) { + return defaultVisit(sf); + } } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java index 156951a19de4d33e1b0005fa6f3c40b1e16be476..704fd1e94cc74cc24274fc68d41d602f620b164b 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java @@ -631,8 +631,26 @@ public static int readFs(long fsHandle, byte[] readBuffer, long offset, long len * TSK */ public static int readFile(long fileHandle, byte[] readBuffer, long offset, long len) throws TskCoreException { - return readFileNat(fileHandle, readBuffer, offset, len); + return readFileNat(fileHandle, readBuffer, offset, 0, len); } + + /** + * reads data from the slack space of a file + * + * @param fileHandle pointer to a file structure in the sleuthkit + * @param readBuffer pre-allocated buffer to read to + * @param offset byte offset in the slack to start at + * @param len amount of data to read + * + * @return the number of characters read, or -1 if the end of the stream has + * been reached + * + * @throws TskCoreException exception thrown if critical error occurs within + * TSK + */ + public static int readFileSlack(long fileHandle, byte[] readBuffer, long offset, long len) throws TskCoreException { + return readFileNat(fileHandle, readBuffer, offset, 1, len); + } /** * Get human readable (some what) details about a file. This is the same as @@ -1027,7 +1045,7 @@ public static long findDeviceSize(String devPath) throws TskCoreException { private static native int readFsNat(long fsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException; - private static native int readFileNat(long fileHandle, byte[] readBuffer, long offset, long len) throws TskCoreException; + private static native int readFileNat(long fileHandle, byte[] readBuffer, long offset, int offset_type, long len) throws TskCoreException; private static native int saveFileMetaDataTextNat(long fileHandle, String fileName) throws TskCoreException; diff --git a/bindings/java/src/org/sleuthkit/datamodel/TskData.java b/bindings/java/src/org/sleuthkit/datamodel/TskData.java index c7c442e4f33e7eca02bc9e9bc92252bdc8464759..63eeb87c39e0bb9bd9d83b9272ce8f686e141fdf 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/TskData.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TskData.java @@ -660,6 +660,7 @@ public enum TSK_DB_FILES_TYPE_ENUM { UNALLOC_BLOCKS(4, "Unallocated Blocks"), ///< Set of blocks not allocated by file system. Parent should be image, volume, or file system. Many columns in tsk_files will be NULL. Set layout in tsk_file_layout. UNUSED_BLOCKS(5, "Unused Blocks"), ///< Set of blocks that are unallocated AND not used by a carved or other file type. Parent should be UNALLOC_BLOCKS, many columns in tsk_files will be NULL, set layout in tsk_file_layout. VIRTUAL_DIR(6, "Virtual Directory"), ///< Virtual directory (not on fs) with no meta-data entry that can be used to group files of types other than TSK_DB_FILES_TYPE_FS. Its parent is either another TSK_DB_FILES_TYPE_FS or a root directory or type TSK_DB_FILES_TYPE_FS. + SLACK(7, "Slack"), ///< Slack space for a single file ; private final short fileType; diff --git a/tsk/fs/tsk_fs.h b/tsk/fs/tsk_fs.h index d927272ed9110c7c53c99e3dcfe9845e53a5b01e..c859c6411b98b9db48a8a5b448c1a3cfe23b19f7 100644 --- a/tsk/fs/tsk_fs.h +++ b/tsk/fs/tsk_fs.h @@ -690,6 +690,14 @@ extern "C" { TSK_FS_FILE_READ_FLAG_NOID = 0x02, ///< Ignore the Id argument given in the API (use only the type) } TSK_FS_FILE_READ_FLAG_ENUM; + /** + * Flag used by readFileNat to specify if the offset is relative to the start of the file + * or the start of the slack space */ + typedef enum { + TSK_FS_FILE_READ_OFFSET_TYPE_START_OF_FILE = 0x00, + TSK_FS_FILE_READ_OFFSET_TYPE_START_OF_SLACK = 0x01, + } TSK_FS_FILE_READ_OFFSET_TYPE_ENUM; + extern void tsk_fs_file_close(TSK_FS_FILE * a_fs_file); extern TSK_FS_FILE *tsk_fs_file_open(TSK_FS_INFO * a_fs, TSK_FS_FILE * a_fs_file, const char *a_path);