Sleuth Kit Java Bindings (JNI)  4.8.0
Java bindings for using The Sleuth Kit
SleuthkitJNI.java
Go to the documentation of this file.
1 /*
2  * Sleuth Kit Data Model
3  *
4  * Copyright 2011-2018 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.io.BufferedReader;
22 import java.io.FileReader;
23 import java.io.IOException;
24 import java.text.DateFormat;
25 import java.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.GregorianCalendar;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.TimeZone;
35 import java.util.UUID;
36 import java.util.concurrent.locks.ReadWriteLock;
37 import java.util.concurrent.locks.ReentrantReadWriteLock;
39 
48 public class SleuthkitJNI {
49 
56  private static final ReadWriteLock tskLock = new ReentrantReadWriteLock();
57 
58  /*
59  * Loads the SleuthKit libraries.
60  */
61  static {
63  }
64 
69  private SleuthkitJNI() {
70  }
71 
75  private static class CaseHandles {
76  /*
77  * A SleuthKit image handle cache implemented as a mappng of
78  * concatenated image file paths to image handles.
79  */
80  private final Map<String, Long> imageHandleCache = new HashMap<>();
81 
82  /*
83  * A SleuthKit file system handles cache implemented as a mapping of
84  * image handles to image offset and file system handle pairs.
85  */
86  private final Map<Long, Map<Long, Long>> fsHandleCache = new HashMap<>();
87 
88  /*
89  * The collection of open file handles. We will only allow requests
90  * through to the C code if the file handle exists in this collection.
91  */
92  private final Set<Long> fileHandleCache = new HashSet<>();
93 
94  private final Map<Long, List<Long>> fileSystemToFileHandles = new HashMap<>();
95 
96  private final Map<Long, Map<Long, Long>> poolHandleCache = new HashMap<>();
97 
98  // The poolImgCache is only used to close the images later.
99  private final List<Long> poolImgCache = new ArrayList<>();
100 
101  /*
102  * Currently, our APFS code is not thread-safe and it is the only code
103  * that uses pools. To prevent crashes, we make any reads to a file system
104  * contained in a pool single-threaded. This cache keeps track of which
105  * open file system handles are contained in a pool so we can set the locks
106  * appropriately.
107  */
108  private final List<Long> poolFsList = new ArrayList<>();
109 
110  private CaseHandles() {
111  // Nothing to do here
112  }
113  }
114 
121  private static class HandleCache {
122 
123  /*
124  * A monitor used to guard access to cached Sleuthkit JNI handles.
125  */
126  private static final Object cacheLock = new Object();
127 
128  private static final Map<Long, CaseHandles> caseHandlesCache = new HashMap<>();
129 
130  private static final String INVALID_FILE_HANDLE = "Invalid file handle."; //NON-NLS
131 
132  /*
133  * Currently, our APFS code is not thread-safe and it is the only code
134  * that uses pools. To prevent crashes, we make any reads to a file system
135  * contained in a pool single-threaded. This cache keeps track of which
136  * open file handles are contained in a pool so we can set the locks
137  * appropriately.
138  *
139  * Access to this list should be guarded by cacheLock.
140  */
141  private static final List<Long> poolFileHandles = new ArrayList<>();
142 
148  private static void createCaseHandleCache(long caseDbPointer) {
149  caseHandlesCache.put(caseDbPointer, new CaseHandles());
150  }
151 
160  private static long getDefaultCaseDbPointer() throws TskCoreException {
161  synchronized (cacheLock) {
162  if (caseHandlesCache.keySet().size() > 1) {
163  throw new TskCoreException("Can not get default case handle with multiple open cases");
164  } else if (caseHandlesCache.keySet().isEmpty()) {
165  throw new TskCoreException("Can not get default case handle with no open case");
166  }
167 
168  return (caseHandlesCache.keySet().iterator().next());
169  }
170  }
171 
179  private static CaseHandles getCaseHandles(long caseDbPointer) {
180  synchronized (cacheLock) {
181  return caseHandlesCache.get(caseDbPointer);
182  }
183  }
184 
190  private static void removeCaseHandlesCache(long caseDbPointer) {
191  synchronized (cacheLock) {
192  if (caseHandlesCache.containsKey(caseDbPointer)) {
193  caseHandlesCache.get(caseDbPointer).fsHandleCache.clear();
194  caseHandlesCache.get(caseDbPointer).imageHandleCache.clear();
195  caseHandlesCache.get(caseDbPointer).fileHandleCache.clear();
196  caseHandlesCache.get(caseDbPointer).fileSystemToFileHandles.clear();
197  caseHandlesCache.get(caseDbPointer).poolHandleCache.clear();
198  caseHandlesCache.remove(caseDbPointer);
199  }
200  }
201  }
202 
210  private static boolean isImageInAnyCache(long imgHandle) {
211  synchronized (cacheLock) {
212  for (long caseDbPointer:caseHandlesCache.keySet()) {
213  if (caseHandlesCache.get(caseDbPointer).fsHandleCache.keySet().contains(imgHandle)) {
214  return true;
215  }
216  }
217  return false;
218  }
219  }
220 
227  private static void addFileHandle(long caseDbPointer, long fileHandle, long fsHandle) {
228  synchronized (cacheLock) {
229  // Add to collection of open file handles.
230  getCaseHandles(caseDbPointer).fileHandleCache.add(fileHandle);
231 
232  // Add to map of file system to file handles.
233  if (getCaseHandles(caseDbPointer).fileSystemToFileHandles.containsKey(fsHandle)) {
234  getCaseHandles(caseDbPointer).fileSystemToFileHandles.get(fsHandle).add(fileHandle);
235  } else {
236  getCaseHandles(caseDbPointer).fileSystemToFileHandles.put(fsHandle, new ArrayList<Long>(Arrays.asList(fileHandle)));
237  }
238  }
239  }
240 
247  private static void removeFileHandle(long fileHandle, SleuthkitCase skCase) {
248  synchronized (cacheLock) {
249  // Remove from collection of open file handles.
250  if (skCase != null) {
251  try {
252  getCaseHandles(skCase.getCaseDbPointer()).fileHandleCache.remove(fileHandle);
253  } catch (TskCoreException ex) {
254  // This exception will only occur if a file handle is closed as the case is being closed.
255  // The file will be closed by the case closing code.
256  }
257  } else {
258  // If we don't know what case the handle is from, delete the first one we find
259  for (long caseDbPointer:caseHandlesCache.keySet()) {
260  if (caseHandlesCache.get(caseDbPointer).fileHandleCache.contains(fileHandle)) {
261  caseHandlesCache.get(caseDbPointer).fileHandleCache.remove(fileHandle);
262  return;
263  }
264  }
265  }
266  }
267  }
268 
276  private static boolean isValidFileHandle(long fileHandle) {
277  synchronized (cacheLock) {
278  for (long caseDbPointer:caseHandlesCache.keySet()) {
279  if (caseHandlesCache.get(caseDbPointer).fileHandleCache.contains(fileHandle)) {
280  return true;
281  }
282  }
283  return false;
284  }
285  }
286 
287  private static void closeHandlesAndClearCache(long caseDbPointer) throws TskCoreException {
288  synchronized (cacheLock) {
289  /*
290  * Close any cached file system handles.
291  */
292  for (Map<Long, Long> imageToFsMap : getCaseHandles(caseDbPointer).fsHandleCache.values()) {
293  for (Long fsHandle : imageToFsMap.values()) {
294  // First close all open file handles for the file system.
295  if (getCaseHandles(caseDbPointer).fileSystemToFileHandles.containsKey(fsHandle)) {
296  for (Long fileHandle : getCaseHandles(caseDbPointer).fileSystemToFileHandles.get(fsHandle)) {
297  // Update the cache of file handles contained in pools
298  if (poolFileHandles.contains(fileHandle)) {
299  poolFileHandles.remove(fileHandle);
300  }
301  closeFile(fileHandle);
302  }
303  }
304  // Then close the file system handle.
305  closeFsNat(fsHandle);
306  }
307  }
308 
309  /*
310  * Clear out the list of pool file systems.
311  */
312  getCaseHandles(caseDbPointer).poolFsList.clear();
313 
314  /*
315  * Close any cached pools
316  */
317  for (Long imgHandle : getCaseHandles(caseDbPointer).poolHandleCache.keySet()) {
318  for (Long poolHandle : getCaseHandles(caseDbPointer).poolHandleCache.get(imgHandle).values()) {
319  closePoolNat(poolHandle);
320  }
321  }
322 
323  /*
324  * Close any open pool images
325  */
326  for (Long imageHandle : getCaseHandles(caseDbPointer).poolImgCache) {
327  closeImgNat(imageHandle);
328  }
329 
330  /*
331  * Close any cached image handles.
332  */
333  for (Long imageHandle : getCaseHandles(caseDbPointer).imageHandleCache.values()) {
334  closeImgNat(imageHandle);
335  }
336 
337  removeCaseHandlesCache(caseDbPointer);
338  }
339 
340  }
341  }
342 
347  public static class CaseDbHandle {
348 
349  /*
350  * A pointer to a TskCaseDb object.
351  */
352  private final long caseDbPointer;
353 
360  private CaseDbHandle(long caseDbPointer) {
361  this.caseDbPointer = caseDbPointer;
362  HandleCache.createCaseHandleCache(caseDbPointer);
363  }
364 
370  long getCaseDbPointer() {
371  return caseDbPointer;
372  }
373 
380  void free() throws TskCoreException {
381  tskLock.writeLock().lock();
382  try {
383  HandleCache.closeHandlesAndClearCache(caseDbPointer);
384  SleuthkitJNI.closeCaseDbNat(caseDbPointer);
385  } finally {
386  tskLock.writeLock().unlock();
387  }
388  }
389 
413  long addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone, SleuthkitCase skCase) throws TskCoreException {
414  try {
415  long tskAutoDbPointer = initializeAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), false, false, false);
416  runOpenAndAddImgNat(tskAutoDbPointer, UUID.randomUUID().toString(), imageFilePaths.toArray(new String[0]), imageFilePaths.size(), timeZone);
417  long id = commitAddImgNat(tskAutoDbPointer);
418  skCase.addDataSourceToHasChildrenMap();
419  return id;
420  } catch (TskDataException ex) {
421  throw new TskCoreException("Error adding image to case database", ex);
422  }
423  }
424 
441  AddImageProcess initAddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans, String imageCopyPath, SleuthkitCase skCase) {
442  return new AddImageProcess(timeZone, addUnallocSpace, skipFatFsOrphans, imageCopyPath, skCase);
443  }
444 
449  public class AddImageProcess {
450 
451  private final String timeZone;
452  private final boolean addUnallocSpace;
453  private final boolean skipFatFsOrphans;
454  private final String imageWriterPath;
455  private volatile long tskAutoDbPointer;
456  private boolean isCanceled;
457  private final SleuthkitCase skCase;
458 
472  private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans, String imageWriterPath, SleuthkitCase skCase) {
473  this.timeZone = timeZone;
474  this.addUnallocSpace = addUnallocSpace;
475  this.skipFatFsOrphans = skipFatFsOrphans;
476  this.imageWriterPath = imageWriterPath;
477  tskAutoDbPointer = 0;
478  this.isCanceled = false;
479  this.skCase = skCase;
480  }
481 
500  public void run(String deviceId, String[] imageFilePaths, int sectorSize) throws TskCoreException, TskDataException {
501  getTSKReadLock();
502  try {
503  long imageHandle = 0;
504 
505  synchronized (this) {
506  if (0 != tskAutoDbPointer) {
507  throw new TskCoreException("Add image process already started");
508  }
509  if (!isCanceled) { //with isCanceled being guarded by this it will have the same value everywhere in this synchronized block
510  imageHandle = openImage(imageFilePaths, sectorSize, false, caseDbPointer);
511  tskAutoDbPointer = initAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), addUnallocSpace, skipFatFsOrphans);
512  }
513  if (0 == tskAutoDbPointer) {
514  throw new TskCoreException("initAddImgNat returned a NULL TskAutoDb pointer");
515  }
516  }
517  if (imageHandle != 0) {
518  runAddImgNat(tskAutoDbPointer, deviceId, imageHandle, timeZone, imageWriterPath);
519  }
520  } finally {
521  releaseTSKReadLock();
522  }
523  }
524 
534  public synchronized void stop() throws TskCoreException {
535  getTSKReadLock();
536  try {
537  isCanceled = true;
538  if (tskAutoDbPointer != 0) {
539  stopAddImgNat(tskAutoDbPointer);
540  }
541  } finally {
542  releaseTSKReadLock();
543  }
544  }
545 
553  public synchronized void revert() throws TskCoreException {
554  getTSKReadLock();
555  try {
556  if (tskAutoDbPointer == 0) {
557  throw new TskCoreException("AddImgProcess::revert: AutoDB pointer is NULL");
558  }
559 
560  revertAddImgNat(tskAutoDbPointer);
561  // the native code deleted the object
562  tskAutoDbPointer = 0;
563  } finally {
564  releaseTSKReadLock();
565  }
566  }
567 
577  public synchronized long commit() throws TskCoreException {
578  getTSKReadLock();
579  try {
580  if (tskAutoDbPointer == 0) {
581  throw new TskCoreException("AddImgProcess::commit: AutoDB pointer is NULL");
582  }
583 
584  long id = commitAddImgNat(tskAutoDbPointer);
585 
586  skCase.addDataSourceToHasChildrenMap();
587 
588  // the native code deleted the object
589  tskAutoDbPointer = 0;
590  return id;
591  } finally {
592  releaseTSKReadLock();
593  }
594  }
595 
602  public synchronized String currentDirectory() {
603  return tskAutoDbPointer == 0 ? "" : getCurDirNat(tskAutoDbPointer); //NON-NLS
604  }
605 
621  @Deprecated
622  public void run(String[] imageFilePaths) throws TskCoreException, TskDataException {
623  run(null, imageFilePaths, 0);
624  }
625 
643  public void run(String deviceId, String[] imageFilePaths) throws TskCoreException, TskDataException {
644  run(deviceId, imageFilePaths, 0);
645  }
646  }
647 
648  }
649 
661  static CaseDbHandle newCaseDb(String path) throws TskCoreException {
662  return new CaseDbHandle(newCaseDbNat(path));
663  }
664 
677  static CaseDbHandle newCaseDb(String databaseName, CaseDbConnectionInfo info) throws TskCoreException {
678  return new CaseDbHandle(newCaseDbMultiNat(info.getHost(), info.getPort(), info.getUserName(), info.getPassword(), info.getDbType().ordinal(), databaseName));
679  }
680 
692  static CaseDbHandle openCaseDb(String path) throws TskCoreException {
693  return new CaseDbHandle(openCaseDbNat(path));
694  }
695 
708  static CaseDbHandle openCaseDb(String databaseName, CaseDbConnectionInfo info) throws TskCoreException {
709  return new CaseDbHandle(openCaseDbMultiNat(info.getHost(), info.getPort(), info.getUserName(), info.getPassword(), info.getDbType().ordinal(), databaseName));
710  }
711 
717  public static String getVersion() {
718  return getVersionNat();
719  }
720 
726  public static void startVerboseLogging(String logPath) {
727  startVerboseLoggingNat(logPath);
728  }
729 
741  public static long openImage(String[] imageFiles, SleuthkitCase skCase) throws TskCoreException {
742  if (skCase == null) {
743  throw new TskCoreException("SleuthkitCase can not be null");
744  }
745  return openImage(imageFiles, 0, true, skCase.getCaseDbPointer());
746  }
747 
761  public static long openImage(String[] imageFiles, int sSize, SleuthkitCase skCase) throws TskCoreException {
762  if (skCase == null) {
763  throw new TskCoreException("SleuthkitCase can not be null");
764  }
765  return openImage(imageFiles, sSize, true, skCase.getCaseDbPointer());
766  }
767 
785  private static long openImage(String[] imageFiles, int sSize, boolean useCache, Long caseDbPointer) throws TskCoreException {
786 
787  getTSKReadLock();
788  try {
789  long imageHandle;
790 
791  StringBuilder keyBuilder = new StringBuilder();
792  for (int i = 0; i < imageFiles.length; ++i) {
793  keyBuilder.append(imageFiles[i]);
794  }
795  final String imageKey = keyBuilder.toString();
796 
797  synchronized (HandleCache.cacheLock) {
798  Long nonNullCaseDbPointer = caseDbPointer;
799  if (nonNullCaseDbPointer == null) {
800  nonNullCaseDbPointer = HandleCache.getDefaultCaseDbPointer();
801  }
802 
803  // If we're getting a fresh copy and an image with this path is already
804  // in the cache, move the existing cache reference so it won't be used by
805  // any subsequent calls to openImage but will still be valid if any objects
806  // have it cached. This happens in the case where the user adds the same data
807  // source twice (see JIRA-5868).
808  if (!useCache && HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.containsKey(imageKey)) {
809  long tempImageHandle = HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.get(imageKey);
810 
811  // Store the old image handle in a fake path. This way it will no longer be found but will
812  // still be valid and the image and its file systems will be closed with the case.
813  String newPath = "Image_" + UUID.randomUUID().toString();
814  HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.put(newPath, tempImageHandle);
815  HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.remove(imageKey);
816  }
817 
818  if (useCache && HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.containsKey(imageKey)) //get from cache
819  {
820  imageHandle = HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.get(imageKey);
821  } else {
822  //open new handle and cache it
823  imageHandle = openImgNat(imageFiles, imageFiles.length, sSize);
824  HandleCache.getCaseHandles(nonNullCaseDbPointer).fsHandleCache.put(imageHandle, new HashMap<>());
825  HandleCache.getCaseHandles(nonNullCaseDbPointer).imageHandleCache.put(imageKey, imageHandle);
826  }
827  }
828  return imageHandle;
829  } finally {
830  releaseTSKReadLock();
831  }
832  }
833 
846  public static long openVs(long imgHandle, long vsOffset) throws TskCoreException {
847  getTSKReadLock();
848  try {
849  if(! imgHandleIsValid(imgHandle)) {
850  throw new TskCoreException("Image handle " + imgHandle + " is closed");
851  }
852  return openVsNat(imgHandle, vsOffset);
853  } finally {
854  releaseTSKReadLock();
855  }
856  }
857 
858  //get pointers
870  public static long openVsPart(long vsHandle, long volId) throws TskCoreException {
871  getTSKReadLock();
872  try {
873  //returned long is ptr to vs Handle object in tsk
874  return openVolNat(vsHandle, volId);
875  } finally {
876  releaseTSKReadLock();
877  }
878  }
879 
891  static long openPool(long imgHandle, long offset, SleuthkitCase skCase) throws TskCoreException {
892  getTSKReadLock();
893  try {
894  if(! imgHandleIsValid(imgHandle)) {
895  throw new TskCoreException("Image handle " + imgHandle + " is closed");
896  }
897 
898  synchronized (HandleCache.cacheLock) {
899  long caseDbPointer;
900  if (skCase == null) {
901  caseDbPointer = HandleCache.getDefaultCaseDbPointer();
902  } else {
903  caseDbPointer = skCase.getCaseDbPointer();
904  }
905 
906  // If a pool handle cache for this image does not exist, make one
907  if (! HandleCache.getCaseHandles(caseDbPointer).poolHandleCache.containsKey(imgHandle)) {
908  HandleCache.getCaseHandles(caseDbPointer).poolHandleCache.put(imgHandle, new HashMap<>());
909  }
910 
911  // Get the pool handle cache for this image
912  Map<Long, Long> poolCacheForImage = HandleCache.getCaseHandles(caseDbPointer).poolHandleCache.get(imgHandle);
913 
914  if (poolCacheForImage.containsKey(offset)) {
915  return poolCacheForImage.get(offset);
916  } else {
917  //returned long is ptr to pool Handle object in tsk
918  long poolHandle = openPoolNat(imgHandle, offset);
919  poolCacheForImage.put(offset, poolHandle);
920  return poolHandle;
921  }
922  }
923  } finally {
924  releaseTSKReadLock();
925  }
926  }
927 
941  public static long openFs(long imgHandle, long fsOffset, SleuthkitCase skCase) throws TskCoreException {
942  getTSKReadLock();
943  try {
944  long fsHandle;
945  synchronized (HandleCache.cacheLock) {
946  long caseDbPointer;
947  if (skCase == null) {
948  caseDbPointer = HandleCache.getDefaultCaseDbPointer();
949  } else {
950  caseDbPointer = skCase.getCaseDbPointer();
951  }
952  final Map<Long, Long> imgOffSetToFsHandle = HandleCache.getCaseHandles(caseDbPointer).fsHandleCache.get(imgHandle);
953  if (imgOffSetToFsHandle == null) {
954  throw new TskCoreException("Missing image offset to file system handle cache for image handle " + imgHandle);
955  }
956  if (imgOffSetToFsHandle.containsKey(fsOffset)) {
957  //return cached
958  fsHandle = imgOffSetToFsHandle.get(fsOffset);
959  } else {
960  fsHandle = openFsNat(imgHandle, fsOffset);
961  //cache it
962  imgOffSetToFsHandle.put(fsOffset, fsHandle);
963  }
964  }
965  return fsHandle;
966  } finally {
967  releaseTSKReadLock();
968  }
969  }
970 
987  static long openFsPool(long imgHandle, long fsOffset, long poolHandle, long poolBlock, SleuthkitCase skCase) throws TskCoreException {
988  /*
989  * Currently, our APFS code is not thread-safe and it is the only code
990  * that uses pools. To prevent crashes, we make any reads to a file system
991  * contained in a pool single-threaded.
992  */
993  getTSKWriteLock();
994  try {
995  long fsHandle;
996  synchronized (HandleCache.cacheLock) {
997  long caseDbPointer;
998  if (skCase == null) {
999  caseDbPointer = HandleCache.getDefaultCaseDbPointer();
1000  } else {
1001  caseDbPointer = skCase.getCaseDbPointer();
1002  }
1003  final Map<Long, Long> imgOffSetToFsHandle = HandleCache.getCaseHandles(caseDbPointer).fsHandleCache.get(imgHandle);
1004  if (imgOffSetToFsHandle == null) {
1005  throw new TskCoreException("Missing image offset to file system handle cache for image handle " + imgHandle);
1006  }
1007 
1008  if (imgOffSetToFsHandle.containsKey(poolBlock)) {
1009  //return cached
1010  fsHandle = imgOffSetToFsHandle.get(poolBlock);
1011  } else {
1012  long poolImgHandle = getImgInfoForPoolNat(poolHandle, poolBlock);
1013  HandleCache.getCaseHandles(caseDbPointer).poolImgCache.add(poolImgHandle);
1014  fsHandle = openFsNat(poolImgHandle, fsOffset);
1015  //cache it
1016  imgOffSetToFsHandle.put(poolBlock, fsHandle);
1017  HandleCache.getCaseHandles(caseDbPointer).poolFsList.add(fsHandle);
1018  }
1019  }
1020  return fsHandle;
1021  } finally {
1022  releaseTSKWriteLock();
1023  }
1024  }
1025 
1040  public static long openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId, SleuthkitCase skCase) throws TskCoreException {
1041  /*
1042  * NOTE: previously attrId used to be stored in AbstractFile as (signed)
1043  * short even though it is stored as uint16 in TSK. In extremely rare
1044  * occurrences attrId can be larger than what a signed short can hold
1045  * (2^15). Changes were made to AbstractFile to store attrId as integer.
1046  * However, a depricated method still exists in AbstractFile to get
1047  * attrId as short. In that method we convert attribute ids that are
1048  * larger than 32K to a negative number. Therefore if encountered, we
1049  * need to convert negative attribute id to uint16 which is what TSK is
1050  * using to store attribute id.
1051  */
1052  boolean withinPool = false;
1053  synchronized (HandleCache.cacheLock) {
1054  long caseDbPointer;
1055  if (skCase == null) {
1056  caseDbPointer = HandleCache.getDefaultCaseDbPointer();
1057  } else {
1058  caseDbPointer = skCase.getCaseDbPointer();
1059  }
1060  if (HandleCache.getCaseHandles(caseDbPointer).poolFsList.contains(fsHandle)) {
1061  withinPool = true;
1062  }
1063  }
1064 
1065  /*
1066  * The current APFS code is not thread-safe. To compensate, we make any
1067  * reads to the APFS pool single-threaded by obtaining a write
1068  * lock instead of a read lock.
1069  */
1070  if (withinPool) {
1071  getTSKWriteLock();
1072  } else {
1073  getTSKReadLock();
1074  }
1075  try {
1076  long fileHandle = openFileNat(fsHandle, fileId, attrType.getValue(), convertSignedToUnsigned(attrId));
1077  synchronized (HandleCache.cacheLock) {
1078  long caseDbPointer;
1079  if (skCase == null) {
1080  caseDbPointer = HandleCache.getDefaultCaseDbPointer();
1081  } else {
1082  caseDbPointer = skCase.getCaseDbPointer();
1083  }
1084  HandleCache.addFileHandle(caseDbPointer, fileHandle, fsHandle);
1085 
1086  // If this file is in a pool file system, record it so the locks
1087  // can be set appropriately when reading it.
1088  if (withinPool) {
1089  HandleCache.poolFileHandles.add(fileHandle);
1090  }
1091  }
1092  return fileHandle;
1093  } finally {
1094  if (withinPool) {
1095  releaseTSKWriteLock();
1096  } else {
1097  releaseTSKReadLock();
1098  }
1099  }
1100  }
1101 
1109  private static int convertSignedToUnsigned(int val) {
1110  if (val >= 0) {
1111  return val;
1112  }
1113 
1114  return val & 0xffff; // convert negative value to positive value
1115  }
1116 
1122  private static boolean imgHandleIsValid(long imgHandle) {
1123  synchronized(HandleCache.cacheLock) {
1124  return HandleCache.isImageInAnyCache(imgHandle);
1125  }
1126  }
1127 
1128  //do reads
1143  public static int readImg(long imgHandle, byte[] readBuffer, long offset, long len) throws TskCoreException {
1144  getTSKReadLock();
1145  try {
1146  if(! imgHandleIsValid(imgHandle)) {
1147  throw new TskCoreException("Image handle " + imgHandle + " is closed");
1148  }
1149  //returned byte[] is the data buffer
1150  return readImgNat(imgHandle, readBuffer, offset, len);
1151  } finally {
1152  releaseTSKReadLock();
1153  }
1154  }
1155 
1170  public static int readVs(long vsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException {
1171  getTSKReadLock();
1172  try {
1173  return readVsNat(vsHandle, readBuffer, offset, len);
1174  } finally {
1175  releaseTSKReadLock();
1176  }
1177  }
1178 
1191  static int readPool(long poolHandle, byte[] readBuffer, long offset, long len) throws TskCoreException {
1192  getTSKReadLock();
1193  try {
1194  return readPoolNat(poolHandle, readBuffer, offset, len);
1195  } finally {
1196  releaseTSKReadLock();
1197  }
1198  }
1199 
1214  public static int readVsPart(long volHandle, byte[] readBuffer, long offset, long len) throws TskCoreException {
1215  getTSKReadLock();
1216  try {
1217  //returned byte[] is the data buffer
1218  return readVolNat(volHandle, readBuffer, offset, len);
1219  } finally {
1220  releaseTSKReadLock();
1221  }
1222  }
1223 
1238  public static int readFs(long fsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException {
1239  getTSKReadLock();
1240  try {
1241  //returned byte[] is the data buffer
1242  return readFsNat(fsHandle, readBuffer, offset, len);
1243  } finally {
1244  releaseTSKReadLock();
1245  }
1246  }
1247 
1252  private enum TSK_FS_FILE_READ_OFFSET_TYPE_ENUM {
1253  START_OF_FILE(0),
1254  START_OF_SLACK(1);
1255 
1256  private final int val;
1257 
1258  TSK_FS_FILE_READ_OFFSET_TYPE_ENUM(int val) {
1259  this.val = val;
1260  }
1261 
1262  int getValue() {
1263  return val;
1264  }
1265  }
1266 
1281  public static int readFile(long fileHandle, byte[] readBuffer, long offset, long len) throws TskCoreException {
1282  boolean withinPool = false;
1283  synchronized (HandleCache.cacheLock) {
1284  if (HandleCache.poolFileHandles.contains(fileHandle)) {
1285  withinPool = true;
1286  }
1287  }
1288 
1289  /*
1290  * The current APFS code is not thread-safe. To compensate, we make any
1291  * reads to the APFS pool single-threaded by obtaining a write
1292  * lock instead of a read lock.
1293  */
1294  if (withinPool) {
1295  getTSKWriteLock();
1296  } else {
1297  getTSKReadLock();
1298  }
1299  try {
1300  if (!HandleCache.isValidFileHandle(fileHandle)) {
1301  throw new TskCoreException(HandleCache.INVALID_FILE_HANDLE);
1302  }
1303 
1304  return readFileNat(fileHandle, readBuffer, offset, TSK_FS_FILE_READ_OFFSET_TYPE_ENUM.START_OF_FILE.getValue(), len);
1305  } finally {
1306  if (withinPool) {
1307  releaseTSKWriteLock();
1308  } else {
1309  releaseTSKReadLock();
1310  }
1311  }
1312  }
1313 
1328  public static int readFileSlack(long fileHandle, byte[] readBuffer, long offset, long len) throws TskCoreException {
1329  getTSKReadLock();
1330  try {
1331  if (!HandleCache.isValidFileHandle(fileHandle)) {
1332  throw new TskCoreException(HandleCache.INVALID_FILE_HANDLE);
1333  }
1334 
1335  return readFileNat(fileHandle, readBuffer, offset, TSK_FS_FILE_READ_OFFSET_TYPE_ENUM.START_OF_SLACK.getValue(), len);
1336  } finally {
1337  releaseTSKReadLock();
1338  }
1339  }
1340 
1351  public static List<String> getFileMetaDataText(long fileHandle) throws TskCoreException {
1352  getTSKReadLock();
1353  try {
1354  if (!HandleCache.isValidFileHandle(fileHandle)) {
1355  throw new TskCoreException(HandleCache.INVALID_FILE_HANDLE);
1356  }
1357 
1358  try {
1359  java.io.File tmp = java.io.File.createTempFile("tsk", ".txt");
1360 
1361  saveFileMetaDataTextNat(fileHandle, tmp.getAbsolutePath());
1362 
1363  FileReader fr = new FileReader(tmp.getAbsolutePath());
1364  BufferedReader textReader = new BufferedReader(fr);
1365 
1366  List<String> lines = new ArrayList<String>();
1367  while (true) {
1368  String line = textReader.readLine();
1369  if (line == null) {
1370  break;
1371  }
1372  lines.add(line);
1373  }
1374  textReader.close();
1375  fr.close();
1376  tmp.delete();
1377  return lines;
1378  } catch (IOException ex) {
1379  throw new TskCoreException("Error reading istat output: " + ex.getLocalizedMessage());
1380  }
1381  } finally {
1382  releaseTSKReadLock();
1383  }
1384  }
1385 
1391  public static void closeFile(long fileHandle) {
1392  closeFile(fileHandle, null);
1393  }
1394 
1401  public static void closeFile(long fileHandle, SleuthkitCase skCase) {
1402  boolean withinPool = false;
1403  synchronized (HandleCache.cacheLock) {
1404  if (HandleCache.poolFileHandles.contains(fileHandle)) {
1405  withinPool = true;
1406  }
1407  }
1408 
1409  /*
1410  * The current APFS code is not thread-safe. To compensate, we make any
1411  * reads to the APFS pool single-threaded by obtaining a write
1412  * lock instead of a read lock.
1413  */
1414  if (withinPool) {
1415  getTSKWriteLock();
1416  } else {
1417  getTSKReadLock();
1418  }
1419  try {
1420  synchronized (HandleCache.cacheLock) {
1421  if (!HandleCache.isValidFileHandle(fileHandle)) {
1422  // File handle is not open so this is a no-op.
1423  return;
1424  }
1425  closeFileNat(fileHandle);
1426  HandleCache.removeFileHandle(fileHandle, skCase);
1427  if (HandleCache.poolFileHandles.contains(fileHandle)) {
1428  HandleCache.poolFileHandles.remove(fileHandle);
1429  }
1430  }
1431  } finally {
1432  if (withinPool) {
1433  releaseTSKWriteLock();
1434  } else {
1435  releaseTSKReadLock();
1436  }
1437  }
1438  }
1439 
1447  public static void createLookupIndexForHashDatabase(int dbHandle) throws TskCoreException {
1448  hashDbCreateIndexNat(dbHandle);
1449  }
1450 
1460  public static boolean hashDatabaseHasLookupIndex(int dbHandle) throws TskCoreException {
1461  return hashDbIndexExistsNat(dbHandle);
1462  }
1463 
1474  public static boolean hashDatabaseCanBeReindexed(int dbHandle) throws TskCoreException {
1475  return hashDbIsReindexableNat(dbHandle);
1476  }
1477 
1487  public static String getHashDatabasePath(int dbHandle) throws TskCoreException {
1488  return hashDbPathNat(dbHandle);
1489  }
1490 
1500  public static String getHashDatabaseIndexPath(int dbHandle) throws TskCoreException {
1501  return hashDbIndexPathNat(dbHandle);
1502  }
1503 
1510  public static int openHashDatabase(String path) throws TskCoreException {
1511  return hashDbOpenNat(path);
1512  }
1513 
1523  public static int createHashDatabase(String path) throws TskCoreException {
1524  return hashDbNewNat(path);
1525  }
1526 
1533  public static void closeAllHashDatabases() throws TskCoreException {
1534  hashDbCloseAll();
1535  }
1536 
1546  public static void closeHashDatabase(int dbHandle) throws TskCoreException {
1547  hashDbClose(dbHandle);
1548  }
1549 
1559  public static String getHashDatabaseDisplayName(int dbHandle) throws TskCoreException {
1560  return hashDbGetDisplayName(dbHandle);
1561  }
1562 
1573  public static boolean lookupInHashDatabase(String hash, int dbHandle) throws TskCoreException {
1574  return hashDbLookup(hash, dbHandle);
1575  }
1576 
1588  public static HashHitInfo lookupInHashDatabaseVerbose(String hash, int dbHandle) throws TskCoreException {
1589  return hashDbLookupVerbose(hash, dbHandle);
1590  }
1591 
1604  public static void addToHashDatabase(String filename, String md5, String sha1, String sha256, String comment, int dbHandle) throws TskCoreException {
1605  hashDbAddEntryNat(filename, md5, sha1, sha256, comment, dbHandle);
1606  }
1607 
1608  public static void addToHashDatabase(List<HashEntry> hashes, int dbHandle) throws TskCoreException {
1609  hashDbBeginTransactionNat(dbHandle);
1610  try {
1611  for (HashEntry entry : hashes) {
1612  hashDbAddEntryNat(entry.getFileName(), entry.getMd5Hash(), entry.getSha1Hash(), entry.getSha256Hash(), entry.getComment(), dbHandle);
1613  }
1614  hashDbCommitTransactionNat(dbHandle);
1615  } catch (TskCoreException ex) {
1616  try {
1617  hashDbRollbackTransactionNat(dbHandle);
1618  } catch (TskCoreException ex2) {
1619  ex2.initCause(ex);
1620  throw ex2;
1621  }
1622  throw ex;
1623  }
1624  }
1625 
1626  public static boolean isUpdateableHashDatabase(int dbHandle) throws TskCoreException {
1627  return hashDbIsUpdateableNat(dbHandle);
1628  }
1629 
1630  public static boolean hashDatabaseIsIndexOnly(int dbHandle) throws TskCoreException {
1631  return hashDbIsIdxOnlyNat(dbHandle);
1632  }
1633 
1643  private static String timezoneLongToShort(String timezoneLongForm) {
1644  if (timezoneLongForm == null || timezoneLongForm.isEmpty()) {
1645  return "";
1646  }
1647 
1648  String timezoneShortForm;
1649  TimeZone zone = TimeZone.getTimeZone(timezoneLongForm);
1650  int offset = zone.getRawOffset() / 1000;
1651  int hour = offset / 3600;
1652  int min = (offset % 3600) / 60;
1653  DateFormat dfm = new SimpleDateFormat("z");
1654  dfm.setTimeZone(zone);
1655  boolean hasDaylight = zone.useDaylightTime();
1656  String first = dfm.format(new GregorianCalendar(2010, 1, 1).getTime()).substring(0, 3); // make it only 3 letters code
1657  String second = dfm.format(new GregorianCalendar(2011, 6, 6).getTime()).substring(0, 3); // make it only 3 letters code
1658  int mid = hour * -1;
1659  timezoneShortForm = first + Integer.toString(mid);
1660  if (min != 0) {
1661  timezoneShortForm = timezoneShortForm + ":" + (min < 10 ? "0" : "") + Integer.toString(min);
1662  }
1663  if (hasDaylight) {
1664  timezoneShortForm += second;
1665  }
1666  return timezoneShortForm;
1667  }
1668 
1679  public static int finishImageWriter(long imgHandle) throws TskCoreException {
1680  getTSKReadLock();
1681  try {
1682  if(! imgHandleIsValid(imgHandle)) {
1683  throw new TskCoreException("Image handle " + imgHandle + " is closed");
1684  }
1685  return finishImageWriterNat(imgHandle);
1686  } finally {
1687  releaseTSKReadLock();
1688  }
1689  }
1690 
1698  public static int getFinishImageProgress(long imgHandle) {
1699  getTSKReadLock();
1700  try {
1701  if (imgHandleIsValid(imgHandle)) {
1702  return getFinishImageProgressNat(imgHandle);
1703  } else {
1704  return 0;
1705  }
1706  } finally {
1707  releaseTSKReadLock();
1708  }
1709  }
1710 
1716  public static void cancelFinishImage(long imgHandle) {
1717  getTSKReadLock();
1718  try {
1719  if (imgHandleIsValid(imgHandle)) {
1720  cancelFinishImageNat(imgHandle);
1721  }
1722  } finally {
1723  releaseTSKReadLock();
1724  }
1725  }
1726 
1738  public static long findDeviceSize(String devPath) throws TskCoreException {
1739  return findDeviceSizeNat(devPath);
1740  }
1741 
1742  public static boolean isImageSupported(String imagePath) {
1743  return isImageSupportedNat(imagePath);
1744  }
1745 
1750  private static void getTSKReadLock() {
1751  tskLock.readLock().lock();
1752  }
1753 
1757  private static void releaseTSKReadLock() {
1758  tskLock.readLock().unlock();
1759  }
1760 
1768  private static void getTSKWriteLock() {
1769  tskLock.writeLock().lock();
1770  }
1771 
1775  private static void releaseTSKWriteLock() {
1776  tskLock.writeLock().unlock();
1777  }
1778 
1779  //free pointers
1786  @Deprecated
1787  public static void closeImg(long imgHandle) {
1788  //closeImgNat(imgHandle);
1789  }
1790 
1796  @Deprecated
1797  public static void closeVs(long vsHandle) {
1798  // closeVsNat(vsHandle); TODO JIRA-3829
1799  }
1800 
1807  @Deprecated
1808  public static void closeFs(long fsHandle) {
1809  //closeFsNat(fsHandle);
1810  }
1811 
1823  @Deprecated
1824  public static long openImage(String[] imageFiles) throws TskCoreException {
1825 
1826  return openImage(imageFiles, 0, true, null);
1827  }
1828 
1842  @Deprecated
1843  public static long openImage(String[] imageFiles, int sSize) throws TskCoreException {
1844  return openImage(imageFiles, sSize, true, null);
1845  }
1846 
1847 
1861  @Deprecated
1862  public static long openFs(long imgHandle, long fsOffset) throws TskCoreException {
1863  return openFs(imgHandle, fsOffset, null);
1864  }
1865 
1880  @Deprecated
1881  public static long openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId) throws TskCoreException {
1882  return openFile(fsHandle, fileId, attrType, attrId, null);
1883  }
1884 
1885 
1886  private static native String getVersionNat();
1887 
1888  private static native void startVerboseLoggingNat(String logPath);
1889 
1890  private static native long newCaseDbNat(String dbPath) throws TskCoreException;
1891 
1892  private static native long newCaseDbMultiNat(String hostNameOrIP, String portNumber, String userName, String password, int dbTypeOrdinal, String databaseName);
1893 
1894  private static native long openCaseDbMultiNat(String hostNameOrIP, String portNumber, String userName, String password, int dbTypeOrdinal, String databaseName);
1895 
1896  private static native long openCaseDbNat(String path) throws TskCoreException;
1897 
1898  private static native void closeCaseDbNat(long db) throws TskCoreException;
1899 
1900  private static native int hashDbOpenNat(String hashDbPath) throws TskCoreException;
1901 
1902  private static native int hashDbNewNat(String hashDbPath) throws TskCoreException;
1903 
1904  private static native int hashDbBeginTransactionNat(int dbHandle) throws TskCoreException;
1905 
1906  private static native int hashDbCommitTransactionNat(int dbHandle) throws TskCoreException;
1907 
1908  private static native int hashDbRollbackTransactionNat(int dbHandle) throws TskCoreException;
1909 
1910  private static native int hashDbAddEntryNat(String filename, String hashMd5, String hashSha1, String hashSha256, String comment, int dbHandle) throws TskCoreException;
1911 
1912  private static native boolean hashDbIsUpdateableNat(int dbHandle);
1913 
1914  private static native boolean hashDbIsReindexableNat(int dbHandle);
1915 
1916  private static native String hashDbPathNat(int dbHandle);
1917 
1918  private static native String hashDbIndexPathNat(int dbHandle);
1919 
1920  private static native String hashDbGetDisplayName(int dbHandle) throws TskCoreException;
1921 
1922  private static native void hashDbCloseAll() throws TskCoreException;
1923 
1924  private static native void hashDbClose(int dbHandle) throws TskCoreException;
1925 
1926  private static native void hashDbCreateIndexNat(int dbHandle) throws TskCoreException;
1927 
1928  private static native boolean hashDbIndexExistsNat(int dbHandle) throws TskCoreException;
1929 
1930  private static native boolean hashDbIsIdxOnlyNat(int dbHandle) throws TskCoreException;
1931 
1932  private static native boolean hashDbLookup(String hash, int dbHandle) throws TskCoreException;
1933 
1934  private static native HashHitInfo hashDbLookupVerbose(String hash, int dbHandle) throws TskCoreException;
1935 
1936  private static native long initAddImgNat(long db, String timezone, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException;
1937 
1938  private static native long initializeAddImgNat(long db, String timezone, boolean addFileSystems, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException;
1939 
1940  private static native void runOpenAndAddImgNat(long process, String deviceId, String[] imgPath, int splits, String timezone) throws TskCoreException, TskDataException;
1941 
1942  private static native void runAddImgNat(long process, String deviceId, long a_img_info, String timeZone, String imageWriterPath) throws TskCoreException, TskDataException;
1943 
1944  private static native void stopAddImgNat(long process) throws TskCoreException;
1945 
1946  private static native void revertAddImgNat(long process) throws TskCoreException;
1947 
1948  private static native long commitAddImgNat(long process) throws TskCoreException;
1949 
1950  private static native long openImgNat(String[] imgPath, int splits, int sSize) throws TskCoreException;
1951 
1952  private static native long openVsNat(long imgHandle, long vsOffset) throws TskCoreException;
1953 
1954  private static native long openVolNat(long vsHandle, long volId) throws TskCoreException;
1955 
1956  private static native long openPoolNat(long imgHandle, long offset) throws TskCoreException;
1957 
1958  private static native long getImgInfoForPoolNat(long poolHandle, long poolOffset) throws TskCoreException;
1959 
1960  private static native long openFsNat(long imgHandle, long fsId) throws TskCoreException;
1961 
1962  private static native long openFileNat(long fsHandle, long fileId, int attrType, int attrId) throws TskCoreException;
1963 
1964  private static native int readImgNat(long imgHandle, byte[] readBuffer, long offset, long len) throws TskCoreException;
1965 
1966  private static native int readVsNat(long vsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException;
1967 
1968  private static native int readPoolNat(long poolHandle, byte[] readBuffer, long offset, long len) throws TskCoreException;
1969 
1970  private static native int readVolNat(long volHandle, byte[] readBuffer, long offset, long len) throws TskCoreException;
1971 
1972  private static native int readFsNat(long fsHandle, byte[] readBuffer, long offset, long len) throws TskCoreException;
1973 
1974  private static native int readFileNat(long fileHandle, byte[] readBuffer, long offset, int offset_type, long len) throws TskCoreException;
1975 
1976  private static native int saveFileMetaDataTextNat(long fileHandle, String fileName) throws TskCoreException;
1977 
1978  private static native void closeImgNat(long imgHandle);
1979 
1980  private static native void closePoolNat(long poolHandle);
1981 
1982  private static native void closeVsNat(long vsHandle);
1983 
1984  private static native void closeFsNat(long fsHandle);
1985 
1986  private static native void closeFileNat(long fileHandle);
1987 
1988  private static native long findDeviceSizeNat(String devicePath) throws TskCoreException;
1989 
1990  private static native String getCurDirNat(long process);
1991 
1992  private static native boolean isImageSupportedNat(String imagePath);
1993 
1994  private static native int finishImageWriterNat(long a_img_info);
1995 
1996  private static native int getFinishImageProgressNat(long a_img_info);
1997 
1998  private static native void cancelFinishImageNat(long a_img_info);
1999 
2000 }
static int readImg(long imgHandle, byte[] readBuffer, long offset, long len)
static String getHashDatabaseIndexPath(int dbHandle)
static int readVs(long vsHandle, byte[] readBuffer, long offset, long len)
static void createLookupIndexForHashDatabase(int dbHandle)
static void addToHashDatabase(String filename, String md5, String sha1, String sha256, String comment, int dbHandle)
static long openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId, SleuthkitCase skCase)
static int createHashDatabase(String path)
static void closeFs(long fsHandle)
static void cancelFinishImage(long imgHandle)
static long openFile(long fsHandle, long fileId, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId)
void run(String deviceId, String[] imageFilePaths)
static int readFile(long fileHandle, byte[] readBuffer, long offset, long len)
static int finishImageWriter(long imgHandle)
static HashHitInfo lookupInHashDatabaseVerbose(String hash, int dbHandle)
static long openVs(long imgHandle, long vsOffset)
static long openImage(String[] imageFiles, SleuthkitCase skCase)
static boolean hashDatabaseIsIndexOnly(int dbHandle)
static boolean isImageSupported(String imagePath)
static int readVsPart(long volHandle, byte[] readBuffer, long offset, long len)
static void closeFile(long fileHandle, SleuthkitCase skCase)
static long openImage(String[] imageFiles, int sSize)
static void closeVs(long vsHandle)
static long openImage(String[] imageFiles)
static long openFs(long imgHandle, long fsOffset, SleuthkitCase skCase)
static long openImage(String[] imageFiles, int sSize, SleuthkitCase skCase)
void run(String deviceId, String[] imageFilePaths, int sectorSize)
Definition: HashEntry.java:25
static long findDeviceSize(String devPath)
static String getHashDatabaseDisplayName(int dbHandle)
static List< String > getFileMetaDataText(long fileHandle)
static void closeImg(long imgHandle)
static long openFs(long imgHandle, long fsOffset)
static int getFinishImageProgress(long imgHandle)
static int openHashDatabase(String path)
static void closeFile(long fileHandle)
static boolean lookupInHashDatabase(String hash, int dbHandle)
static boolean hashDatabaseHasLookupIndex(int dbHandle)
static long openVsPart(long vsHandle, long volId)
static int readFileSlack(long fileHandle, byte[] readBuffer, long offset, long len)
static boolean isUpdateableHashDatabase(int dbHandle)
static void addToHashDatabase(List< HashEntry > hashes, int dbHandle)
static boolean hashDatabaseCanBeReindexed(int dbHandle)
static void startVerboseLogging(String logPath)
static int readFs(long fsHandle, byte[] readBuffer, long offset, long len)
static String getHashDatabasePath(int dbHandle)
static void closeHashDatabase(int dbHandle)

Copyright © 2011-2020 Brian Carrier. (carrier -at- sleuthkit -dot- org)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.