Skip to content

Commit 8a3d719

Browse files
Amendment to #71
1 parent b35d35a commit 8a3d719

File tree

5 files changed

+64
-37
lines changed

5 files changed

+64
-37
lines changed

src/main/java/org/cryptomator/cryptofs/CryptoFileSystemProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public static void initialize(Path pathToVault, String masterkeyFilename, byte[]
164164
if (!Files.isDirectory(pathToVault)) {
165165
throw new NotDirectoryException(pathToVault.toString());
166166
}
167-
new FileSystemCapabilityChecker().assertReadWriteCapabilities(pathToVault);
167+
new FileSystemCapabilityChecker().assertAllCapabilities(pathToVault);
168168
try (Cryptor cryptor = CRYPTOR_PROVIDER.createNew()) {
169169
// save masterkey file:
170170
Path masterKeyPath = pathToVault.resolve(masterkeyFilename);

src/main/java/org/cryptomator/cryptofs/CryptoFileSystems.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,18 @@ public CryptoFileSystemImpl create(CryptoFileSystemProvider provider, Path pathT
5757
private CryptoFileSystemProperties adjustForCapabilities(Path pathToVault, CryptoFileSystemProperties originalProperties) throws FileSystemCapabilityChecker.MissingCapabilityException {
5858
if (!originalProperties.readonly()) {
5959
try {
60-
capabilityChecker.assertReadWriteCapabilities(pathToVault);
60+
capabilityChecker.assertWriteAccess(pathToVault);
6161
return originalProperties;
6262
} catch (FileSystemCapabilityChecker.MissingCapabilityException e) {
63-
LOG.warn("Missing file system capabilities for read-write access. Fallback to read-only access.");
63+
capabilityChecker.assertReadAccess(pathToVault);
64+
LOG.warn("No write access to vault. Fallback to read-only access.");
65+
Set<CryptoFileSystemProperties.FileSystemFlags> flags = EnumSet.copyOf(originalProperties.flags());
66+
flags.add(CryptoFileSystemProperties.FileSystemFlags.READONLY);
67+
return CryptoFileSystemProperties.cryptoFileSystemPropertiesFrom(originalProperties).withFlags(flags).build();
6468
}
69+
} else {
70+
return originalProperties;
6571
}
66-
capabilityChecker.assertReadOnlyCapabilities(pathToVault);
67-
Set<CryptoFileSystemProperties.FileSystemFlags> flags = EnumSet.copyOf(originalProperties.flags());
68-
flags.add(CryptoFileSystemProperties.FileSystemFlags.READONLY);
69-
return CryptoFileSystemProperties.cryptoFileSystemPropertiesFrom(originalProperties).withFlags(flags).build();
7072
}
7173

7274
public void remove(CryptoFileSystemImpl cryptoFileSystem) {

src/main/java/org/cryptomator/cryptofs/common/FileSystemCapabilityChecker.java

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.slf4j.LoggerFactory;
99

1010
import java.io.IOException;
11+
import java.nio.file.DirectoryStream;
1112
import java.nio.file.FileSystemException;
1213
import java.nio.file.Files;
1314
import java.nio.file.Path;
@@ -17,6 +18,12 @@ public class FileSystemCapabilityChecker {
1718
private static final Logger LOG = LoggerFactory.getLogger(FileSystemCapabilityChecker.class);
1819

1920
public enum Capability {
21+
/**
22+
* File system allows read access
23+
* @since 1.9.3
24+
*/
25+
READ_ACCESS,
26+
2027
/**
2128
* File system allows write access
2229
* @since 1.9.3
@@ -37,67 +44,85 @@ public enum Capability {
3744
}
3845

3946
/**
40-
* Checks whether the underlying filesystem has all required capabilities for readonly access.
47+
* Checks whether the underlying filesystem has all required capabilities.
48+
*
4149
* @param pathToVault Path to a vault's storage location
4250
* @throws MissingCapabilityException if any check fails
4351
* @implNote Only short-running tests with constant time are performed
44-
* @since 1.9.3
52+
* @since 1.9.2
4553
*/
46-
public void assertReadOnlyCapabilities(Path pathToVault) throws MissingCapabilityException {
47-
// no-op
54+
public void assertAllCapabilities(Path pathToVault) throws MissingCapabilityException {
55+
assertReadAccess(pathToVault);
56+
assertWriteAccess(pathToVault);
57+
assertLongFilenameSupport(pathToVault);
58+
assertLongFilePathSupport(pathToVault);
4859
}
4960

5061
/**
51-
* Checks whether the underlying filesystem has all required capabilities.
52-
*
62+
* Checks whether the underlying filesystem allows reading the given dir.
5363
* @param pathToVault Path to a vault's storage location
54-
* @throws MissingCapabilityException if any check fails
55-
* @implNote Only short-running tests with constant time are performed
56-
* @since 1.9.2
64+
* @throws MissingCapabilityException if the check fails
65+
* @since 1.9.3
5766
*/
58-
public void assertReadWriteCapabilities(Path pathToVault) throws MissingCapabilityException {
59-
Path checkDir = pathToVault.resolve("c");
60-
try {
61-
checkWriteAccess(checkDir);
62-
checkLongFilenames(checkDir);
63-
checkLongFilePaths(checkDir);
64-
} finally {
65-
try {
66-
if (Files.exists(checkDir)) {
67-
MoreFiles.deleteRecursively(checkDir, RecursiveDeleteOption.ALLOW_INSECURE);
68-
}
69-
} catch (IOException e) {
70-
LOG.warn("Failed to clean up " + checkDir, e);
71-
}
67+
public void assertReadAccess(Path pathToVault) throws MissingCapabilityException {
68+
try (DirectoryStream ds = Files.newDirectoryStream(pathToVault)) {
69+
assert ds != null;
70+
} catch (IOException e) {
71+
throw new MissingCapabilityException(pathToVault, Capability.READ_ACCESS);
7272
}
7373
}
74-
75-
private void checkWriteAccess(Path checkDir) throws MissingCapabilityException {
74+
75+
/**
76+
* Checks whether the underlying filesystem allows writing to the given dir.
77+
* @param pathToVault Path to a vault's storage location
78+
* @throws MissingCapabilityException if the check fails
79+
* @since 1.9.3
80+
*/
81+
public void assertWriteAccess(Path pathToVault) throws MissingCapabilityException {
82+
Path checkDir = pathToVault.resolve("c");
7683
try {
77-
Files.createDirectories(checkDir);
84+
Files.createDirectory(checkDir);
7885
} catch (IOException e) {
7986
throw new MissingCapabilityException(checkDir, Capability.WRITE_ACCESS);
87+
} finally {
88+
deleteSilently(checkDir);
8089
}
8190
}
8291

83-
private void checkLongFilenames(Path checkDir) throws MissingCapabilityException {
92+
public void assertLongFilenameSupport(Path pathToVault) throws MissingCapabilityException {
8493
String longFileName = Strings.repeat("a", 226) + ".c9r";
94+
Path checkDir = pathToVault.resolve("c");
8595
Path p = checkDir.resolve(longFileName);
8696
try {
8797
Files.createDirectories(p);
8898
} catch (IOException e) {
8999
throw new MissingCapabilityException(p, Capability.LONG_FILENAMES);
100+
} finally {
101+
deleteSilently(checkDir);
90102
}
91103
}
92104

93-
private void checkLongFilePaths(Path checkDir) throws MissingCapabilityException {
105+
public void assertLongFilePathSupport(Path pathToVault) throws MissingCapabilityException {
94106
String longFileName = Strings.repeat("a", 96) + ".c9r";
95107
String longPath = Joiner.on('/').join(longFileName, longFileName, longFileName, longFileName);
108+
Path checkDir = pathToVault.resolve("c");
96109
Path p = checkDir.resolve(longPath);
97110
try {
98111
Files.createDirectories(p);
99112
} catch (IOException e) {
100113
throw new MissingCapabilityException(p, Capability.LONG_PATHS);
114+
} finally {
115+
deleteSilently(checkDir);
116+
}
117+
}
118+
119+
private void deleteSilently(Path dir) {
120+
try {
121+
if (Files.exists(dir)) {
122+
MoreFiles.deleteRecursively(dir, RecursiveDeleteOption.ALLOW_INSECURE);
123+
}
124+
} catch (IOException e) {
125+
LOG.warn("Failed to clean up " + dir, e);
101126
}
102127
}
103128

src/main/java/org/cryptomator/cryptofs/migration/Migrators.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public boolean needsMigration(Path pathToVault, String masterkeyFilename) throws
9494
* @throws IOException if an I/O error occurs migrating the vault
9595
*/
9696
public void migrate(Path pathToVault, String masterkeyFilename, CharSequence passphrase, MigrationProgressListener progressListener) throws NoApplicableMigratorException, InvalidPassphraseException, IOException {
97-
fsCapabilityChecker.assertReadWriteCapabilities(pathToVault);
97+
fsCapabilityChecker.assertAllCapabilities(pathToVault);
9898

9999
Path masterKeyPath = pathToVault.resolve(masterkeyFilename);
100100
byte[] keyFileContents = Files.readAllBytes(masterKeyPath);

src/test/java/org/cryptomator/cryptofs/migration/MigratorsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void testMigrateWithFailingCapabilitiesCheck() throws IOException {
8989
Migrators migrators = new Migrators(Collections.emptyMap(), fsCapabilityChecker);
9090

9191
Exception expected = new FileSystemCapabilityChecker.MissingCapabilityException(pathToVault, FileSystemCapabilityChecker.Capability.LONG_FILENAMES);
92-
Mockito.doThrow(expected).when(fsCapabilityChecker).assertReadWriteCapabilities(pathToVault);
92+
Mockito.doThrow(expected).when(fsCapabilityChecker).assertAllCapabilities(pathToVault);
9393

9494
Exception thrown = Assertions.assertThrows(FileSystemCapabilityChecker.MissingCapabilityException.class, () -> {
9595
migrators.migrate(pathToVault, "masterkey.cryptomator", "secret", (state, progress) -> {});

0 commit comments

Comments
 (0)