true
if the directory seems to contain a vault.
+ * @param pathToAssumedVault
+ * @param vaultConfigFilename
+ * @param masterkeyFilename
+ * @return a {@link DirStructure} object
+ * @throws IOException
* @since 2.0.0
*/
- public static boolean containsVault(Path pathToVault, String vaultConfigFilename, String masterkeyFilename) {
- Path vaultConfigPath = pathToVault.resolve(vaultConfigFilename);
- Path masterkeyPath = pathToVault.resolve(masterkeyFilename);
- Path dataDirPath = pathToVault.resolve(Constants.DATA_DIR_NAME);
- return (Files.isReadable(vaultConfigPath) || Files.isReadable(masterkeyPath)) && Files.isDirectory(dataDirPath);
+ public static DirStructure checkDirStructureForVault(Path pathToAssumedVault, String vaultConfigFilename, String masterkeyFilename) throws IOException {
+ return DirStructure.checkDirStructure(pathToAssumedVault, vaultConfigFilename, masterkeyFilename);
}
/**
diff --git a/src/main/java/org/cryptomator/cryptofs/DirStructure.java b/src/main/java/org/cryptomator/cryptofs/DirStructure.java
new file mode 100644
index 00000000..daff7fb4
--- /dev/null
+++ b/src/main/java/org/cryptomator/cryptofs/DirStructure.java
@@ -0,0 +1,69 @@
+package org.cryptomator.cryptofs;
+
+import org.cryptomator.cryptofs.common.Constants;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.NotDirectoryException;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+
+/**
+ * Enumeration of the vault directory structure resemblances.
+ * + * A valid vault must contain a `d` directory. + * Beginning with vault format 8, it must also contain a vault config file. + * If the vault format is lower than 8, it must instead contain a masterkey file. + *
+ * In the latter case, to distinguish between a damaged vault 8 directory and a legacy vault the masterkey file must be read.
+ * For efficiency reasons, this class only checks for existence/readability of the above elements.
+ * Hence, if the result of {@link #checkDirStructure(Path, String, String)} is {@link #MAYBE_LEGACY}, one needs to parse
+ * the masterkey file and read out the vault version to determine this case.
+ *
+ * @since 2.0.0
+ */
+public enum DirStructure {
+
+ /**
+ * Dir contains a d
dir as well as a vault config file.
+ */
+ VAULT,
+
+ /**
+ * Dir contains a d
dir and a masterkey file, but misses a vault config file.
+ * Either needs migration to a newer format or damaged.
+ */
+ MAYBE_LEGACY,
+
+ /**
+ * Dir does not qualify as vault.
+ */
+ UNRELATED;
+
+
+ /**
+ * Analyzes the structure of the given directory under certain vault existence criteria.
+ *
+ * @param pathToVault A directory path
+ * @param vaultConfigFilename Name of the vault config file
+ * @param masterkeyFilename Name of the masterkey file
+ * @return enum indicating what this directory might be
+ * @throws IOException if the provided path is not a directory, does not exist or cannot be read
+ */
+ public static DirStructure checkDirStructure(Path pathToVault, String vaultConfigFilename, String masterkeyFilename) throws IOException {
+ if(! Files.readAttributes(pathToVault, BasicFileAttributes.class).isDirectory()) {
+ throw new NotDirectoryException(pathToVault.toString());
+ }
+ Path vaultConfigPath = pathToVault.resolve(vaultConfigFilename);
+ Path masterkeyPath = pathToVault.resolve(masterkeyFilename);
+ Path dataDirPath = pathToVault.resolve(Constants.DATA_DIR_NAME);
+ if (Files.isDirectory(dataDirPath)) {
+ if (Files.isReadable(vaultConfigPath)) {
+ return VAULT;
+ } else if (Files.isReadable(masterkeyPath)) {
+ return MAYBE_LEGACY;
+ }
+ }
+ return UNRELATED;
+ }
+}
diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java
index 5ae7a36a..6ae7b903 100644
--- a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java
+++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java
@@ -227,9 +227,9 @@ public void initializeVaults() {
@Test
@Order(2)
@DisplayName("get filesystem with incorrect credentials")
- public void testGetFsWithWrongCredentials() {
- Assumptions.assumeTrue(CryptoFileSystemProvider.containsVault(pathToVault1, "vault.cryptomator", "masterkey.cryptomator"));
- Assumptions.assumeTrue(CryptoFileSystemProvider.containsVault(pathToVault2, "vault.cryptomator", "masterkey.cryptomator"));
+ public void testGetFsWithWrongCredentials() throws IOException {
+ Assumptions.assumeTrue(CryptoFileSystemProvider.checkDirStructureForVault(pathToVault1, "vault.cryptomator", "masterkey.cryptomator") == DirStructure.VAULT);
+ Assumptions.assumeTrue(CryptoFileSystemProvider.checkDirStructureForVault(pathToVault2, "vault.cryptomator", "masterkey.cryptomator") == DirStructure.VAULT);
Assertions.assertAll(
() -> {
URI fsUri = CryptoFileSystemUri.create(pathToVault1);
diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderTest.java
index d786d9d0..64836e78 100644
--- a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderTest.java
+++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderTest.java
@@ -46,7 +46,6 @@
import static java.nio.file.StandardOpenOption.APPEND;
import static java.util.Arrays.asList;
import static org.cryptomator.cryptofs.CryptoFileSystemProperties.cryptoFileSystemProperties;
-import static org.cryptomator.cryptofs.CryptoFileSystemProvider.containsVault;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
import static org.mockito.Mockito.mock;
@@ -211,69 +210,6 @@ public void testNewFileSystem() throws IOException, MasterkeyLoadingFailedExcept
Mockito.verify(fileSystems).create(Mockito.same(inTest), Mockito.eq(pathToVault.toAbsolutePath()), Mockito.eq(properties));
}
- @Test
- public void testContainsVaultReturnsTrueIfDirectoryContainsVaultConfigFileAndDataDir() throws IOException {
- FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
-
- String vaultConfigFilename = "vaultconfig.foo.baz";
- String masterkeyFilename = "masterkey.foo.baz";
- Path pathToVault = fs.getPath("/vaultDir");
-
- Path vaultConfigFile = pathToVault.resolve(vaultConfigFilename);
- Path dataDir = pathToVault.resolve("d");
- Files.createDirectories(dataDir);
- Files.write(vaultConfigFile, new byte[0]);
-
- Assertions.assertTrue(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
- }
-
- @Test
- public void testContainsVaultReturnsTrueIfDirectoryContainsMasterkeyFileAndDataDir() throws IOException {
- FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
-
- String vaultConfigFilename = "vaultconfig.foo.baz";
- String masterkeyFilename = "masterkey.foo.baz";
- Path pathToVault = fs.getPath("/vaultDir");
-
- Path masterkeyFile = pathToVault.resolve(masterkeyFilename);
- Path dataDir = pathToVault.resolve("d");
- Files.createDirectories(dataDir);
- Files.write(masterkeyFile, new byte[0]);
-
- Assertions.assertTrue(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
- }
-
- @Test
- public void testContainsVaultReturnsFalseIfDirectoryContainsOnlyDataDir() throws IOException {
- FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
-
- String vaultConfigFilename = "vaultconfig.foo.baz";
- String masterkeyFilename = "masterkey.foo.baz";
- Path pathToVault = fs.getPath("/vaultDir");
-
- Path dataDir = pathToVault.resolve("d");
- Files.createDirectories(dataDir);
-
- Assertions.assertFalse(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
- }
-
- @Test
- public void testContainsVaultReturnsFalseIfDirectoryContainsNoDataDir() throws IOException {
- FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
-
- String vaultConfigFilename = "vaultconfig.foo.baz";
- String masterkeyFilename = "masterkey.foo.baz";
- Path pathToVault = fs.getPath("/vaultDir");
-
- Path vaultConfigFile = pathToVault.resolve(vaultConfigFilename);
- Path masterkeyFile = pathToVault.resolve(masterkeyFilename);
- Files.createDirectories(pathToVault);
- Files.write(vaultConfigFile, new byte[0]);
- Files.write(masterkeyFile, new byte[0]);
-
- Assertions.assertFalse(containsVault(pathToVault, vaultConfigFilename, masterkeyFilename));
- }
-
@Test
public void testGetFileSystemInvokesFileSystemsGetWithPathToVaultFromUri() {
Path pathToVault = get("a").toAbsolutePath();
diff --git a/src/test/java/org/cryptomator/cryptofs/DirStructureTest.java b/src/test/java/org/cryptomator/cryptofs/DirStructureTest.java
new file mode 100644
index 00000000..f35818bc
--- /dev/null
+++ b/src/test/java/org/cryptomator/cryptofs/DirStructureTest.java
@@ -0,0 +1,75 @@
+package org.cryptomator.cryptofs;
+
+import org.cryptomator.cryptofs.common.Constants;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+
+public class DirStructureTest {
+
+ private static final String KEY = "key";
+ private static final String CONFIG = "config";
+
+ @TempDir
+ Path vaultPath;
+
+ @Test
+ public void testNonExistingVaultPathThrowsIOException() {
+ Path vaultPath = Path.of("this/certainly/does/not/exist");
+ Assumptions.assumeTrue(Files.notExists(vaultPath));
+
+ Assertions.assertThrows(IOException.class, () -> DirStructure.checkDirStructure(vaultPath, CONFIG, KEY));
+ }
+
+ @Test
+ public void testNonDirectoryVaultPathThrowsIOException() throws IOException {
+ Path tmp = vaultPath.resolve("this");
+ Files.createFile(tmp);
+ Assumptions.assumeTrue(Files.exists(tmp));
+
+ Assertions.assertThrows(IOException.class, () -> DirStructure.checkDirStructure(tmp, CONFIG, KEY));
+ }
+
+ @ParameterizedTest(name = "Testing all combinations of data dir, config and masterkey file existence.")
+ @MethodSource("provideAllCases")
+ public void testAllCombosOfDataAndConfigAndKey(boolean createDataDir, boolean createConfig, boolean createKey, DirStructure expectedResult) throws IOException {
+ Path keyPath = vaultPath.resolve(KEY);
+ Path configPath = vaultPath.resolve(CONFIG);
+ Path dataDir = vaultPath.resolve(Constants.DATA_DIR_NAME);
+
+ if (createDataDir) {
+ Files.createDirectory(dataDir);
+ }
+ if (createConfig) {
+ Files.createFile(configPath);
+ }
+ if (createKey) {
+ Files.createFile(keyPath);
+ }
+
+ Assertions.assertEquals(expectedResult, DirStructure.checkDirStructure(vaultPath, CONFIG, KEY));
+ }
+
+ private static Stream