Autopsy  4.19.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
AddLogicalImageTask.java
Go to the documentation of this file.
1 /*
2  * Autopsy
3  *
4  * Copyright 2019 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.autopsy.logicalimager.dsp;
20 
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FilenameFilter;
25 import java.io.IOException;
26 import java.io.InputStreamReader;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.logging.Level;
37 import javax.annotation.concurrent.GuardedBy;
38 import org.apache.commons.io.FileUtils;
39 import org.openide.util.NbBundle.Messages;
46 import org.sleuthkit.datamodel.AbstractFile;
47 import org.sleuthkit.datamodel.Blackboard;
48 import org.sleuthkit.datamodel.BlackboardArtifact;
49 import org.sleuthkit.datamodel.BlackboardAttribute;
50 import org.sleuthkit.datamodel.Content;
51 import org.sleuthkit.datamodel.Host;
52 import org.sleuthkit.datamodel.LocalFilesDataSource;
53 import org.sleuthkit.datamodel.Score;
54 import org.sleuthkit.datamodel.SleuthkitCase;
55 import org.sleuthkit.datamodel.TskCoreException;
56 
62 final class AddLogicalImageTask implements Runnable {
63 
68  private static class FileId {
69 
70  private final long dataSourceId;
71  private final long fileId;
72 
79  FileId(long dataSourceId, long fileId) {
80  this.dataSourceId = dataSourceId;
81  this.fileId = fileId;
82  }
83 
89  long getDataSourceId() {
90  return dataSourceId;
91  }
92 
98  long getFileId() {
99  return fileId;
100  }
101  }
102 
103  private final static Logger LOGGER = Logger.getLogger(AddLogicalImageTask.class.getName());
104  private final static String SEARCH_RESULTS_TXT = "SearchResults.txt"; //NON-NLS
105  private final static String USERS_TXT = "_users.txt"; //NON-NLS
106  private final static String MODULE_NAME = "Logical Imager"; //NON-NLS
107  private final static String ROOT_STR = "root"; // NON-NLS
108  private final static String VHD_EXTENSION = ".vhd"; // NON-NLS
109  private final static int REPORT_PROGRESS_INTERVAL = 100;
110  private final static int POST_ARTIFACT_INTERVAL = 1000;
111  private final String deviceId;
112  private final String timeZone;
113  private final File src;
114  private final File dest;
115  private final Host host;
116  private final DataSourceProcessorCallback callback;
117  private final DataSourceProcessorProgressMonitor progressMonitor;
118  private final Blackboard blackboard;
119  private final Case currentCase;
120 
121  private volatile boolean cancelled;
122  private volatile boolean createVHD;
123  private long totalFiles;
124  private Map<String, Long> imagePathToObjIdMap;
125 
126  private final Object addMultipleImagesLock;
127  @GuardedBy("addMultipleImagesLock")
128  private AddMultipleImagesTask addMultipleImagesTask = null;
129 
130  AddLogicalImageTask(String deviceId,
131  String timeZone,
132  File src, File dest, Host host,
133  DataSourceProcessorProgressMonitor progressMonitor,
134  DataSourceProcessorCallback callback
135  ) throws NoCurrentCaseException {
136  this.deviceId = deviceId;
137  this.timeZone = timeZone;
138  this.src = src;
139  this.dest = dest;
140  this.host = host;
141  this.progressMonitor = progressMonitor;
142  this.callback = callback;
143  this.currentCase = Case.getCurrentCase();
144  this.blackboard = this.currentCase.getServices().getArtifactsBlackboard();
145  this.addMultipleImagesLock = new Object();
146  }
147 
152  @Messages({
153  "# {0} - src", "# {1} - dest", "AddLogicalImageTask.copyingImageFromTo=Copying image from {0} to {1}",
154  "AddLogicalImageTask.doneCopying=Done copying",
155  "# {0} - src", "# {1} - dest", "AddLogicalImageTask.failedToCopyDirectory=Failed to copy directory {0} to {1}",
156  "# {0} - file", "AddLogicalImageTask.addingToReport=Adding {0} to report",
157  "# {0} - file", "AddLogicalImageTask.doneAddingToReport=Done adding {0} to report",
158  "AddLogicalImageTask.ingestionCancelled=Ingestion cancelled",
159  "# {0} - file", "AddLogicalImageTask.failToGetCanonicalPath=Fail to get canonical path for {0}",
160  "# {0} - sparseImageDirectory", "AddLogicalImageTask.directoryDoesNotContainSparseImage=Directory {0} does not contain any images",
161  "AddLogicalImageTask.noCurrentCase=No current case",
162  "AddLogicalImageTask.addingInterestingFiles=Adding search results as interesting files",
163  "AddLogicalImageTask.doneAddingInterestingFiles=Done adding search results as interesting files",
164  "# {0} - SearchResults.txt", "# {1} - directory", "AddLogicalImageTask.cannotFindFiles=Cannot find {0} in {1}",
165  "# {0} - reason", "AddLogicalImageTask.failedToAddInterestingFiles=Failed to add interesting files: {0}",
166  "AddLogicalImageTask.addingExtractedFiles=Adding extracted files",
167  "AddLogicalImageTask.doneAddingExtractedFiles=Done adding extracted files",
168  "# {0} - reason", "AddLogicalImageTask.failedToGetTotalFilesCount=Failed to get total files count: {0}",
169  "AddLogicalImageTask.addImageCancelled=Add image cancelled"
170  })
171  @Override
172  public void run() {
173  List<String> errorList = new ArrayList<>();
174  List<Content> emptyDataSources = new ArrayList<>();
175 
176  try {
177  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_copyingImageFromTo(src.toString(), dest.toString()));
178  FileUtils.copyDirectory(src, dest);
179  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneCopying());
180  } catch (IOException ex) {
181  // Copy directory failed
182  String msg = Bundle.AddLogicalImageTask_failedToCopyDirectory(src.toString(), dest.toString());
183  errorList.add(msg);
184  }
185 
186  if (cancelled) {
187  // Don't delete destination directory once we started adding interesting files.
188  // At this point the database and destination directory are complete.
189  deleteDestinationDirectory();
190  errorList.add(Bundle.AddLogicalImageTask_addImageCancelled());
191  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
192  return;
193  }
194 
195  // Add the SearchResults.txt and *_users.txt to the case report
196  String resultsFilename;
197  if (Paths.get(dest.toString(), SEARCH_RESULTS_TXT).toFile().exists()) {
198  resultsFilename = SEARCH_RESULTS_TXT;
199  } else {
200  errorList.add(Bundle.AddLogicalImageTask_cannotFindFiles(SEARCH_RESULTS_TXT, dest.toString()));
201  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
202  return;
203  }
204 
205  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingToReport(resultsFilename));
206  String status = addReport(Paths.get(dest.toString(), resultsFilename), resultsFilename + " " + src.getName());
207  if (status != null) {
208  errorList.add(status);
209  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
210  return;
211  }
212  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingToReport(resultsFilename));
213 
214  // All all *_users.txt files to report
215  File[] userFiles = dest.listFiles(new FilenameFilter() {
216  @Override
217  public boolean accept(File dir, String name) {
218  return name.endsWith(USERS_TXT);
219  }
220  });
221 
222  for (File userFile : userFiles) {
223  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingToReport(userFile.getName()));
224  status = addReport(userFile.toPath(), userFile.getName() + " " + src.getName());
225  if (status != null) {
226  errorList.add(status);
227  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
228  return;
229  }
230  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingToReport(userFile.getName()));
231  }
232 
233  // Get all VHD files in the dest directory
234  List<String> imagePaths = new ArrayList<>();
235  for (File f : dest.listFiles()) {
236  if (f.getName().endsWith(VHD_EXTENSION)) {
237  try {
238  imagePaths.add(f.getCanonicalPath());
239  } catch (IOException ioe) {
240  String msg = Bundle.AddLogicalImageTask_failToGetCanonicalPath(f.getName());
241  errorList.add(msg);
242  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
243  return;
244  }
245  }
246  }
247 
248  Path resultsPath = Paths.get(dest.toString(), resultsFilename);
249  try {
250  totalFiles = Files.lines(resultsPath).count() - 1; // skip the header line
251  } catch (IOException ex) {
252  errorList.add(Bundle.AddLogicalImageTask_failedToGetTotalFilesCount(ex.getMessage()));
253  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
254  return;
255  }
256 
257  List<Content> newDataSources = new ArrayList<>();
258  Map<String, List<FileId>> interestingFileMap = new HashMap<>();
259 
260  if (imagePaths.isEmpty()) {
261  createVHD = false;
262  // No VHD in src directory, try ingest the root directory as local files
263  File root = Paths.get(dest.toString(), ROOT_STR).toFile();
264  if (root.exists() && root.isDirectory()) {
265  imagePaths.add(root.getAbsolutePath());
266  } else {
267  String msg = Bundle.AddLogicalImageTask_directoryDoesNotContainSparseImage(dest);
268  errorList.add(msg);
269  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
270  return;
271  }
272 
273  try {
274  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingExtractedFiles());
275  interestingFileMap = addExtractedFiles(dest, resultsPath, host, newDataSources);
276  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingExtractedFiles());
277  } catch (IOException | TskCoreException ex) {
278  errorList.add(ex.getMessage());
279  LOGGER.log(Level.SEVERE, String.format("Failed to add datasource: %s", ex.getMessage()), ex); // NON-NLS
280  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
281  return;
282  }
283  } else {
284  createVHD = true;
285  // ingest the VHDs
286  try {
287  synchronized (addMultipleImagesLock) {
288  if (cancelled) {
289  LOGGER.log(Level.SEVERE, "Add VHD cancelled"); // NON-NLS
290  errorList.add(Bundle.AddLogicalImageTask_addImageCancelled());
291  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
292  return;
293  }
294  addMultipleImagesTask = new AddMultipleImagesTask(deviceId, imagePaths, timeZone, host, progressMonitor);
295  }
296  addMultipleImagesTask.run();
297  if (addMultipleImagesTask.getResult() == DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS) {
298  LOGGER.log(Level.SEVERE, "Failed to add VHD datasource"); // NON-NLS
299  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, addMultipleImagesTask.getErrorMessages(), emptyDataSources);
300  return;
301  }
302  try {
303  interestingFileMap = getInterestingFileMapForVHD(Paths.get(dest.toString(), resultsFilename));
304  } catch (TskCoreException | IOException ex) {
305  errorList.add(Bundle.AddLogicalImageTask_failedToAddInterestingFiles(ex.getMessage()));
306  LOGGER.log(Level.SEVERE, "Failed to add interesting files", ex); // NON-NLS
307  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.NONCRITICAL_ERRORS, errorList, emptyDataSources);
308  }
309 
310  } catch (NoCurrentCaseException ex) {
311  String msg = Bundle.AddLogicalImageTask_noCurrentCase();
312  errorList.add(msg);
313  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
314  return;
315  }
316  }
317 
318  if (cancelled) {
319  if (!createVHD) {
320  // TODO: When 5453 is fixed, we should be able to delete it when adding VHD.
321  deleteDestinationDirectory();
322  }
323  errorList.add(Bundle.AddLogicalImageTask_addImageCancelled());
324  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
325  return;
326  }
327 
328  try {
329  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingInterestingFiles());
330  addInterestingFiles(interestingFileMap);
331  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingInterestingFiles());
332  if (createVHD) {
333  callback.done(addMultipleImagesTask.getResult(), addMultipleImagesTask.getErrorMessages(), addMultipleImagesTask.getNewDataSources());
334  } else {
335  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS, errorList, newDataSources);
336  }
337  } catch (IOException | TskCoreException ex) {
338  errorList.add(Bundle.AddLogicalImageTask_failedToAddInterestingFiles(ex.getMessage()));
339  LOGGER.log(Level.SEVERE, "Failed to add interesting files", ex); // NON-NLS
340  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.NONCRITICAL_ERRORS, errorList, emptyDataSources);
341  }
342  }
343 
353  @Messages({
354  "# {0} - file", "# {1} - exception message", "AddLogicalImageTask.failedToAddReport=Failed to add report {0}. Reason= {1}"
355  })
356  private String addReport(Path reportPath, String reportName) {
357  if (!reportPath.toFile().exists()) {
358  return null; // if the reportPath doesn't exist, just ignore it.
359  }
360  try {
361  Case.getCurrentCase().addReport(reportPath.toString(), "LogicalImager", reportName); //NON-NLS
362  return null;
363  } catch (TskCoreException ex) {
364  String msg = Bundle.AddLogicalImageTask_failedToAddReport(reportPath.toString(), ex.getMessage());
365  LOGGER.log(Level.SEVERE, String.format("Failed to add report %s. Reason= %s", reportPath.toString(), ex.getMessage()), ex); // NON-NLS
366  return msg;
367  }
368  }
369 
374  void cancelTask() {
375  LOGGER.log(Level.WARNING, "AddLogicalImageTask cancelled, processing may be incomplete"); // NON-NLS
376  synchronized (addMultipleImagesLock) {
377  cancelled = true;
378  if (addMultipleImagesTask != null) {
379  addMultipleImagesTask.cancelTask();
380  }
381  }
382  }
383 
384  private Map<String, Long> imagePathsToDataSourceObjId(Map<Long, List<String>> imagePaths) {
385  Map<String, Long> imagePathToObjId = new HashMap<>();
386  for (Map.Entry<Long, List<String>> entry : imagePaths.entrySet()) {
387  Long key = entry.getKey();
388  List<String> names = entry.getValue();
389  for (String name : names) {
390  imagePathToObjId.put(name, key);
391  }
392  }
393  return imagePathToObjId;
394  }
395 
396  @Messages({
397  "# {0} - line number", "# {1} - fields length", "# {2} - expected length", "AddLogicalImageTask.notEnoughFields=File does not contain enough fields at line {0}, got {1}, expecting {2}",
398  "# {0} - target image path", "AddLogicalImageTask.cannotFindDataSourceObjId=Cannot find obj_id in tsk_image_names for {0}",
399  "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingInterestingFile=Adding interesting files ({0}/{1})",
400  "AddLogicalImageTask.logicalImagerResults=Logical Imager results"
401  })
402  private void addInterestingFiles(Map<String, List<FileId>> interestingFileMap) throws IOException, TskCoreException {
403  int lineNumber = 0;
404  List<BlackboardArtifact> artifacts = new ArrayList<>();
405 
406  Iterator<Map.Entry<String, List<FileId>>> iterator = interestingFileMap.entrySet().iterator();
407  while (iterator.hasNext()) {
408 
409  if (cancelled) {
410  // Don't delete destination directory once we started adding interesting files.
411  // At this point the database and destination directory are complete.
412  break;
413  }
414 
415  Map.Entry<String, List<FileId>> entry = iterator.next();
416  String key = entry.getKey();
417  String ruleName;
418  String[] split = key.split("\t");
419  ruleName = split[1];
420 
421  List<FileId> fileIds = entry.getValue();
422  for (FileId fileId : fileIds) {
423  if (cancelled) {
424  postArtifacts(artifacts);
425  return;
426  }
427  if (lineNumber % REPORT_PROGRESS_INTERVAL == 0) {
428  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingInterestingFile(lineNumber, totalFiles));
429  }
430  if (lineNumber % POST_ARTIFACT_INTERVAL == 0) {
431  postArtifacts(artifacts);
432  artifacts.clear();
433  }
434  addInterestingFileToArtifacts(fileId.getFileId(), fileId.getDataSourceId(), Bundle.AddLogicalImageTask_logicalImagerResults(), ruleName, artifacts);
435  lineNumber++;
436  }
437  iterator.remove();
438  }
439  postArtifacts(artifacts);
440  }
441 
442  private void addInterestingFileToArtifacts(long fileId, long dataSourceId, String ruleSetName, String ruleName, List<BlackboardArtifact> artifacts) throws TskCoreException {
443  BlackboardArtifact artifact;
444  try {
445  artifact = this.blackboard.newAnalysisResult(
446  BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, fileId, dataSourceId,
447  Score.SCORE_LIKELY_NOTABLE,
448  null, ruleSetName, null,
449  Arrays.asList(
450  new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, ruleSetName),
451  new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, MODULE_NAME, ruleName)
452  ))
453  .getAnalysisResult();
454  } catch (Blackboard.BlackboardException ex) {
455  throw new TskCoreException("Unable to create analysis result.", ex);
456  }
457 
458  artifacts.add(artifact);
459  }
460 
461  @Messages({
462  "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.searchingInterestingFile=Searching for interesting files ({0}/{1})"
463  })
464  private Map<String, List<FileId>> getInterestingFileMapForVHD(Path resultsPath) throws TskCoreException, IOException {
465  Map<Long, List<String>> objIdToimagePathsMap = currentCase.getSleuthkitCase().getImagePaths();
466  imagePathToObjIdMap = imagePathsToDataSourceObjId(objIdToimagePathsMap);
467  Map<String, List<FileId>> interestingFileMap = new HashMap<>();
468 
469  try (BufferedReader br = new BufferedReader(new InputStreamReader(
470  new FileInputStream(resultsPath.toFile()), "UTF8"))) { // NON-NLS
471  String line;
472  br.readLine(); // skip the header line
473  int lineNumber = 2;
474  while ((line = br.readLine()) != null) {
475  if (cancelled) {
476  // Don't delete destination directory once we started adding interesting files.
477  // At this point the database and destination directory are complete.
478  break;
479  }
480  String[] fields = line.split("\t", -1); // NON-NLS
481  if (fields.length != 14) {
482  throw new IOException(Bundle.AddLogicalImageTask_notEnoughFields(lineNumber, fields.length, 14));
483  }
484  String vhdFilename = fields[0];
485 // String fileSystemOffsetStr = fields[1];
486  String fileMetaAddressStr = fields[2];
487 // String extractStatusStr = fields[3];
488  String ruleSetName = fields[4];
489  String ruleName = fields[5];
490 // String description = fields[6];
491  String filename = fields[7];
492  String parentPath = fields[8];
493 
494  if (lineNumber % REPORT_PROGRESS_INTERVAL == 0) {
495  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_searchingInterestingFile(lineNumber, totalFiles));
496  }
497 
498  String query = makeQuery(vhdFilename, fileMetaAddressStr, parentPath, filename);
499  List<AbstractFile> matchedFiles = Case.getCurrentCase().getSleuthkitCase().findAllFilesWhere(query);
500  List<FileId> fileIds = new ArrayList<>();
501  for (AbstractFile file : matchedFiles) {
502  fileIds.add(new FileId(file.getDataSourceObjectId(), file.getId()));
503  }
504  String key = String.format("%s\t%s", ruleSetName, ruleName);
505  interestingFileMap.computeIfAbsent(key, (k) -> new ArrayList<>())
506  .addAll(fileIds);
507 
508  lineNumber++;
509  } // end reading file
510  }
511  return interestingFileMap;
512  }
513 
514  private void postArtifacts(List<BlackboardArtifact> artifacts) {
515  try {
516  // index the artifact for keyword search
517  blackboard.postArtifacts(artifacts, MODULE_NAME);
518  } catch (Blackboard.BlackboardException ex) {
519  LOGGER.log(Level.SEVERE, "Unable to post artifacts to blackboard", ex); //NON-NLS
520  }
521  }
522 
523  @Messages({
524  "# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingExtractedFile=Adding extracted files ({0}/{1})"
525  })
526  private Map<String, List<FileId>> addExtractedFiles(File src, Path resultsPath, Host host, List<Content> newDataSources) throws TskCoreException, IOException {
527  SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
528  SleuthkitCase.CaseDbTransaction trans = null;
529  Map<String, List<FileId>> interestingFileMap = new HashMap<>();
530 
531  try {
532  trans = skCase.beginTransaction();
533  LocalFilesDataSource localFilesDataSource = skCase.addLocalFilesDataSource(deviceId, this.src.getName(), timeZone, host, trans);
534  LocalFileImporter fileImporter = new LocalFileImporter(skCase, trans);
535 
536  try (BufferedReader br = new BufferedReader(new InputStreamReader(
537  new FileInputStream(resultsPath.toFile()), "UTF8"))) { // NON-NLS
538  String line;
539  br.readLine(); // skip the header line
540  int lineNumber = 2;
541  while ((line = br.readLine()) != null) {
542  if (cancelled) {
543  rollbackTransaction(trans);
544  return new HashMap<>();
545  }
546  String[] fields = line.split("\t", -1); // NON-NLS
547  if (fields.length != 14) {
548  rollbackTransaction(trans);
549  throw new IOException(Bundle.AddLogicalImageTask_notEnoughFields(lineNumber, fields.length, 14));
550  }
551  String vhdFilename = fields[0];
552 // String fileSystemOffsetStr = fields[1];
553 // String fileMetaAddressStr = fields[2];
554 // String extractStatusStr = fields[3];
555  String ruleSetName = fields[4];
556  String ruleName = fields[5];
557 // String description = fields[6];
558  String filename = fields[7];
559  String parentPath = fields[8];
560  String extractedFilePath = fields[9];
561  String crtime = fields[10];
562  String mtime = fields[11];
563  String atime = fields[12];
564  String ctime = fields[13];
565  parentPath = ROOT_STR + "/" + vhdFilename + "/" + parentPath;
566 
567  if (lineNumber % REPORT_PROGRESS_INTERVAL == 0) {
568  progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingExtractedFile(lineNumber, totalFiles));
569  }
570 
571  //addLocalFile here
572  AbstractFile fileAdded = fileImporter.addLocalFile(
573  Paths.get(src.toString(), extractedFilePath).toFile(),
574  filename,
575  parentPath,
576  Long.parseLong(ctime),
577  Long.parseLong(crtime),
578  Long.parseLong(atime),
579  Long.parseLong(mtime),
580  localFilesDataSource);
581  String key = String.format("%s\t%s", ruleSetName, ruleName);
582 
583  long dataSourceId = fileAdded.getDataSourceObjectId();
584  long fileId = fileAdded.getId();
585  interestingFileMap.computeIfAbsent(key, (k) -> new ArrayList<>())
586  .add(new FileId(dataSourceId, fileId));
587  lineNumber++;
588  } // end reading file
589  }
590  trans.commit();
591  newDataSources.add(localFilesDataSource);
592  return interestingFileMap;
593 
594  } catch (NumberFormatException | TskCoreException ex) {
595  LOGGER.log(Level.SEVERE, "Error adding extracted files", ex); // NON-NLS
596  rollbackTransaction(trans);
597  throw new TskCoreException("Error adding extracted files", ex);
598  }
599  }
600 
601  private void rollbackTransaction(SleuthkitCase.CaseDbTransaction trans) throws TskCoreException {
602  if (null != trans) {
603  try {
604  trans.rollback();
605  } catch (TskCoreException ex) {
606  LOGGER.log(Level.SEVERE, String.format("Failed to rollback transaction: %s", ex.getMessage()), ex); // NON-NLS
607  }
608  }
609  }
610 
611  private boolean deleteDestinationDirectory() {
612  try {
613  FileUtils.deleteDirectory(dest);
614  LOGGER.log(Level.INFO, String.format("Cancellation: Deleted directory %s", dest.toString())); // NON-NLS
615  return true;
616  } catch (IOException ex) {
617  LOGGER.log(Level.WARNING, String.format("Cancellation: Failed to delete directory %s", dest.toString()), ex); // NON-NLS
618  return false;
619  }
620  }
621 
622  String makeQuery(String vhdFilename, String fileMetaAddressStr, String parentPath, String filename) throws TskCoreException {
623  String query;
624  String targetImagePath = Paths.get(dest.toString(), vhdFilename).toString();
625  Long dataSourceObjId = imagePathToObjIdMap.get(targetImagePath);
626  if (dataSourceObjId == null) {
627  throw new TskCoreException(Bundle.AddLogicalImageTask_cannotFindDataSourceObjId(targetImagePath));
628  }
629  query = String.format("data_source_obj_id = '%s' AND meta_addr = '%s' AND name = '%s'", // NON-NLS
630  dataSourceObjId.toString(), fileMetaAddressStr, filename.replace("'", "''"));
631  // TODO - findAllFilesWhere should SQL-escape the query
632  return query;
633  }
634 
635 }

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.