1 /*
2  * Sleuth Kit Data Model
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.sql.ResultSet;
22 import java.sql.SQLException;
23 import java.sql.Statement;
24 import java.util.logging.Level;
25 import java.util.logging.Logger;
26 
27 /**
28  * A local/logical files and/or directories data source.
29  *
30  * NOTE: The DataSource interface is an emerging feature and at present is only
31  * useful for obtaining the object id and the device id, an ASCII-printable
32  * identifier for the device associated with the data source that is intended to
33  * be unique across multiple cases (e.g., a UUID). In the future, this interface
34  * will extend the Content interface and the AbstractDataSource will become an
35  * abstract superclass.
36  */
37 public class LocalFilesDataSource extends VirtualDirectory implements DataSource {
38 
39 	private final long objectId;
40 	private final String deviceId;
41 	private final String timezone;
42 
43 	private static final Logger LOGGER = Logger.getLogger(LocalFilesDataSource.class.getName());
44 
45 	/**
46 	 * Constructs a local/logical files and/or directories data source.
47 	 *
48 	 * @param db                 The case database.
49 	 * @param objId              The object id of the virtual directory.
50 	 * @param dataSourceObjectId The object id of the data source for the
51 	 *                           virtual directory; same as objId if the virtual
52 	 *                           directory is a data source.
53 	 * @param name               The name of the virtual directory.
54 	 * @param dirType            The TSK_FS_NAME_TYPE_ENUM for the virtual
55 	 *                           directory.
56 	 * @param deviceId           The device ID for the data source.
57 	 * @param metaType           The TSK_FS_META_TYPE_ENUM for the virtual
58 	 *                           directory.
59 	 * @param dirFlag            The TSK_FS_META_TYPE_ENUM for the virtual
60 	 *                           directory.
61 	 * @param metaFlags          The meta flags for the virtual directory.
62 	 * @param timezone           The timezone for the data source.
63 	 * @param md5Hash            The MD5 hash for the virtual directory.
64 	 * @param knownState         The known state for the virtual directory
65 	 * @param parentPath         The parent path for the virtual directory,
66 	 *                           should be "/" if the virtual directory is a
67 	 *                           data source.
68 	 */
LocalFilesDataSource(SleuthkitCase db, long objId, long dataSourceObjectId, String deviceId, String name, TskData.TSK_FS_NAME_TYPE_ENUM dirType, TskData.TSK_FS_META_TYPE_ENUM metaType, TskData.TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, String timezone, String md5Hash, TskData.FileKnown knownState, String parentPath)69 	public LocalFilesDataSource(SleuthkitCase db, long objId, long dataSourceObjectId, String deviceId, String name, TskData.TSK_FS_NAME_TYPE_ENUM dirType, TskData.TSK_FS_META_TYPE_ENUM metaType, TskData.TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, String timezone, String md5Hash, TskData.FileKnown knownState, String parentPath) {
70 		super(db, objId, dataSourceObjectId, name, dirType, metaType, dirFlag, metaFlags, md5Hash, knownState, parentPath);
71 		this.objectId = objId;
72 		this.deviceId = deviceId;
73 		this.timezone = timezone;
74 	}
75 
76 	/**
77 	 * Returns the VirtualDirectory instance. /deprecated LocalFilesDataSource
78 	 * is already a VirtualDirectory.
79 	 *
80 	 * @return This object.
81 	 *
82 	 * @deprecated LocalFilesDataSource is already a VirtualDirectory.
83 	 */
84 	@Deprecated
getRootDirectory()85 	public VirtualDirectory getRootDirectory() {
86 		return this;
87 	}
88 
89 	/**
90 	 * Gets the ASCII-printable identifier for the device associated with the
91 	 * data source. This identifier is intended to be unique across multiple
92 	 * cases (e.g., a UUID).
93 	 *
94 	 * @return The device id.
95 	 */
96 	@Override
getDeviceId()97 	public String getDeviceId() {
98 		return deviceId;
99 	}
100 
101 	/**
102 	 * Gets the time zone that was used to process the data source.
103 	 *
104 	 * @return The time zone.
105 	 */
106 	@Override
getTimeZone()107 	public String getTimeZone() {
108 		return timezone;
109 	}
110 
111 	/**
112 	 * Set the name for this data source.
113 	 *
114 	 * @param newName       The new name for the data source
115 	 *
116 	 * @throws TskCoreException Thrown if an error occurs while updating the database
117 	 */
118 	@Override
setDisplayName(String newName)119 	public void setDisplayName(String newName) throws TskCoreException {
120 		this.getSleuthkitCase().setFileName(newName, objectId);
121 	}
122 
123 	/**
124 	 * Gets the size of the contents of the data source in bytes. This size can
125 	 * change as archive files within the data source are expanded, files are
126 	 * carved, etc., and is different from the size of the data source as
127 	 * returned by Content.getSize, which is the size of the data source as a
128 	 * file.
129 	 *
130 	 * @param sleuthkitCase The sleuthkit case instance from which to make calls
131 	 *                      to the database.
132 	 *
133 	 * @return The size in bytes.
134 	 *
135 	 * @throws TskCoreException Thrown when there is an issue trying to retrieve
136 	 *                          data from the database.
137 	 */
138 	@Override
getContentSize(SleuthkitCase sleuthkitCase)139 	public long getContentSize(SleuthkitCase sleuthkitCase) throws TskCoreException {
140 		return getContentSize(sleuthkitCase, objectId);
141 	}
142 
143 	/**
144 	 * Gets the size of the contents of the data source in bytes given a data
145 	 * source object ID. This size can change as archive files within the data
146 	 * source are expanded, files are carved, etc., and is different from the
147 	 * size of the data source as returned by Content.getSize, which is the size
148 	 * of the data source as a file.
149 	 *
150 	 * @param sleuthkitCase The sleuthkit case instance from which to make calls
151 	 *                      to the database.
152 	 *
153 	 * @return The size in bytes.
154 	 *
155 	 * @throws TskCoreException Thrown when there is an issue trying to retrieve
156 	 *                          data from the database.
157 	 */
getContentSize(SleuthkitCase sleuthkitCase, long dataSourceObjId)158 	static long getContentSize(SleuthkitCase sleuthkitCase, long dataSourceObjId) throws TskCoreException {
159 		SleuthkitCase.CaseDbConnection connection;
160 		Statement statement = null;
161 		ResultSet resultSet = null;
162 		long contentSize = 0;
163 
164 		connection = sleuthkitCase.getConnection();
165 
166 		try {
167 			statement = connection.createStatement();
168 			resultSet = connection.executeQuery(statement, "SELECT SUM (size) FROM tsk_files WHERE tsk_files.data_source_obj_id = " + dataSourceObjId);
169 			if (resultSet.next()) {
170 				contentSize = resultSet.getLong("sum");
171 			}
172 		} catch (SQLException ex) {
173 			throw new TskCoreException(String.format("There was a problem while querying the database for size data for object ID %d.", dataSourceObjId), ex);
174 		} finally {
175 			closeResultSet(resultSet);
176 			closeStatement(statement);
177 			connection.close();
178 		}
179 
180 		return contentSize;
181 	}
182 
183 	/**
184 	 * Sets the acquisition details field in the case database.
185 	 *
186 	 * @param details The acquisition details
187 	 *
188 	 * @throws TskCoreException Thrown if the data can not be written
189 	 */
190 	@Override
setAcquisitionDetails(String details)191 	public void setAcquisitionDetails(String details) throws TskCoreException {
192 		getSleuthkitCase().setAcquisitionDetails(this, details);
193 	}
194 
195 	/**
196 	 * Gets the acquisition details field from the case database.
197 	 *
198 	 * @return The acquisition details
199 	 *
200 	 * @throws TskCoreException Thrown if the data can not be read
201 	 */
202 	@Override
getAcquisitionDetails()203 	public String getAcquisitionDetails() throws TskCoreException {
204 		return getSleuthkitCase().getAcquisitionDetails(this);
205 	}
206 
207 	/**
208 	 * Close a ResultSet.
209 	 *
210 	 * @param resultSet The ResultSet to be closed.
211 	 */
closeResultSet(ResultSet resultSet)212 	private static void closeResultSet(ResultSet resultSet) {
213 		if (resultSet != null) {
214 			try {
215 				resultSet.close();
216 			} catch (SQLException ex) {
217 				LOGGER.log(Level.SEVERE, "Error closing ResultSet", ex); //NON-NLS
218 			}
219 		}
220 	}
221 
222 	/**
223 	 * Close a Statement.
224 	 *
225 	 * @param statement The Statement to be closed.
226 	 */
closeStatement(Statement statement)227 	private static void closeStatement(Statement statement) {
228 		if (statement != null) {
229 			try {
230 				statement.close();
231 			} catch (SQLException ex) {
232 				LOGGER.log(Level.SEVERE, "Error closing Statement", ex); //NON-NLS
233 			}
234 		}
235 	}
236 }
237