19 package org.sleuthkit.autopsy.logicalimager.dsp;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.logging.Level;
24 import javax.annotation.concurrent.GuardedBy;
25 import org.openide.util.NbBundle.Messages;
45 "AddMultipleImagesTask.fsTypeUnknownErr=Cannot determine file system type"
47 class AddMultipleImagesTask implements Runnable {
49 private static final Logger LOGGER = Logger.getLogger(AddMultipleImagesTask.class.getName());
50 public static final String TSK_FS_TYPE_UNKNOWN_ERR_MSG = Bundle.AddMultipleImagesTask_fsTypeUnknownErr();
51 private static final long TWO_GB = 2000000000L;
52 private final String deviceId;
53 private final List<String> imageFilePaths;
54 private final String timeZone;
55 private final long chunkSize = TWO_GB;
56 private final DataSourceProcessorProgressMonitor progressMonitor;
57 private final Case currentCase;
58 private boolean criticalErrorOccurred;
59 private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess = null;
60 private List<String> errorMessages =
new ArrayList<>();
61 private DataSourceProcessorResult result;
62 private List<Content> newDataSources =
new ArrayList<>();
70 private final Object tskAddImageProcessLock;
71 @GuardedBy(
"tskAddImageProcessLock")
72 private
boolean tskAddImageProcessStopped;
92 "# {0} - file",
"AddMultipleImagesTask.addingFileAsLogicalFile=Adding: {0} as an unallocated space file.",
93 "# {0} - deviceId",
"# {1} - exceptionMessage",
94 "AddMultipleImagesTask.errorAddingImgWithoutFileSystem=Error adding images without file systems for device {0}: {1}",})
95 AddMultipleImagesTask(String deviceId, List<String> imageFilePaths, String timeZone,
96 DataSourceProcessorProgressMonitor progressMonitor)
throws NoCurrentCaseException {
97 this.deviceId = deviceId;
98 this.imageFilePaths = imageFilePaths;
99 this.timeZone = timeZone;
100 this.progressMonitor = progressMonitor;
101 currentCase = Case.getCurrentCaseThrows();
102 this.criticalErrorOccurred =
false;
103 tskAddImageProcessLock =
new Object();
107 "AddMultipleImagesTask.cancelled=Cancellation: Add image process reverted",
111 errorMessages =
new ArrayList<>();
112 newDataSources =
new ArrayList<>();
113 List<Content> emptyDataSources =
new ArrayList<>();
118 List<String> corruptedImageFilePaths =
new ArrayList<>();
119 progressMonitor.setIndeterminate(
true);
120 for (String imageFilePath : imageFilePaths) {
121 synchronized (tskAddImageProcessLock) {
122 if (!tskAddImageProcessStopped) {
123 addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone,
false,
false,
"");
128 run(imageFilePath, corruptedImageFilePaths, errorMessages);
129 commitOrRevertAddImageProcess(imageFilePath, errorMessages, newDataSources);
130 synchronized (tskAddImageProcessLock) {
131 if (tskAddImageProcessStopped) {
132 errorMessages.add(Bundle.AddMultipleImagesTask_cancelled());
133 result = DataSourceProcessorResult.CRITICAL_ERRORS;
134 newDataSources = emptyDataSources;
145 if (!tskAddImageProcessStopped && !corruptedImageFilePaths.isEmpty()) {
146 SleuthkitCase caseDatabase;
147 caseDatabase = currentCase.getSleuthkitCase();
149 progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_addingFileAsLogicalFile(corruptedImageFilePaths.toString()));
151 Image dataSource = caseDatabase.addImageInfo(0, corruptedImageFilePaths, timeZone);
152 newDataSources.add(dataSource);
153 List<TskFileRange> fileRanges =
new ArrayList<>();
155 long imageSize = dataSource.getSize();
159 if (chunkSize > 0 && imageSize >= TWO_GB) {
160 for (
double size = TWO_GB; size < dataSource.getSize(); size += TWO_GB) {
161 fileRanges.add(
new TskFileRange(start, TWO_GB, sequence));
166 double leftoverSize = imageSize - sequence * TWO_GB;
167 fileRanges.add(
new TskFileRange(start, (
long)leftoverSize, sequence));
169 caseDatabase.addLayoutFiles(dataSource, fileRanges);
170 }
catch (TskCoreException ex) {
171 errorMessages.add(Bundle.AddMultipleImagesTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage()));
172 criticalErrorOccurred =
true;
180 progressMonitor.setProgress(0);
181 progressMonitor.setProgress(100);
183 if (criticalErrorOccurred) {
184 result = DataSourceProcessorResult.CRITICAL_ERRORS;
185 }
else if (!errorMessages.isEmpty()) {
186 result = DataSourceProcessorResult.NONCRITICAL_ERRORS;
188 result = DataSourceProcessorResult.NO_ERRORS;
197 LOGGER.log(Level.WARNING,
"AddMultipleImagesTask cancelled, processing may be incomplete");
198 synchronized (tskAddImageProcessLock) {
199 tskAddImageProcessStopped =
true;
200 if (addImageProcess != null) {
210 addImageProcess.stop();
211 }
catch (TskCoreException ex) {
212 LOGGER.log(Level.SEVERE,
"Cancellation: addImagePRocess.stop failed", ex);
232 "# {0} - imageFilePath",
"AddMultipleImagesTask.adding=Adding: {0}",
233 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.criticalErrorAdding=Critical error adding {0} for device {1}: {2}",
234 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.criticalErrorReverting=Critical error reverting add image process for {0} for device {1}: {2}",
235 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.nonCriticalErrorAdding=Non-critical error adding {0} for device {1}: {2}",})
236 private void run(String imageFilePath, List<String> corruptedImageFilePaths, List<String> errorMessages) {
240 progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_adding(imageFilePath));
242 addImageProcess.run(deviceId,
new String[]{imageFilePath});
243 }
catch (TskCoreException ex) {
244 if (ex.getMessage().contains(TSK_FS_TYPE_UNKNOWN_ERR_MSG)) {
251 corruptedImageFilePaths.add(imageFilePath);
253 errorMessages.add(Bundle.AddMultipleImagesTask_criticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
254 criticalErrorOccurred =
true;
256 }
catch (TskDataException ex) {
257 errorMessages.add(Bundle.AddMultipleImagesTask_nonCriticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
273 private void commitOrRevertAddImageProcess(String imageFilePath, List<String> errorMessages, List<Content> newDataSources) {
274 synchronized (tskAddImageProcessLock) {
275 if (tskAddImageProcessStopped || criticalErrorOccurred) {
277 addImageProcess.revert();
278 }
catch (TskCoreException ex) {
279 errorMessages.add(Bundle.AddMultipleImagesTask_criticalErrorReverting(imageFilePath, deviceId, ex.getLocalizedMessage()));
280 criticalErrorOccurred =
true;
291 long imageId = addImageProcess.commit();
292 Image dataSource = currentCase.getSleuthkitCase().getImageById(imageId);
293 newDataSources.add(dataSource);
299 String verificationError = dataSource.verifyImageSize();
300 if (!verificationError.isEmpty()) {
301 errorMessages.add(Bundle.AddMultipleImagesTask_nonCriticalErrorAdding(imageFilePath, deviceId, verificationError));
303 }
catch (TskCoreException ex) {
309 errorMessages.add(Bundle.AddMultipleImagesTask_criticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
310 criticalErrorOccurred =
true;
319 public List<String> getErrorMessages() {
320 return errorMessages;
327 public DataSourceProcessorResult getResult() {
335 public List<Content> getNewDataSources() {
336 return newDataSources;