19package org.sleuthkit.autopsy.logicalimager.dsp;
21import java.util.ArrayList;
23import java.util.logging.Level;
24import javax.annotation.concurrent.GuardedBy;
25import org.openide.util.NbBundle.Messages;
26import org.sleuthkit.autopsy.casemodule.Case;
27import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
28import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
29import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
30import org.sleuthkit.autopsy.coreutils.Logger;
31import org.sleuthkit.datamodel.Content;
32import org.sleuthkit.datamodel.DefaultAddDataSourceCallbacks;
33import org.sleuthkit.datamodel.Host;
34import org.sleuthkit.datamodel.Image;
35import org.sleuthkit.datamodel.SleuthkitCase;
36import org.sleuthkit.datamodel.SleuthkitJNI;
37import org.sleuthkit.datamodel.TskCoreException;
38import org.sleuthkit.datamodel.TskDataException;
39import org.sleuthkit.datamodel.TskFileRange;
47 "AddMultipleImagesTask.fsTypeUnknownErr=Cannot determine file system type"
49class AddMultipleImagesTask implements Runnable {
52 public static final String TSK_FS_TYPE_UNKNOWN_ERR_MSG = Bundle.AddMultipleImagesTask_fsTypeUnknownErr();
53 private static final long TWO_GB = 2000000000L;
54 private final String deviceId;
55 private final List<String> imageFilePaths;
56 private final String timeZone;
57 private final Host host;
58 private final long chunkSize = TWO_GB;
60 private final Case currentCase;
61 private boolean criticalErrorOccurred;
62 private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess =
null;
63 private List<String> errorMessages =
new ArrayList<>();
65 private List<Content> newDataSources =
new ArrayList<>();
66 private Image currentImage =
null;
74 private final Object tskAddImageProcessLock;
75 @GuardedBy(
"tskAddImageProcessLock")
76 private
boolean tskAddImageProcessStopped;
97 "# {0} - file",
"AddMultipleImagesTask.addingFileAsLogicalFile=Adding: {0} as an unallocated space file.",
98 "# {0} - deviceId",
"# {1} - exceptionMessage",
99 "AddMultipleImagesTask.errorAddingImgWithoutFileSystem=Error adding images without file systems for device {0}: {1}",})
100 AddMultipleImagesTask(String deviceId, List<String> imageFilePaths, String timeZone, Host host,
102 this.deviceId = deviceId;
103 this.imageFilePaths = imageFilePaths;
104 this.timeZone = timeZone;
106 this.progressMonitor = progressMonitor;
108 this.criticalErrorOccurred =
false;
109 tskAddImageProcessLock =
new Object();
113 "AddMultipleImagesTask.cancelled=Cancellation: Add image process reverted",
114 "# {0} - image path",
115 "AddMultipleImagesTask.imageError=Error adding image {0} to the database"
119 errorMessages =
new ArrayList<>();
120 newDataSources =
new ArrayList<>();
121 List<Content> emptyDataSources =
new ArrayList<>();
126 List<String> corruptedImageFilePaths =
new ArrayList<>();
127 progressMonitor.setIndeterminate(
true);
128 for (String imageFilePath : imageFilePaths) {
130 currentImage = SleuthkitJNI.addImageToDatabase(currentCase.getSleuthkitCase(),
new String[]{imageFilePath},
131 0, timeZone,
"",
"",
"", deviceId, host);
132 }
catch (TskCoreException ex) {
133 LOGGER.log(Level.SEVERE,
"Error adding image " + imageFilePath +
" to database", ex);
134 errorMessages.add(Bundle.AddMultipleImagesTask_imageError(imageFilePath));
138 synchronized (tskAddImageProcessLock) {
140 if (!tskAddImageProcessStopped) {
141 addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone,
false,
false,
"");
146 run(imageFilePath, currentImage, corruptedImageFilePaths, errorMessages);
147 finishAddImageProcess(imageFilePath, errorMessages, newDataSources);
148 synchronized (tskAddImageProcessLock) {
149 if (tskAddImageProcessStopped) {
150 errorMessages.add(Bundle.AddMultipleImagesTask_cancelled());
152 newDataSources = emptyDataSources;
163 if (!tskAddImageProcessStopped && !corruptedImageFilePaths.isEmpty()) {
164 SleuthkitCase caseDatabase;
165 caseDatabase = currentCase.getSleuthkitCase();
167 progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_addingFileAsLogicalFile(corruptedImageFilePaths.toString()));
169 Image dataSource = caseDatabase.addImageInfo(0, corruptedImageFilePaths, timeZone);
170 newDataSources.add(dataSource);
171 List<TskFileRange> fileRanges =
new ArrayList<>();
173 long imageSize = dataSource.getSize();
177 if (chunkSize > 0 && imageSize >= TWO_GB) {
178 for (
double size = TWO_GB; size < dataSource.getSize(); size += TWO_GB) {
179 fileRanges.add(
new TskFileRange(start, TWO_GB, sequence));
184 double leftoverSize = imageSize - sequence * TWO_GB;
185 fileRanges.add(
new TskFileRange(start, (
long)leftoverSize, sequence));
187 caseDatabase.addLayoutFiles(dataSource, fileRanges);
188 }
catch (TskCoreException ex) {
189 errorMessages.add(Bundle.AddMultipleImagesTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage()));
190 criticalErrorOccurred =
true;
198 progressMonitor.setProgress(0);
199 progressMonitor.setProgress(100);
201 if (criticalErrorOccurred) {
203 }
else if (!errorMessages.isEmpty()) {
215 LOGGER.log(Level.WARNING,
"AddMultipleImagesTask cancelled, processing may be incomplete");
216 synchronized (tskAddImageProcessLock) {
217 tskAddImageProcessStopped =
true;
218 if (addImageProcess !=
null) {
228 addImageProcess.stop();
229 }
catch (TskCoreException ex) {
230 LOGGER.log(Level.SEVERE,
"Cancellation: addImagePRocess.stop failed", ex);
251 "# {0} - imageFilePath",
"AddMultipleImagesTask.adding=Adding: {0}",
252 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.criticalErrorAdding=Critical error adding {0} for device {1}: {2}",
253 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.criticalErrorReverting=Critical error reverting add image process for {0} for device {1}: {2}",
254 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.nonCriticalErrorAdding=Non-critical error adding {0} for device {1}: {2}",})
255 private void run(String imageFilePath, Image image, List<String> corruptedImageFilePaths, List<String> errorMessages) {
259 progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_adding(imageFilePath));
261 addImageProcess.run(deviceId, image, 0,
new DefaultAddDataSourceCallbacks());
262 }
catch (TskCoreException ex) {
263 if (ex.getMessage().contains(TSK_FS_TYPE_UNKNOWN_ERR_MSG)) {
270 corruptedImageFilePaths.add(imageFilePath);
272 errorMessages.add(Bundle.AddMultipleImagesTask_criticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
273 criticalErrorOccurred =
true;
275 }
catch (TskDataException ex) {
276 errorMessages.add(Bundle.AddMultipleImagesTask_nonCriticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
292 private void finishAddImageProcess(String imageFilePath, List<String> errorMessages, List<Content> newDataSources) {
293 synchronized (tskAddImageProcessLock) {
298 newDataSources.add(currentImage);
301 if (tskAddImageProcessStopped) {
309 String verificationError = currentImage.verifyImageSize();
310 if (!verificationError.isEmpty()) {
311 errorMessages.add(Bundle.AddMultipleImagesTask_nonCriticalErrorAdding(imageFilePath, deviceId, verificationError));
320 public List<String> getErrorMessages() {
321 return errorMessages;
336 public List<Content> getNewDataSources() {
337 return newDataSources;
static Case getCurrentCaseThrows()
synchronized static Logger getLogger(String name)