1 /* 2 * SleuthKit Java Bindings 3 * 4 * Copyright 2011-2017 Basis Technology Corp. 5 * Contact: carrier <at> sleuthkit <dot> org 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 package org.sleuthkit.datamodel; 20 21 import java.util.logging.Level; 22 import java.util.logging.Logger; 23 import org.sleuthkit.datamodel.TskData.FileKnown; 24 import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; 25 import org.sleuthkit.datamodel.TskData.TSK_FS_ATTR_TYPE_ENUM; 26 import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM; 27 import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; 28 import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_TYPE_ENUM; 29 30 /** 31 * A representation of a layout file that has been added to a case. Layout files 32 * are not file system files, but "virtual" files created from blocks of data 33 * (e.g. unallocated) that are treated as files for convenience and uniformity. 34 * 35 * Because layout files are not real file system files, they only utilize a 36 * subset of meta-data attributes. A layout file normally contains one or more 37 * entry in tsk_file_layout table that define ordered byte block ranges, with 38 * respect to the image. 39 * 40 * The class also supports reads of layout files, reading blocks across ranges 41 * in a sequence. 42 */ 43 public class LayoutFile extends AbstractFile { 44 45 private long imageHandle = -1; 46 47 /** 48 * Constructs a representation of a layout file that has been added to a 49 * case. Layout files are not file system files, but "virtual" files created 50 * from blocks of data (e.g. unallocated) that are treated as files for 51 * convenience and uniformity. 52 * 53 * @param db The case database to which the file has been 54 * added. 55 * @param objId The object id of the file in the case database. 56 * @param dataSourceObjectId The object id of the data source for the file. 57 * @param name The name of the file. 58 * @param fileType The type of the file. 59 * @param dirType The type of the file, usually as reported in 60 * the name structure of the file system. May be 61 * set to TSK_FS_NAME_TYPE_ENUM.UNDEF. 62 * @param metaType The type of the file, usually as reported in 63 * the metadata structure of the file system. May 64 * be set to 65 * TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_UNDEF. 66 * @param dirFlag The allocated status of the file, usually as 67 * reported in the name structure of the file 68 * system. 69 * @param metaFlags The allocated status of the file, usually as 70 * reported in the metadata structure of the file 71 * system. 72 * @param size The size of the file. 73 * @param ctime The changed time of the file. 74 * @param crtime The creation time of the file. 75 * @param atime The accessed time of the file 76 * @param mtime The modified time of the file. 77 * @param md5Hash The MD5 hash of the file, null if not yet 78 * calculated. 79 * @param knownState The known state of the file from a hash 80 * database lookup, null if not yet looked up. 81 * @param parentPath The path of the parent of the file. 82 * @param mimeType The MIME type of the file, null if it has not 83 * yet been determined. 84 */ LayoutFile(SleuthkitCase db, long objId, long dataSourceObjectId, String name, TSK_DB_FILES_TYPE_ENUM fileType, TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, long ctime, long crtime, long atime, long mtime, String md5Hash, FileKnown knownState, String parentPath, String mimeType)85 LayoutFile(SleuthkitCase db, 86 long objId, 87 long dataSourceObjectId, 88 String name, 89 TSK_DB_FILES_TYPE_ENUM fileType, 90 TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, 91 TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, 92 long size, 93 long ctime, long crtime, long atime, long mtime, 94 String md5Hash, FileKnown knownState, 95 String parentPath, String mimeType) { 96 super(db, objId, dataSourceObjectId, TSK_FS_ATTR_TYPE_ENUM.TSK_FS_ATTR_TYPE_DEFAULT, 0, name, fileType, 0L, 0, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, (short) 0, 0, 0, md5Hash, knownState, parentPath, mimeType, SleuthkitCase.extractExtension(name)); 97 } 98 99 /** 100 * Gets the number of file layout ranges associated with this layout file. 101 * 102 * @return The number of file layout ranges. 103 */ getNumParts()104 public int getNumParts() { 105 int numParts = 0; 106 try { 107 numParts = getRanges().size(); 108 } catch (TskCoreException ex) { 109 Logger.getLogger(LayoutFile.class.getName()).log(Level.SEVERE, String.format("Error getting layout ranges for layout file (objId = %d)", getId()), ex); //NON-NLS 110 } 111 return numParts; 112 } 113 114 /** 115 * Indicates whether or not this layout file is the root of a file system, 116 * always returns false. 117 * 118 * @return False. 119 */ 120 @Override isRoot()121 public boolean isRoot() { 122 return false; 123 } 124 125 /** 126 * Does nothing, a layout file cannot be directly opened, read, or closed. 127 * Use the readInt method to get layout file content. 128 */ 129 @Override close()130 public void close() { 131 } 132 133 /** 134 * Reads bytes from the layout ranges associated with this file. 135 * 136 * @param buf Buffer to read into. 137 * @param offset Start position in the file. 138 * @param len Number of bytes to read. 139 * 140 * @return Number of bytes read. 141 * 142 * @throws TskCoreException if there is a problem reading the file. 143 */ 144 @Override readInt(byte[] buf, long offset, long len)145 protected int readInt(byte[] buf, long offset, long len) throws TskCoreException { 146 long offsetInThisLayoutContent = 0; // current offset in this LayoutContent 147 int bytesRead = 0; // Bytes read so far 148 149 // if the caller has requested more data than we have in the file 150 // then make sure we don't go beyond the end of the file 151 long readLen = len; 152 if (offset + readLen > size) 153 readLen = size - offset; 154 155 if (imageHandle == -1) { 156 Content dataSource = getDataSource(); 157 if ((dataSource != null) && (dataSource instanceof Image)) { 158 Image image = (Image) dataSource; 159 imageHandle = image.getImageHandle(); 160 } else { 161 throw new TskCoreException("Data Source of LayoutFile is not Image"); 162 } 163 } 164 165 for (TskFileRange range : getRanges()) { 166 if (bytesRead < readLen) { // we haven't read enough yet 167 if (offset < offsetInThisLayoutContent + range.getByteLen()) { // if we are in a range object we want to read from 168 long offsetInRange = 0; // how far into the current range object to start reading 169 if (bytesRead == 0) { // we haven't read anything yet so we want to read from the correct offset in this range object 170 offsetInRange = offset - offsetInThisLayoutContent; // start reading from the correct offset 171 } 172 long offsetInImage = range.getByteStart() + offsetInRange; // how far into the image to start reading 173 long lenToReadInRange = Math.min(range.getByteLen() - offsetInRange, readLen - bytesRead); // how much we can read this time 174 int lenRead = readImgToOffset(imageHandle, buf, bytesRead, offsetInImage, (int) lenToReadInRange); 175 bytesRead += lenRead; 176 if (lenToReadInRange != lenRead) { // If image read failed or was cut short 177 break; 178 } 179 } 180 offsetInThisLayoutContent += range.getByteLen(); 181 } else { // we're done reading 182 break; 183 } 184 } 185 return bytesRead; 186 } 187 188 /** 189 * Reads bytes from an image into a buffer, starting at given position in 190 * buffer. 191 * 192 * @param imgHandle The image to read from. 193 * @param buf The array to read into. 194 * @param offsetInBuf Where to start in the array. 195 * @param offsetInImage Where to start in the image. 196 * @param lenToRead How far to read in the image. 197 * 198 * @return the number of characters read, or -1 if the end of the stream has 199 * been reached 200 * 201 * @throws TskCoreException exception thrown if critical error occurs within 202 * TSK 203 */ readImgToOffset(long imgHandle, byte[] buf, int offsetInBuf, long offsetInImage, int lenToRead)204 private int readImgToOffset(long imgHandle, byte[] buf, int offsetInBuf, long offsetInImage, int lenToRead) throws TskCoreException { 205 byte[] currentBuffer = new byte[lenToRead]; // the buffer for the current range object 206 int lenRead = SleuthkitJNI.readImg(imgHandle, currentBuffer, offsetInImage, lenToRead); 207 System.arraycopy(currentBuffer, 0, buf, offsetInBuf, lenToRead); // copy what we just read into the main buffer 208 return lenRead; 209 } 210 211 /** 212 * Accepts a content visitor (Visitor design pattern). 213 * 214 * @param visitor A ContentVisitor supplying an algorithm to run using this 215 * file as input. 216 * 217 * @return The output of the algorithm. 218 */ 219 @Override accept(ContentVisitor<T> visitor)220 public <T> T accept(ContentVisitor<T> visitor) { 221 return visitor.visit(this); 222 } 223 224 /** 225 * Accepts a Sleuthkit item visitor (Visitor design pattern). 226 * 227 * @param visitor A SleuthkitItemVisitor supplying an algorithm to run using 228 * this file as input. 229 * 230 * @return The output of the algorithm. 231 */ 232 @Override accept(SleuthkitItemVisitor<T> visitor)233 public <T> T accept(SleuthkitItemVisitor<T> visitor) { 234 return visitor.visit(this); 235 } 236 237 /** 238 * Provides a string representation of this file. 239 * 240 * @param preserveState True if state should be included in the string 241 * representation of this object. 242 */ 243 @Override toString(boolean preserveState)244 public String toString(boolean preserveState) { 245 return super.toString(preserveState) + "LayoutFile [\t" + "]\t"; //NON-NLS 246 } 247 248 /** 249 * Constructs a representation of a layout file that has been added to a 250 * case. Layout files are not file system files, but "virtual" files created 251 * from blocks of data (e.g. unallocated) that are treated as files for 252 * convenience and uniformity. 253 * 254 * @param db The case database to which the file has been added. 255 * @param objId The object id of the file in the case database. 256 * @param name The name of the file. 257 * @param fileType The type of the file. 258 * @param dirType The type of the file, usually as reported in the name 259 * structure of the file system. May be set to 260 * TSK_FS_NAME_TYPE_ENUM.UNDEF. 261 * @param metaType The type of the file, usually as reported in the 262 * metadata structure of the file system. May be set to 263 * TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_UNDEF. 264 * @param dirFlag The allocated status of the file, usually as reported 265 * in the name structure of the file system. 266 * @param metaFlags The allocated status of the file, usually as reported 267 * in the metadata structure of the file system. 268 * @param size The size of the file. 269 * @param md5Hash The MD5 hash of the file, null if not yet calculated. 270 * @param knownState The known state of the file from a hash database 271 * lookup, null if not yet looked up. 272 * @param parentPath The path of the parent of the file. 273 * 274 * @deprecated Do not make subclasses outside of this package. 275 */ 276 @Deprecated 277 @SuppressWarnings("deprecation") LayoutFile(SleuthkitCase db, long objId, String name, TSK_DB_FILES_TYPE_ENUM fileType, TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, String md5Hash, FileKnown knownState, String parentPath)278 protected LayoutFile(SleuthkitCase db, long objId, String name, 279 TSK_DB_FILES_TYPE_ENUM fileType, 280 TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, 281 TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, 282 long size, String md5Hash, FileKnown knownState, String parentPath) { 283 this(db, objId, db.getDataSourceObjectId(objId), name, fileType, dirType, metaType, dirFlag, metaFlags, size, 0L, 0L, 0L, 0L, md5Hash, knownState, parentPath, null); 284 } 285 } 286