Sleuth Kit Java Bindings (JNI)  4.11.0
Java bindings for using The Sleuth Kit
AbstractFile.java
Go to the documentation of this file.
1 /*
2  * SleuthKit Java Bindings
3  *
4  * Copyright 2011-2021 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.FileNotFoundException;
22 import java.io.IOException;
23 import java.io.RandomAccessFile;
24 import java.sql.SQLException;
25 import java.sql.Statement;
26 import java.text.MessageFormat;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.List;
31 import java.util.Objects;
32 import java.util.Optional;
33 import java.util.ResourceBundle;
34 import java.util.Set;
35 import java.util.SortedSet;
36 import java.util.TimeZone;
37 import java.util.logging.Level;
38 import java.util.logging.Logger;
45 
50 public abstract class AbstractFile extends AbstractContent {
51 
53  protected final TSK_FS_NAME_TYPE_ENUM dirType;
56  protected Set<TSK_FS_META_FLAG_ENUM> metaFlags;
57  protected long size;
58  protected final long metaAddr, ctime, crtime, atime, mtime;
59  protected final int metaSeq;
60  protected final int uid, gid;
61  protected final int attrId;
63  protected final Set<TskData.TSK_FS_META_MODE_ENUM> modes;
64  //local file support
65  private boolean localPathSet = false;
66  private String localPath;
67  private String localAbsPath;
68  private volatile RandomAccessFile localFileHandle;
69  private volatile java.io.File localFile;
70  private TskData.EncodingType encodingType;
71  //range support
72  private List<TskFileRange> ranges;
73  /*
74  * path of parent directory
75  */
76  protected final String parentPath;
81  private boolean knownStateDirty = false;
82  /*
83  * md5 hash
84  */
85  protected String md5Hash;
86  private boolean md5HashDirty = false;
87  /*
88  * SHA-256 hash
89  */
90  protected String sha256Hash;
91  private boolean sha256HashDirty = false;
92  private String mimeType;
93  private boolean mimeTypeDirty = false;
94  private static final Logger LOGGER = Logger.getLogger(AbstractFile.class.getName());
95  private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("org.sleuthkit.datamodel.Bundle");
96  private long dataSourceObjectId;
97  private final String extension;
98  private final List<Attribute> fileAttributesCache = new ArrayList<Attribute>();
99  private boolean loadedAttributesCacheFromDb = false;
100 
101  private final String ownerUid; // string owner uid, for example a Windows SID.
102  // different from the numeric uid which is more commonly found
103  // on Unix based file systems.
104  private final Long osAccountObjId; // obj id of the owner's OS account, may be null
105 
106  private volatile String uniquePath;
107 
149  long objId,
150  long dataSourceObjectId,
152  String name,
154  long metaAddr, int metaSeq,
156  TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags,
157  long size,
158  long ctime, long crtime, long atime, long mtime,
159  short modes,
160  int uid, int gid,
161  String md5Hash, String sha256Hash, FileKnown knownState,
162  String parentPath,
163  String mimeType,
164  String extension,
165  String ownerUid,
166  Long osAccountObjectId,
167  List<Attribute> fileAttributes) {
168  super(db, objId, name);
169  this.dataSourceObjectId = dataSourceObjectId;
170  this.attrType = attrType;
171  this.attrId = attrId;
172  this.fileType = fileType;
173  this.metaAddr = metaAddr;
174  this.metaSeq = metaSeq;
175  this.dirType = dirType;
176  this.metaType = metaType;
177  this.dirFlag = dirFlag;
178  this.metaFlags = TSK_FS_META_FLAG_ENUM.valuesOf(metaFlags);
179  this.size = size;
180  this.ctime = ctime;
181  this.crtime = crtime;
182  this.atime = atime;
183  this.mtime = mtime;
184  this.uid = uid;
185  this.gid = gid;
186  this.modes = TskData.TSK_FS_META_MODE_ENUM.valuesOf(modes);
187 
188  this.md5Hash = md5Hash;
189  this.sha256Hash = sha256Hash;
190  if (knownState == null) {
191  this.knownState = FileKnown.UNKNOWN;
192  } else {
193  this.knownState = knownState;
194  }
195  this.parentPath = parentPath;
196  this.mimeType = mimeType;
197  this.extension = extension == null ? "" : extension;
198  this.encodingType = TskData.EncodingType.NONE;
199  this.ownerUid = ownerUid;
200  this.osAccountObjId = osAccountObjectId;
201  if (Objects.nonNull(fileAttributes) && !fileAttributes.isEmpty()) {
202  this.fileAttributesCache.addAll(fileAttributes);
203  loadedAttributesCacheFromDb = true;
204  }
205  }
206 
213  return fileType;
214  }
215 
222  return attrType;
223  }
224 
230  public int getAttributeId() {
231  return attrId;
232  }
233 
239  public long getCtime() {
240  return ctime;
241  }
242 
248  public String getCtimeAsDate() {
249  return epochToTime(ctime);
250  }
251 
257  public long getCrtime() {
258  return crtime;
259  }
260 
266  public String getCrtimeAsDate() {
267  return epochToTime(crtime);
268  }
269 
275  public long getAtime() {
276  return atime;
277  }
278 
284  public String getAtimeAsDate() {
285  return epochToTime(atime);
286  }
287 
293  public long getMtime() {
294  return mtime;
295  }
296 
302  public String getMtimeAsDate() {
303  return epochToTime(mtime);
304  }
305 
311  public int getUid() {
312  return uid;
313  }
314 
320  public int getGid() {
321  return gid;
322  }
323 
329  public long getMetaAddr() {
330  return metaAddr;
331  }
332 
339  public long getMetaSeq() {
340  return metaSeq;
341  }
342 
348  public String getModesAsString() {
350  String result = "";
351 
352  short isuid = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_ISUID.getMode();
353  short isgid = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_ISGID.getMode();
354  short isvtx = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_ISVTX.getMode();
355 
356  short irusr = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IRUSR.getMode();
357  short iwusr = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IWUSR.getMode();
358  short ixusr = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IXUSR.getMode();
359 
360  short irgrp = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IRGRP.getMode();
361  short iwgrp = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IWGRP.getMode();
362  short ixgrp = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IXGRP.getMode();
363 
364  short iroth = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IROTH.getMode();
365  short iwoth = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IWOTH.getMode();
366  short ixoth = TskData.TSK_FS_META_MODE_ENUM.TSK_FS_META_MODE_IXOTH.getMode();
367 
368  // first character = the Meta Type
369  result += metaType.toString();
370 
371  // second and third characters = user permissions
372  if ((mode & irusr) == irusr) {
373  result += "r"; //NON-NLS
374  } else {
375  result += "-"; //NON-NLS
376  }
377  if ((mode & iwusr) == iwusr) {
378  result += "w"; //NON-NLS
379  } else {
380  result += "-"; //NON-NLS
381  }
382 
383  // fourth character = set uid
384  if ((mode & isuid) == isuid) {
385  if ((mode & ixusr) == ixusr) {
386  result += "s"; //NON-NLS
387  } else {
388  result += "S"; //NON-NLS
389  }
390  } else {
391  if ((mode & ixusr) == ixusr) {
392  result += "x"; //NON-NLS
393  } else {
394  result += "-"; //NON-NLS
395  }
396  }
397 
398  // fifth and sixth characters = group permissions
399  if ((mode & irgrp) == irgrp) {
400  result += "r"; //NON-NLS
401  } else {
402  result += "-"; //NON-NLS
403  }
404  if ((mode & iwgrp) == iwgrp) {
405  result += "w"; //NON-NLS
406  } else {
407  result += "-"; //NON-NLS
408  }
409 
410  // seventh character = set gid
411  if ((mode & isgid) == isgid) {
412  if ((mode & ixgrp) == ixgrp) {
413  result += "s"; //NON-NLS
414  } else {
415  result += "S"; //NON-NLS
416  }
417  } else {
418  if ((mode & ixgrp) == ixgrp) {
419  result += "x"; //NON-NLS
420  } else {
421  result += "-"; //NON-NLS
422  }
423  }
424 
425  // eighth and ninth character = other permissions
426  if ((mode & iroth) == iroth) {
427  result += "r"; //NON-NLS
428  } else {
429  result += "-"; //NON-NLS
430  }
431  if ((mode & iwoth) == iwoth) {
432  result += "w"; //NON-NLS
433  } else {
434  result += "-"; //NON-NLS
435  }
436 
437  // tenth character = sticky bit
438  if ((mode & isvtx) == isvtx) {
439  if ((mode & ixoth) == ixoth) {
440  result += "t"; //NON-NLS
441  } else {
442  result += "T"; //NON-NLS
443  }
444  } else {
445  if ((mode & ixoth) == ixoth) {
446  result += "x"; //NON-NLS
447  } else {
448  result += "-"; //NON-NLS
449  }
450  }
451 
452  // check the result
453  if (result.length() != 10) {
454  // throw error here
455  result = "ERROR"; //NON-NLS
456  }
457  return result;
458  }
459 
465  public String getMIMEType() {
466  return mimeType;
467  }
468 
477  public void setMIMEType(String mimeType) {
478  this.mimeType = mimeType;
479  this.mimeTypeDirty = true;
480  }
481 
482  public boolean isModeSet(TskData.TSK_FS_META_MODE_ENUM mode) {
483  return modes.contains(mode);
484  }
485 
494  public void setMd5Hash(String md5Hash) {
495  this.md5Hash = md5Hash;
496  this.md5HashDirty = true;
497  }
498 
504  public String getMd5Hash() {
505  return this.md5Hash;
506  }
507 
516  public void setSha256Hash(String sha256Hash) {
517  this.sha256Hash = sha256Hash;
518  this.sha256HashDirty = true;
519  }
520 
526  public String getSha256Hash() {
527  return this.sha256Hash;
528  }
529 
537  public List<Attribute> getAttributes() throws TskCoreException {
538  synchronized (this) {
539  if (!loadedAttributesCacheFromDb) {
540  ArrayList<Attribute> attributes = getSleuthkitCase().getFileAttributes(this);
541  fileAttributesCache.clear();
542  fileAttributesCache.addAll(attributes);
543  loadedAttributesCacheFromDb = true;
544  }
545  return Collections.unmodifiableList(fileAttributesCache);
546  }
547  }
548 
562  public void addAttributes(Collection<Attribute> attributes, final SleuthkitCase.CaseDbTransaction caseDbTransaction) throws TskCoreException {
563 
564  if (Objects.isNull(attributes) || attributes.isEmpty()) {
565  throw new TskCoreException("Illegal Argument passed to addAttributes: null or empty attributes passed to addAttributes");
566  }
567  boolean isLocalTransaction = Objects.isNull(caseDbTransaction);
568  SleuthkitCase.CaseDbTransaction localTransaction = isLocalTransaction ? getSleuthkitCase().beginTransaction() : null;
569  SleuthkitCase.CaseDbConnection connection = isLocalTransaction ? localTransaction.getConnection() : caseDbTransaction.getConnection();
570 
571  try {
572  for (final Attribute attribute : attributes) {
573  attribute.setAttributeParentId(getId());
574  attribute.setCaseDatabase(getSleuthkitCase());
575  getSleuthkitCase().addFileAttribute(attribute, connection);
576  }
577 
578  if (isLocalTransaction) {
579  localTransaction.commit();
580  localTransaction = null;
581  }
582  // append the new attributes if cache is already loaded.
583  synchronized (this) {
584  if (loadedAttributesCacheFromDb) {
585  fileAttributesCache.addAll(attributes);
586  }
587  }
588  } catch (SQLException ex) {
589  if (isLocalTransaction && null != localTransaction) {
590  try {
591  localTransaction.rollback();
592  } catch (TskCoreException ex2) {
593  LOGGER.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
594  }
595  }
596  throw new TskCoreException("Error adding file attributes", ex);
597  }
598  }
599 
611  // don't allow them to downgrade the known state
612  if (this.knownState.compareTo(knownState) > 0) {
613  // ideally we'd return some kind of error, but
614  // the API doesn't allow it
615  return;
616  }
617  this.knownState = knownState;
618  this.knownStateDirty = true;
619  }
620 
628  return knownState;
629  }
630 
638  public String getNameExtension() {
639  return extension;
640  }
641 
647  @Override
648  public long getSize() {
649  return size;
650  }
651 
657  public String getParentPath() {
658  return parentPath;
659  }
660 
672  @Override
674  return getSleuthkitCase().getContentById(this.dataSourceObjectId);
675  }
676 
682  public long getDataSourceObjectId() {
683  return dataSourceObjectId;
684  }
685 
696  public List<TskFileRange> getRanges() throws TskCoreException {
697  if (ranges == null) {
698  ranges = getSleuthkitCase().getFileRanges(this.getId());
699  }
700  return ranges;
701  }
702 
716  public long convertToImgOffset(long fileOffset) throws TskCoreException {
717  long imgOffset = -1;
718  for (TskFileRange byteRange : getRanges()) {
719 
720  // if fileOffset is within the current byteRange, calculate the image
721  // offset and break
722  long rangeLength = byteRange.getByteLen();
723  if (fileOffset < rangeLength) {
724  imgOffset = byteRange.getByteStart() + fileOffset;
725  break;
726  }
727 
728  // otherwise, decrement fileOffset by the length of the current
729  // byte range and continue
730  fileOffset -= rangeLength;
731  }
732  return imgOffset;
733  }
734 
749  public List<TskFileRange> convertToImgRanges(long fileOffset, long length) throws TskCoreException {
750  if (fileOffset < 0 || length < 0) {
751  throw new TskCoreException("fileOffset and length must be non-negative");
752  }
753 
754  List<TskFileRange> thisRanges = getRanges();
755  List<TskFileRange> toRet = new ArrayList<>();
756 
757  long requestedEnd = fileOffset + length;
758 
759  // the number of bytes counted from the beginning of this file
760  long bytesCounted = 0;
761 
762  for (int curRangeIdx = 0; curRangeIdx < thisRanges.size(); curRangeIdx++) {
763  // if we exceeded length of requested, then we are done
764  if (bytesCounted >= requestedEnd) {
765  break;
766  }
767 
768  TskFileRange curRange = thisRanges.get(curRangeIdx);
769  long curRangeLen = curRange.getByteLen();
770  // the bytes counted when we reach the end of this range
771  long curRangeEnd = bytesCounted + curRangeLen;
772 
773  // if fileOffset is less than current range's end and we have not
774  // gone past the end we requested, then grab at least part of this
775  // range.
776  if (fileOffset < curRangeEnd) {
777  // offset into range to be returned to user (0 if fileOffset <= bytesCounted)
778  long rangeOffset = Math.max(0, fileOffset - bytesCounted);
779 
780  // calculate the new TskFileRange start by adding on the offset into the current range
781  long newRangeStart = curRange.getByteStart() + rangeOffset;
782 
783  // how much this current range exceeds the length requested (or 0 if within the length requested)
784  long rangeOvershoot = Math.max(0, curRangeEnd - requestedEnd);
785 
786  long newRangeLen = curRangeLen - rangeOffset - rangeOvershoot;
787  toRet.add(new TskFileRange(newRangeStart, newRangeLen, toRet.size()));
788  }
789 
790  bytesCounted = curRangeEnd;
791  }
792 
793  return toRet;
794  }
795 
802  public boolean isVirtual() {
804  || dirType.equals(TskData.TSK_FS_NAME_TYPE_ENUM.VIRT)
806  }
807 
815  public boolean isFile() {
816  return metaType.equals(TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG)
817  || (metaType.equals(TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_UNDEF)
818  && dirType.equals(TSK_FS_NAME_TYPE_ENUM.REG));
819 
820  }
821 
828  public boolean isDir() {
829  return (metaType.equals(TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR)
831  }
832 
838  public abstract boolean isRoot();
839 
848  public static String createNonUniquePath(String uniquePath) {
849 
850  // split the path into parts
851  String[] pathSegments = uniquePath.split("/");
852 
853  // see if uniquePath had an image and/or volume name
854  int index = 0;
855  if (pathSegments[0].startsWith("img_")) { //NON-NLS
856  ++index;
857  }
858  if (pathSegments[1].startsWith("vol_")) { //NON-NLS
859  ++index;
860  }
861 
862  // Assemble the non-unique path (skipping over the image and volume
863  // name, if they exist).
864  StringBuilder strbuf = new StringBuilder();
865  for (; index < pathSegments.length; ++index) {
866  if (!pathSegments[index].isEmpty()) {
867  strbuf.append("/").append(pathSegments[index]);
868  }
869  }
870 
871  return strbuf.toString();
872  }
873 
880  public List<AbstractFile> listFiles() throws TskCoreException {
881  // first, get all children
882  List<Content> children = getChildren();
883 
884  // only keep those that are of type AbstractFile
885  List<AbstractFile> files = new ArrayList<AbstractFile>();
886  for (Content child : children) {
887  if (child instanceof AbstractFile) {
888  AbstractFile afChild = (AbstractFile) child;
889  files.add(afChild);
890  }
891  }
892  return files;
893  }
894 
901  return metaType;
902  }
903 
904  public String getMetaTypeAsString() {
905  return metaType.toString();
906  }
907 
914  return dirType;
915  }
916 
917  public String getDirTypeAsString() {
918  return dirType.toString();
919  }
920 
927  return dirFlag == flag;
928  }
929 
934  public String getDirFlagAsString() {
935  return dirFlag.toString();
936  }
937 
943  void setDirFlag(TSK_FS_NAME_FLAG_ENUM flag) {
944  dirFlag = flag;
945  }
946 
950  public String getMetaFlagsAsString() {
951  String str = "";
952  if (metaFlags.contains(TSK_FS_META_FLAG_ENUM.ALLOC)) {
953  str = TSK_FS_META_FLAG_ENUM.ALLOC.toString();
954  } else if (metaFlags.contains(TSK_FS_META_FLAG_ENUM.UNALLOC)) {
955  str = TSK_FS_META_FLAG_ENUM.UNALLOC.toString();
956  }
957  return str;
958  }
959 
965  public boolean isMetaFlagSet(TSK_FS_META_FLAG_ENUM metaFlag) {
966  return metaFlags.contains(metaFlag);
967  }
968 
974  void setMetaFlag(TSK_FS_META_FLAG_ENUM metaFlag) {
975  metaFlags.add(metaFlag);
976  }
977 
983  void removeMetaFlag(TSK_FS_META_FLAG_ENUM metaFlag) {
984  metaFlags.remove(metaFlag);
985  }
986 
992  short getMetaFlagsAsInt() {
993  return TSK_FS_META_FLAG_ENUM.toInt(metaFlags);
994  }
995 
996  @Override
997  public final int read(byte[] buf, long offset, long len) throws TskCoreException {
998  //template method
999  //if localPath is set, use local, otherwise, use readCustom() supplied by derived class
1000  if (localPathSet) {
1001  return readLocal(buf, offset, len);
1002  } else {
1003  return readInt(buf, offset, len);
1004  }
1005 
1006  }
1007 
1019  protected int readInt(byte[] buf, long offset, long len) throws TskCoreException {
1020  return 0;
1021  }
1022 
1034  protected final int readLocal(byte[] buf, long offset, long len) throws TskCoreException {
1035  if (!localPathSet) {
1036  throw new TskCoreException(
1037  BUNDLE.getString("AbstractFile.readLocal.exception.msg1.text"));
1038  }
1039 
1040  if (isDir()) {
1041  return 0;
1042  }
1043 
1044  // If the file is empty, just return that zero bytes were read.
1045  if (getSize() == 0) {
1046  return 0;
1047  }
1048 
1049  loadLocalFile();
1050 
1051  int bytesRead = 0;
1052 
1053  if (localFileHandle == null) {
1054  synchronized (this) {
1055  if (localFileHandle == null) {
1056  try {
1057  localFileHandle = new RandomAccessFile(localFile, "r");
1058  } catch (FileNotFoundException ex) {
1059  final String msg = MessageFormat.format(BUNDLE.getString(
1060  "AbstractFile.readLocal.exception.msg4.text"),
1061  localAbsPath);
1062  LOGGER.log(Level.SEVERE, msg, ex);
1063  //file could have been deleted or moved
1064  throw new TskCoreException(msg, ex);
1065  }
1066  }
1067  }
1068  }
1069 
1070  try {
1071  if (!encodingType.equals(TskData.EncodingType.NONE)) {
1072  // The file is encoded, so we need to alter the offset to read (since there's
1073  // a header on the encoded file) and then decode each byte
1074  long encodedOffset = offset + EncodedFileUtil.getHeaderLength();
1075 
1076  //move to the user request offset in the stream
1077  long curOffset = localFileHandle.getFilePointer();
1078  if (curOffset != encodedOffset) {
1079  localFileHandle.seek(encodedOffset);
1080  }
1081  bytesRead = localFileHandle.read(buf, 0, (int) len);
1082  for (int i = 0; i < bytesRead; i++) {
1083  buf[i] = EncodedFileUtil.decodeByte(buf[i], encodingType);
1084  }
1085  return bytesRead;
1086  } else {
1087  //move to the user request offset in the stream
1088  long curOffset = localFileHandle.getFilePointer();
1089  if (curOffset != offset) {
1090  localFileHandle.seek(offset);
1091  }
1092  //note, we are always writing at 0 offset of user buffer
1093  return localFileHandle.read(buf, 0, (int) len);
1094  }
1095  } catch (IOException ex) {
1096  final String msg = MessageFormat.format(BUNDLE.getString("AbstractFile.readLocal.exception.msg5.text"), localAbsPath);
1097  LOGGER.log(Level.SEVERE, msg, ex);
1098  //local file could have been deleted / moved
1099  throw new TskCoreException(msg, ex);
1100  }
1101  }
1102 
1110  void setLocalFilePath(String localPath) {
1111 
1112  if (localPath == null || localPath.equals("")) {
1113  this.localPath = "";
1114  localAbsPath = null;
1115  localPathSet = false;
1116  } else {
1117  // It should always be the case that absolute paths start with slashes or a windows drive letter
1118  // and relative paths do not, but some older versions of modules created derived file paths
1119  // starting with slashes. So we first check if this file is a DerivedFile before looking at the path.
1120  this.localPath = localPath;
1121  if (this instanceof DerivedFile) {
1122  // DerivedFiles always have relative paths
1123  this.localAbsPath = getSleuthkitCase().getDbDirPath() + java.io.File.separator + localPath;
1124  } else {
1125  // If a path starts with a slash or with a Windows drive letter, then it is
1126  // absolute. Otherwise it is relative.
1127  if (localPath.startsWith("/") || localPath.startsWith("\\")
1128  || localPath.matches("[A-Za-z]:[/\\\\].*")) {
1129  this.localAbsPath = localPath;
1130  } else {
1131  this.localAbsPath = getSleuthkitCase().getDbDirPath() + java.io.File.separator + localPath;
1132  }
1133  }
1134  this.localPathSet = true;
1135  }
1136  }
1137 
1143  public String getLocalPath() {
1144  return localPath;
1145  }
1146 
1152  public String getLocalAbsPath() {
1153  return localAbsPath;
1154  }
1155 
1161  final void setEncodingType(TskData.EncodingType encodingType) {
1162  this.encodingType = encodingType;
1163  }
1164 
1171  public boolean exists() {
1172  if (!localPathSet) {
1173  return true;
1174  } else {
1175  try {
1176  loadLocalFile();
1177  return localFile.exists();
1178  } catch (TskCoreException ex) {
1179  LOGGER.log(Level.SEVERE, ex.getMessage());
1180  return false;
1181  }
1182  }
1183  }
1184 
1192  public boolean canRead() {
1193  if (!localPathSet) {
1194  return true;
1195  } else {
1196  try {
1197  loadLocalFile();
1198  return localFile.canRead();
1199  } catch (TskCoreException ex) {
1200  LOGGER.log(Level.SEVERE, ex.getMessage());
1201  return false;
1202  }
1203  }
1204  }
1205 
1212  private void loadLocalFile() throws TskCoreException {
1213  if (!localPathSet) {
1214  throw new TskCoreException(
1215  BUNDLE.getString("AbstractFile.readLocal.exception.msg1.text"));
1216  }
1217 
1218  // already been set
1219  if (localFile != null) {
1220  return;
1221  }
1222 
1223  synchronized (this) {
1224  if (localFile == null) {
1225  localFile = new java.io.File(localAbsPath);
1226  }
1227  }
1228  }
1229 
1230  @Override
1231  public void close() {
1232 
1233  //close local file handle if set
1234  if (localFileHandle != null) {
1235  synchronized (this) {
1236  if (localFileHandle != null) {
1237  try {
1238  localFileHandle.close();
1239  } catch (IOException ex) {
1240  LOGGER.log(Level.SEVERE, "Could not close file handle for file: " + getParentPath() + getName(), ex); //NON-NLS
1241  }
1242  localFileHandle = null;
1243  }
1244  }
1245  }
1246 
1247  }
1248 
1249  @Override
1250  protected void finalize() throws Throwable {
1251  try {
1252  close();
1253  } finally {
1254  super.finalize();
1255  }
1256  }
1257 
1258  @Override
1259  public String toString(boolean preserveState) {
1260  return super.toString(preserveState) + "AbstractFile [\t" //NON-NLS
1261  + "\t" + "fileType " + fileType //NON-NLS
1262  + "\tctime " + ctime //NON-NLS
1263  + "\tcrtime " + crtime //NON-NLS
1264  + "\t" + "mtime " + mtime + "\t" + "atime " + atime //NON-NLS
1265  + "\t" + "attrId " + attrId //NON-NLS
1266  + "\t" + "attrType " + attrType //NON-NLS
1267  + "\t" + "dirFlag " + dirFlag + "\t" + "dirType " + dirType //NON-NLS
1268  + "\t" + "uid " + uid //NON-NLS
1269  + "\t" + "gid " + gid //NON-NLS
1270  + "\t" + "metaAddr " + metaAddr + "\t" + "metaSeq " + metaSeq + "\t" + "metaFlags " + metaFlags //NON-NLS
1271  + "\t" + "metaType " + metaType + "\t" + "modes " + modes //NON-NLS
1272  + "\t" + "parentPath " + parentPath + "\t" + "size " + size //NON-NLS
1273  + "\t" + "knownState " + knownState + "\t" + "md5Hash " + md5Hash + "\t" + "sha256Hash " + sha256Hash //NON-NLS
1274  + "\t" + "localPathSet " + localPathSet + "\t" + "localPath " + localPath //NON-NLS
1275  + "\t" + "localAbsPath " + localAbsPath + "\t" + "localFile " + localFile //NON-NLS
1276  + "]\t";
1277  }
1278 
1282  public enum MimeMatchEnum {
1283 
1286  FALSE
1287  }
1288 
1297  public MimeMatchEnum isMimeType(SortedSet<String> mimeTypes) {
1298  if (this.mimeType == null) {
1299  return MimeMatchEnum.UNDEFINED;
1300  }
1301  if (mimeTypes.contains(this.mimeType)) {
1302  return MimeMatchEnum.TRUE;
1303  }
1304  return MimeMatchEnum.FALSE;
1305  }
1306 
1314  public void save() throws TskCoreException {
1315  CaseDbTransaction transaction = null;
1316  try {
1317  transaction = getSleuthkitCase().beginTransaction();
1318  save(transaction);
1319  transaction.commit();
1320  } catch (TskCoreException ex) {
1321  if (transaction != null) {
1322  transaction.rollback();
1323  }
1324  throw ex;
1325  }
1326  }
1327 
1338  public void save(CaseDbTransaction transaction) throws TskCoreException {
1339  if (!(md5HashDirty || sha256HashDirty || mimeTypeDirty || knownStateDirty)) {
1340  return;
1341  }
1342 
1343  String updateSql = "";
1344  if (mimeTypeDirty) {
1345  updateSql = "mime_type = '" + this.getMIMEType() + "'";
1346  }
1347  if (md5HashDirty) {
1348  if (!updateSql.isEmpty()) {
1349  updateSql += ", ";
1350  }
1351  updateSql += "md5 = '" + this.getMd5Hash() + "'";
1352  }
1353  if (sha256HashDirty) {
1354  if (!updateSql.isEmpty()) {
1355  updateSql += ", ";
1356  }
1357  updateSql += "sha256 = '" + this.getSha256Hash() + "'";
1358  }
1359  if (knownStateDirty) {
1360  if (!updateSql.isEmpty()) {
1361  updateSql += ", ";
1362  }
1363  updateSql += "known = '" + this.getKnown().getFileKnownValue() + "'";
1364  }
1365  updateSql = "UPDATE tsk_files SET " + updateSql + " WHERE obj_id = " + this.getId();
1366 
1367  SleuthkitCase.CaseDbConnection connection = transaction.getConnection();
1368  try (Statement statement = connection.createStatement()) {
1369  connection.executeUpdate(statement, updateSql);
1370  md5HashDirty = false;
1371  sha256HashDirty = false;
1372  mimeTypeDirty = false;
1373  knownStateDirty = false;
1374  } catch (SQLException ex) {
1375  throw new TskCoreException(String.format("Error updating properties of file %s (obj_id = %s)", getName(), getId()), ex);
1376  }
1377  }
1378 
1387  public Optional<String> getOwnerUid() {
1388  return Optional.ofNullable(ownerUid);
1389  }
1390 
1396  public Optional<Long> getOsAccountObjectId() {
1397  return Optional.ofNullable(osAccountObjId);
1398  }
1399 
1400  @Override
1401  public String getUniquePath() throws TskCoreException {
1402 
1403  if (uniquePath == null) {
1404  Content dataSource = getDataSource();
1405  if (dataSource instanceof LocalFilesDataSource) {
1406  if(dataSource != this) {
1407  uniquePath = dataSource.getUniquePath() + parentPath + getName();
1408  } else {
1409  uniquePath = "/" + getName();
1410  }
1411  } else {
1412  uniquePath = super.getUniquePath();
1413  }
1414  }
1415 
1416  return uniquePath;
1417  }
1418 
1419  @Deprecated
1420  @SuppressWarnings("deprecation")
1421  @Override
1422  public BlackboardArtifact newArtifact(int artifactTypeID) throws TskCoreException {
1423  return super.newArtifact(artifactTypeID);
1424  }
1425 
1439  @Override
1440  public DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection<BlackboardAttribute> attributesList) throws TskCoreException {
1441  return super.newDataArtifact(artifactType, attributesList, getOsAccountObjectId().orElse(null));
1442  }
1443 
1475  @Deprecated
1476  @SuppressWarnings("deprecation")
1477  protected AbstractFile(SleuthkitCase db, long objId, TskData.TSK_FS_ATTR_TYPE_ENUM attrType, short attrId,
1478  String name, TskData.TSK_DB_FILES_TYPE_ENUM fileType, long metaAddr, int metaSeq,
1479  TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags,
1480  long size, long ctime, long crtime, long atime, long mtime, short modes, int uid, int gid, String md5Hash, FileKnown knownState,
1481  String parentPath) {
1482  this(db, objId, db.getDataSourceObjectId(objId), attrType, (int) attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, null, null, OsAccount.NO_OWNER_ID, OsAccount.NO_ACCOUNT, Collections.emptyList());
1483  }
1484 
1521  @Deprecated
1522  @SuppressWarnings("deprecation")
1523  AbstractFile(SleuthkitCase db, long objId, long dataSourceObjectId, TskData.TSK_FS_ATTR_TYPE_ENUM attrType, short attrId,
1524  String name, TskData.TSK_DB_FILES_TYPE_ENUM fileType, long metaAddr, int metaSeq, TSK_FS_NAME_TYPE_ENUM dirType, TSK_FS_META_TYPE_ENUM metaType,
1525  TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, long ctime, long crtime, long atime, long mtime, short modes,
1526  int uid, int gid, String md5Hash, FileKnown knownState, String parentPath, String mimeType) {
1527  this(db, objId, dataSourceObjectId, attrType, (int) attrId, name, fileType, metaAddr, metaSeq, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, modes, uid, gid, md5Hash, null, knownState, parentPath, null, null, OsAccount.NO_OWNER_ID, OsAccount.NO_ACCOUNT, Collections.emptyList());
1528  }
1529 
1538  @Deprecated
1539  @SuppressWarnings("deprecation")
1540  public short getAttrId() {
1541  /*
1542  * NOTE: previously attrId used to be stored in AbstractFile as (signed)
1543  * short even though it is stored as uint16 in TSK. In extremely rare
1544  * occurrences attrId can be larger than what a signed short can hold
1545  * (2^15). Changes were made to AbstractFile to store attrId as integer.
1546  * Therefore this method has been deprecated. For backwards
1547  * compatibility, attribute ids that are larger than 32K are converted
1548  * to a negative number.
1549  */
1550  return (short) attrId; // casting to signed short converts values over 32K to negative values
1551  }
1552 
1564  @Deprecated
1565  protected void setLocalPath(String localPath, boolean isAbsolute) {
1566  setLocalFilePath(localPath);
1567  }
1568 
1569  /*
1570  * -------------------------------------------------------------------------
1571  * Util methods to convert / map the data
1572  * -------------------------------------------------------------------------
1573  */
1583  @Deprecated
1584  public static String epochToTime(long epoch) {
1585  return TimeUtilities.epochToTime(epoch);
1586  }
1587 
1599  @Deprecated
1600  public static String epochToTime(long epoch, TimeZone tzone) {
1601  return TimeUtilities.epochToTime(epoch, tzone);
1602  }
1603 
1611  @Deprecated
1612  public static long timeToEpoch(String time) {
1613  return TimeUtilities.timeToEpoch(time);
1614  }
1615 }
VIRT
Special (TSK added "Virtual" files) NON-NLS.
Definition: TskData.java:50
boolean isModeSet(TskData.TSK_FS_META_MODE_ENUM mode)
final TSK_FS_NAME_TYPE_ENUM dirType
static long timeToEpoch(String time)
static String epochToTime(long epoch)
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection< BlackboardAttribute > attributesList, Long osAccountId)
static String epochToTime(long epoch)
static Set< TSK_FS_META_FLAG_ENUM > valuesOf(short metaFlags)
Definition: TskData.java:247
final int readLocal(byte[] buf, long offset, long len)
boolean isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM flag)
ALLOC
Metadata structure is currently in an allocated state.
Definition: TskData.java:206
void setSha256Hash(String sha256Hash)
final TskData.TSK_DB_FILES_TYPE_ENUM fileType
UNALLOC
Metadata structure is currently in an unallocated state.
Definition: TskData.java:207
TskData.TSK_DB_FILES_TYPE_ENUM getType()
final TskData.TSK_FS_ATTR_TYPE_ENUM attrType
TSK_FS_META_TYPE_VIRT_DIR
"Virtual Directory" created by TSK for Orphan Files NON-NLS
Definition: TskData.java:114
long convertToImgOffset(long fileOffset)
TSK_FS_NAME_TYPE_ENUM getDirType()
BlackboardArtifact newArtifact(int artifactTypeID)
MimeMatchEnum isMimeType(SortedSet< String > mimeTypes)
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection< BlackboardAttribute > attributesList)
String toString(boolean preserveState)
Set< TSK_FS_META_FLAG_ENUM > metaFlags
void setKnown(TskData.FileKnown knownState)
BlackboardArtifact newArtifact(int artifactTypeID)
FALSE
file has a defined mime type and it is one of the given ones
final Set< TskData.TSK_FS_META_MODE_ENUM > modes
TSK_FS_META_TYPE_VIRT
"Virtual File" created by TSK for file system areas NON-NLS
Definition: TskData.java:113
TSK_FS_META_TYPE_ENUM getMetaType()
boolean isMetaFlagSet(TSK_FS_META_FLAG_ENUM metaFlag)
TRUE
file does not have a defined mime time in blackboard
static short toInt(Set< TSK_FS_META_MODE_ENUM > modes)
Definition: TskData.java:422
static String epochToTime(long epoch, TimeZone tzone)
static long timeToEpoch(String time)
int readInt(byte[] buf, long offset, long len)
void save(CaseDbTransaction transaction)
UNKNOWN
File marked as unknown by hash db.
Definition: TskData.java:791
static Set< TSK_FS_META_MODE_ENUM > valuesOf(short modes)
Definition: TskData.java:403
List< TskFileRange > convertToImgRanges(long fileOffset, long length)
void setLocalPath(String localPath, boolean isAbsolute)
static String createNonUniquePath(String uniquePath)
VIRTUAL_DIR
Virtual directory (not on fs) with no meta-data entry that can be used to group files of types other ...
Definition: TskData.java:691
void addAttributes(Collection< Attribute > attributes, final SleuthkitCase.CaseDbTransaction caseDbTransaction)
final int read(byte[] buf, long offset, long len)
final TSK_FS_META_TYPE_ENUM metaType
List< TskFileRange > getFileRanges(long id)
TskData.TSK_FS_ATTR_TYPE_ENUM getAttrType()

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