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;
32 import org.
sleuthkit.datamodel.DefaultAddDataSourceCallbacks;
46 "AddMultipleImagesTask.fsTypeUnknownErr=Cannot determine file system type"
48 class AddMultipleImagesTask implements Runnable {
50 private static final Logger LOGGER = Logger.getLogger(AddMultipleImagesTask.class.getName());
51 public static final String TSK_FS_TYPE_UNKNOWN_ERR_MSG = Bundle.AddMultipleImagesTask_fsTypeUnknownErr();
52 private static final long TWO_GB = 2000000000L;
53 private final String deviceId;
54 private final List<String> imageFilePaths;
55 private final String timeZone;
56 private final long chunkSize = TWO_GB;
57 private final DataSourceProcessorProgressMonitor progressMonitor;
58 private final Case currentCase;
59 private boolean criticalErrorOccurred;
60 private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess = null;
61 private List<String> errorMessages =
new ArrayList<>();
62 private DataSourceProcessorResult result;
63 private List<Content> newDataSources =
new ArrayList<>();
64 private Image currentImage = null;
72 private final Object tskAddImageProcessLock;
73 @GuardedBy(
"tskAddImageProcessLock")
74 private
boolean tskAddImageProcessStopped;
94 "# {0} - file",
"AddMultipleImagesTask.addingFileAsLogicalFile=Adding: {0} as an unallocated space file.",
95 "# {0} - deviceId",
"# {1} - exceptionMessage",
96 "AddMultipleImagesTask.errorAddingImgWithoutFileSystem=Error adding images without file systems for device {0}: {1}",})
97 AddMultipleImagesTask(String deviceId, List<String> imageFilePaths, String timeZone,
98 DataSourceProcessorProgressMonitor progressMonitor)
throws NoCurrentCaseException {
99 this.deviceId = deviceId;
100 this.imageFilePaths = imageFilePaths;
101 this.timeZone = timeZone;
102 this.progressMonitor = progressMonitor;
103 currentCase = Case.getCurrentCaseThrows();
104 this.criticalErrorOccurred =
false;
105 tskAddImageProcessLock =
new Object();
109 "AddMultipleImagesTask.cancelled=Cancellation: Add image process reverted",
110 "# {0} - image path",
111 "AddMultipleImagesTask.imageError=Error adding image {0} to the database"
115 errorMessages =
new ArrayList<>();
116 newDataSources =
new ArrayList<>();
117 List<Content> emptyDataSources =
new ArrayList<>();
122 List<String> corruptedImageFilePaths =
new ArrayList<>();
123 progressMonitor.setIndeterminate(
true);
124 for (String imageFilePath : imageFilePaths) {
126 currentImage = SleuthkitJNI.addImageToDatabase(currentCase.getSleuthkitCase(),
new String[]{imageFilePath},
127 0, timeZone,
"",
"",
"", deviceId);
128 }
catch (TskCoreException ex) {
129 LOGGER.log(Level.SEVERE,
"Error adding image " + imageFilePath +
" to database", ex);
130 errorMessages.add(Bundle.AddMultipleImagesTask_imageError(imageFilePath));
131 result = DataSourceProcessorResult.CRITICAL_ERRORS;
134 synchronized (tskAddImageProcessLock) {
136 if (!tskAddImageProcessStopped) {
137 addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone,
false,
false,
"");
142 run(imageFilePath, currentImage, corruptedImageFilePaths, errorMessages);
143 finishAddImageProcess(imageFilePath, errorMessages, newDataSources);
144 synchronized (tskAddImageProcessLock) {
145 if (tskAddImageProcessStopped) {
146 errorMessages.add(Bundle.AddMultipleImagesTask_cancelled());
147 result = DataSourceProcessorResult.CRITICAL_ERRORS;
148 newDataSources = emptyDataSources;
159 if (!tskAddImageProcessStopped && !corruptedImageFilePaths.isEmpty()) {
160 SleuthkitCase caseDatabase;
161 caseDatabase = currentCase.getSleuthkitCase();
163 progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_addingFileAsLogicalFile(corruptedImageFilePaths.toString()));
165 Image dataSource = caseDatabase.addImageInfo(0, corruptedImageFilePaths, timeZone);
166 newDataSources.add(dataSource);
167 List<TskFileRange> fileRanges =
new ArrayList<>();
169 long imageSize = dataSource.getSize();
173 if (chunkSize > 0 && imageSize >= TWO_GB) {
174 for (
double size = TWO_GB; size < dataSource.getSize(); size += TWO_GB) {
175 fileRanges.add(
new TskFileRange(start, TWO_GB, sequence));
180 double leftoverSize = imageSize - sequence * TWO_GB;
181 fileRanges.add(
new TskFileRange(start, (
long)leftoverSize, sequence));
183 caseDatabase.addLayoutFiles(dataSource, fileRanges);
184 }
catch (TskCoreException ex) {
185 errorMessages.add(Bundle.AddMultipleImagesTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage()));
186 criticalErrorOccurred =
true;
194 progressMonitor.setProgress(0);
195 progressMonitor.setProgress(100);
197 if (criticalErrorOccurred) {
198 result = DataSourceProcessorResult.CRITICAL_ERRORS;
199 }
else if (!errorMessages.isEmpty()) {
200 result = DataSourceProcessorResult.NONCRITICAL_ERRORS;
202 result = DataSourceProcessorResult.NO_ERRORS;
211 LOGGER.log(Level.WARNING,
"AddMultipleImagesTask cancelled, processing may be incomplete");
212 synchronized (tskAddImageProcessLock) {
213 tskAddImageProcessStopped =
true;
214 if (addImageProcess != null) {
224 addImageProcess.stop();
225 }
catch (TskCoreException ex) {
226 LOGGER.log(Level.SEVERE,
"Cancellation: addImagePRocess.stop failed", ex);
247 "# {0} - imageFilePath",
"AddMultipleImagesTask.adding=Adding: {0}",
248 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.criticalErrorAdding=Critical error adding {0} for device {1}: {2}",
249 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.criticalErrorReverting=Critical error reverting add image process for {0} for device {1}: {2}",
250 "# {0} - imageFilePath",
"# {1} - deviceId",
"# {2} - exceptionMessage",
"AddMultipleImagesTask.nonCriticalErrorAdding=Non-critical error adding {0} for device {1}: {2}",})
251 private void run(String imageFilePath, Image image, List<String> corruptedImageFilePaths, List<String> errorMessages) {
255 progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_adding(imageFilePath));
257 addImageProcess.run(deviceId, image, 0,
new DefaultAddDataSourceCallbacks());
258 }
catch (TskCoreException ex) {
259 if (ex.getMessage().contains(TSK_FS_TYPE_UNKNOWN_ERR_MSG)) {
266 corruptedImageFilePaths.add(imageFilePath);
268 errorMessages.add(Bundle.AddMultipleImagesTask_criticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
269 criticalErrorOccurred =
true;
271 }
catch (TskDataException ex) {
272 errorMessages.add(Bundle.AddMultipleImagesTask_nonCriticalErrorAdding(imageFilePath, deviceId, ex.getLocalizedMessage()));
288 private void finishAddImageProcess(String imageFilePath, List<String> errorMessages, List<Content> newDataSources) {
289 synchronized (tskAddImageProcessLock) {
294 newDataSources.add(currentImage);
297 if (tskAddImageProcessStopped) {
305 String verificationError = currentImage.verifyImageSize();
306 if (!verificationError.isEmpty()) {
307 errorMessages.add(Bundle.AddMultipleImagesTask_nonCriticalErrorAdding(imageFilePath, deviceId, verificationError));
316 public List<String> getErrorMessages() {
317 return errorMessages;
324 public DataSourceProcessorResult getResult() {
332 public List<Content> getNewDataSources() {
333 return newDataSources;