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