mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
fixes
This commit is contained in:
parent
8ae984831b
commit
bed99ecbf6
@ -111,13 +111,8 @@ Case_checkImagePaths_exceptionOccurred=An exception occurred while checking if i
|
||||
# {0} - paths
|
||||
Case_checkImagePaths_noPaths=The following images had no associated paths: {0}
|
||||
# {0} - appplicationName
|
||||
Case_createCaseDatabase_fileLock_concurrentAccessException=The case is open in {0}. Please close it before attempting to open it in Autopsy.
|
||||
Case_createCaseDatabase_fileLock_concurrentAccessException_defaultApp=another application
|
||||
Case_createCaseDatabase_fileLock_ioException=An error occurred while trying to get an exclusive lock on the case.
|
||||
# {0} - appplicationName
|
||||
Case_openCaseDataBase_fileLock_concurrentAccessException=The case is open in {0}. Please close it before attempting to open it in Autopsy.
|
||||
Case_openCaseDataBase_fileLock_concurrentAccessException_defaultApp=another application
|
||||
Case_openCaseDataBase_fileLock_ioException=An error occurred while trying to get an exclusive lock on the case.
|
||||
Case_throwIfConcurrentDbAccessException_fileLock_concurrentAccessException=The case is open in {0}. Please close it before attempting to open it in Autopsy.
|
||||
Case_throwIfConcurrentDbAccessException_fileLock_concurrentAccessException_defaultApp=another application
|
||||
CaseDetailsPanel.casePanel.border.title=Case
|
||||
CaseDetailsPanel.examinerLabel.text=Name:
|
||||
CaseDetailsPanel.examinerPanel.border.title=Examiner
|
||||
|
@ -31,9 +31,7 @@ import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
@ -78,7 +76,6 @@ import org.sleuthkit.autopsy.actions.OpenOutputFolderAction;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService.CaseContext;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseMetadata.CaseMetadataException;
|
||||
import org.sleuthkit.autopsy.casemodule.TskLockResources.ConcurrentDbAccessException;
|
||||
import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryAction;
|
||||
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent;
|
||||
@ -148,6 +145,7 @@ import org.sleuthkit.autopsy.timeline.OpenTimelineAction;
|
||||
import org.sleuthkit.autopsy.timeline.events.TimelineEventAddedEvent;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
|
||||
import org.sleuthkit.datamodel.ConcurrentDbAccessException;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentStreamProvider;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
@ -200,7 +198,6 @@ public class Case {
|
||||
private CollaborationMonitor collaborationMonitor;
|
||||
private Services caseServices;
|
||||
|
||||
private TskLockResources tskLockResources = null;
|
||||
private volatile boolean hasDataSource = false;
|
||||
private volatile boolean hasData = false;
|
||||
|
||||
@ -215,7 +212,6 @@ public class Case {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An enumeration of case types.
|
||||
*/
|
||||
@ -775,7 +771,6 @@ public class Case {
|
||||
|| caseName.contains("<") || caseName.contains(">") || caseName.contains("|"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new case and makes it the current case.
|
||||
*
|
||||
@ -2731,11 +2726,7 @@ public class Case {
|
||||
"Case.progressMessage.creatingCaseDatabase=Creating case database...",
|
||||
"# {0} - exception message", "Case.exceptionMessage.couldNotGetDbServerConnectionInfo=Failed to get case database server conneciton info:\n{0}.",
|
||||
"# {0} - exception message", "Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database:\n{0}.",
|
||||
"# {0} - exception message", "Case.exceptionMessage.couldNotSaveDbNameToMetadataFile=Failed to save case database name to case metadata file:\n{0}.",
|
||||
"Case_createCaseDatabase_fileLock_ioException=An error occurred while trying to get an exclusive lock on the case.",
|
||||
"# {0} - appplicationName",
|
||||
"Case_createCaseDatabase_fileLock_concurrentAccessException=The case is open in {0}. Please close it before attempting to open it in Autopsy.",
|
||||
"Case_createCaseDatabase_fileLock_concurrentAccessException_defaultApp=another application"
|
||||
"# {0} - exception message", "Case.exceptionMessage.couldNotSaveDbNameToMetadataFile=Failed to save case database name to case metadata file:\n{0}."
|
||||
})
|
||||
private void createCaseDatabase(ProgressIndicator progressIndicator) throws CaseActionException {
|
||||
progressIndicator.progress(Bundle.Case_progressMessage_creatingCaseDatabase());
|
||||
@ -2746,17 +2737,7 @@ public class Case {
|
||||
* with a standard name, physically located in the case
|
||||
* directory.
|
||||
*/
|
||||
try {
|
||||
this.tskLockResources = TskLockResources.tryAcquireFileLock(metadata.getCaseDirectory(), UserPreferences.getAppName());
|
||||
} catch (IOException | OverlappingFileLockException ex) {
|
||||
throw new CaseActionException(Bundle.Case_openCaseDataBase_fileLock_ioException(), ex);
|
||||
} catch (ConcurrentDbAccessException ex) {
|
||||
throw new CaseActionException(Bundle.Case_openCaseDataBase_fileLock_concurrentAccessException(
|
||||
StringUtils.defaultIfBlank(ex.getConflictingApplicationName(),
|
||||
Bundle.Case_openCaseDataBase_fileLock_concurrentAccessException_defaultApp())
|
||||
), ex);
|
||||
}
|
||||
caseDb = SleuthkitCase.newCase(Paths.get(metadata.getCaseDirectory(), SINGLE_USER_CASE_DB_NAME).toString());
|
||||
caseDb = SleuthkitCase.newCase(Paths.get(metadata.getCaseDirectory(), SINGLE_USER_CASE_DB_NAME, APP_NAME).toString());
|
||||
metadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
|
||||
} else {
|
||||
/*
|
||||
@ -2768,6 +2749,7 @@ public class Case {
|
||||
metadata.setCaseDatabaseName(caseDb.getDatabaseName());
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
throwIfConcurrentDbAccessException(ex);
|
||||
throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(ex.getLocalizedMessage()), ex);
|
||||
} catch (UserPreferencesException ex) {
|
||||
throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
|
||||
@ -2792,11 +2774,7 @@ public class Case {
|
||||
"# {0} - exception message", "Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database:\n{0}.",
|
||||
"# {0} - exception message", "Case.exceptionMessage.unsupportedSchemaVersionMessage=Unsupported case database schema version:\n{0}.",
|
||||
"Case.exceptionMessage.contentProviderCouldNotBeFound=Content provider was specified for the case but could not be loaded.",
|
||||
"Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-User.",
|
||||
"Case_openCaseDataBase_fileLock_ioException=An error occurred while trying to get an exclusive lock on the case.",
|
||||
"# {0} - appplicationName",
|
||||
"Case_openCaseDataBase_fileLock_concurrentAccessException=The case is open in {0}. Please close it before attempting to open it in Autopsy.",
|
||||
"Case_openCaseDataBase_fileLock_concurrentAccessException_defaultApp=another application"
|
||||
"Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-User."
|
||||
})
|
||||
private void openCaseDataBase(ProgressIndicator progressIndicator) throws CaseActionException {
|
||||
progressIndicator.progress(Bundle.Case_progressMessage_openingCaseDatabase());
|
||||
@ -2812,17 +2790,7 @@ public class Case {
|
||||
}
|
||||
|
||||
if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) {
|
||||
try {
|
||||
this.tskLockResources = TskLockResources.tryAcquireFileLock(metadata.getCaseDirectory(), UserPreferences.getAppName());
|
||||
} catch (IOException | OverlappingFileLockException ex) {
|
||||
throw new CaseActionException(Bundle.Case_openCaseDataBase_fileLock_ioException(), ex);
|
||||
} catch (ConcurrentDbAccessException ex) {
|
||||
throw new CaseActionException(Bundle.Case_openCaseDataBase_fileLock_concurrentAccessException(
|
||||
StringUtils.defaultIfBlank(ex.getConflictingApplicationName(),
|
||||
Bundle.Case_openCaseDataBase_fileLock_concurrentAccessException_defaultApp())
|
||||
), ex);
|
||||
}
|
||||
caseDb = SleuthkitCase.openCase(metadata.getCaseDatabasePath(), contentProvider);
|
||||
caseDb = SleuthkitCase.openCase(metadata.getCaseDatabasePath(), contentProvider, APP_NAME);
|
||||
} else if (UserPreferences.getIsMultiUserModeEnabled()) {
|
||||
caseDb = SleuthkitCase.openCase(databaseName, UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory(), contentProvider);
|
||||
} else {
|
||||
@ -2834,11 +2802,43 @@ public class Case {
|
||||
} catch (UserPreferencesException ex) {
|
||||
throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
|
||||
} catch (TskCoreException ex) {
|
||||
throwIfConcurrentDbAccessException(ex);
|
||||
throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(ex.getLocalizedMessage()), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws a CaseActionException if the exception or any nested exception is a ConcurrentDbAccessException (max depth of 10)
|
||||
* @param ex The exception.
|
||||
* @throws CaseActionException Thrown if there is a concurrent db access exception.
|
||||
*/
|
||||
@Messages({
|
||||
"# {0} - appplicationName",
|
||||
"Case_throwIfConcurrentDbAccessException_fileLock_concurrentAccessException=The case is open in {0}. Please close it before attempting to open it in Autopsy.",
|
||||
"Case_throwIfConcurrentDbAccessException_fileLock_concurrentAccessException_defaultApp=another application"
|
||||
})
|
||||
private void throwIfConcurrentDbAccessException(Exception ex) throws CaseActionException {
|
||||
ConcurrentDbAccessException concurrentEx = null;
|
||||
Throwable curEx = ex;
|
||||
// max depth search for a concurrent db access exception will be 10
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (curEx instanceof ConcurrentDbAccessException foundEx) {
|
||||
concurrentEx = foundEx;
|
||||
break;
|
||||
}
|
||||
curEx = curEx.getCause();
|
||||
}
|
||||
|
||||
if (concurrentEx != null) {
|
||||
throw new CaseActionException(Bundle.Case_throwIfConcurrentDbAccessException_fileLock_concurrentAccessException(
|
||||
StringUtils.defaultIfBlank(concurrentEx.getConflictingApplicationName(),
|
||||
Bundle.Case_throwIfConcurrentDbAccessException_fileLock_concurrentAccessException_defaultApp())
|
||||
), concurrentEx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to load a content provider for the provided arguments. Returns
|
||||
* null if no content provider for the arguments can be identified.
|
||||
@ -3134,15 +3134,6 @@ public class Case {
|
||||
eventPublisher.closeRemoteEventChannel();
|
||||
}
|
||||
|
||||
if (this.tskLockResources != null) {
|
||||
try {
|
||||
this.tskLockResources.close();
|
||||
this.tskLockResources = null;
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.WARNING, "There was an error closing the TSK case lock resources", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow all registered application services providers to close
|
||||
* resources related to the case.
|
||||
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2024 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* The resources associated with the file lock for the TSK database.
|
||||
*/
|
||||
class TskLockResources implements AutoCloseable {
|
||||
|
||||
private static final String LOCK_FILE_NAME = "lock";
|
||||
|
||||
private File lockFile = null;
|
||||
private RandomAccessFile lockFileRaf = null;
|
||||
private FileChannel lockFileChannel = null;
|
||||
private FileLock lockFileLock = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param lockFile The lock file File reference.
|
||||
* @param lockFileRef The lock file random access file reference.
|
||||
* @param lockFileChannel The lock file file channel.
|
||||
* @param lockFileLock The lock file file lock.
|
||||
*/
|
||||
TskLockResources(File lockFile, RandomAccessFile lockFileRaf, FileChannel lockFileChannel, FileLock lockFileLock) {
|
||||
this.lockFile = lockFile;
|
||||
this.lockFileRaf = lockFileRaf;
|
||||
this.lockFileChannel = lockFileChannel;
|
||||
this.lockFileLock = lockFileLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to acquire a lock to the lock file in the case directory.
|
||||
*
|
||||
* @param caseDir The case directory that the autopsy.db is in.
|
||||
* @return The lock file resources to be closed.
|
||||
* @throws IllegalAccessException
|
||||
* @throws IOException
|
||||
*/
|
||||
static TskLockResources tryAcquireFileLock(String caseDir, String applicationName) throws ConcurrentDbAccessException, IOException, OverlappingFileLockException {
|
||||
// get the lock file path
|
||||
File lockFile = new File(caseDir, LOCK_FILE_NAME);
|
||||
// make directories leading up to that
|
||||
lockFile.getParentFile().mkdirs();
|
||||
|
||||
// if the lock file exists
|
||||
if (lockFile.isFile() && !lockFile.canWrite()) {
|
||||
// get the random access file as read only
|
||||
RandomAccessFile lockFileRaf = new RandomAccessFile(lockFile, "r");
|
||||
throw ConcurrentDbAccessException.createForFile(lockFile.getAbsolutePath(), lockFileRaf);
|
||||
} else {
|
||||
RandomAccessFile lockFileRaf = new RandomAccessFile(lockFile, "rw");
|
||||
FileChannel lockFileChannel = lockFileRaf.getChannel();
|
||||
FileLock lockFileLock = lockFileChannel == null
|
||||
? null
|
||||
: lockFileChannel.tryLock(1024L, 1L, false);
|
||||
|
||||
if (lockFileLock != null) {
|
||||
lockFileRaf.setLength(0);
|
||||
lockFileRaf.writeChars(applicationName);
|
||||
return new TskLockResources(lockFile, lockFileRaf, lockFileChannel, lockFileLock);
|
||||
} else {
|
||||
throw ConcurrentDbAccessException.createForFile(lockFile.getAbsolutePath(), lockFileRaf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
// close lock file resources in reverse acquisition order
|
||||
if (this.lockFileLock != null) {
|
||||
this.lockFileLock.close();
|
||||
this.lockFileLock = null;
|
||||
}
|
||||
|
||||
if (this.lockFileChannel != null) {
|
||||
this.lockFileChannel.close();
|
||||
this.lockFileChannel = null;
|
||||
}
|
||||
|
||||
if (this.lockFileRaf != null) {
|
||||
this.lockFileRaf.close();
|
||||
this.lockFileRaf = null;
|
||||
}
|
||||
|
||||
if (this.lockFile != null) {
|
||||
this.lockFile.delete();
|
||||
this.lockFile = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An exception thrown if the database is currently in use.
|
||||
*/
|
||||
static class ConcurrentDbAccessException extends Exception {
|
||||
|
||||
private final String conflictingApplicationName;
|
||||
|
||||
/**
|
||||
* Creates a ConcurrentDbAccessException from the lock file path and the
|
||||
* random access file of that path whose contents are the application
|
||||
* name.
|
||||
*
|
||||
* @param lockFilePath The lock file path.
|
||||
* @param lockFileRaf The lock file random access file.
|
||||
* @return The exception
|
||||
* @throws IOException
|
||||
*/
|
||||
static ConcurrentDbAccessException createForFile(String lockFilePath, RandomAccessFile lockFileRaf) throws IOException {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
while (lockFileRaf.getFilePointer() < lockFileRaf.length()) {
|
||||
buffer.append(lockFileRaf.readLine() + System.lineSeparator());
|
||||
}
|
||||
String conflictingApplication = buffer.toString().trim();
|
||||
String message = "Unable to acquire lock on " + lockFilePath + "." + (StringUtils.isNotBlank(conflictingApplication) ? (" Database is already open in " + conflictingApplication + ".") : "");
|
||||
return new ConcurrentDbAccessException(message, conflictingApplication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param conflictingApplicationName The conflicting application name
|
||||
* (or null if unknown).
|
||||
*/
|
||||
ConcurrentDbAccessException(String message, String conflictingApplicationName) {
|
||||
super(message);
|
||||
this.conflictingApplicationName = conflictingApplicationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The conflicting application name (or null if unknown).
|
||||
*/
|
||||
public String getConflictingApplicationName() {
|
||||
return conflictingApplicationName;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user