Skip to content

Commit d41b4ac

Browse files
Armin Schrenkoverheadhunter
andauthored
Health API / Directory Check: Result EmptyDirFile (#108)
Add to DirIdCheck new result: EmptyDirId (including unit tests) Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
1 parent 0038445 commit d41b4ac

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

src/main/java/org/cryptomator/cryptofs/health/dirid/DirIdCheck.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ private FileVisitResult visitDirFile(Path file, BasicFileAttributes attrs) throw
103103
if (attrs.size() > Constants.MAX_DIR_FILE_LENGTH) {
104104
LOG.warn("Encountered dir.c9r file of size {}", attrs.size());
105105
resultCollector.accept(new ObeseDirFile(file, attrs.size()));
106+
} else if (attrs.size() == 0) {
107+
LOG.warn("Empty dir.c9r file.", file);
108+
resultCollector.accept(new EmptyDirFile(file));
106109
} else {
107110
byte[] bytes = Files.readAllBytes(file);
108111
String dirId = new String(bytes, StandardCharsets.UTF_8);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.cryptomator.cryptofs.health.dirid;
2+
3+
import org.cryptomator.cryptofs.health.api.DiagnosticResult;
4+
5+
import java.nio.file.Path;
6+
import java.util.Map;
7+
8+
import static org.cryptomator.cryptofs.health.api.CommonDetailKeys.DIR_ID_FILE;
9+
10+
/**
11+
* A diagnostic result of an empty directory id file (dir.c9r).
12+
* <p>
13+
* Even though the empty directory ID exists, it is reserved for the root node of the crypto filesystem only.
14+
* Due to its nature, the root node has no corresponding dir.c9r file.
15+
* As a consequence, actual dir.c9r files must not be empty, otherwise it is an error in the vault structure.
16+
*
17+
* @see org.cryptomator.cryptofs.common.Constants#ROOT_DIR_ID
18+
*/
19+
public class EmptyDirFile implements DiagnosticResult {
20+
21+
final Path dirFile;
22+
23+
public EmptyDirFile(Path dirFile) {this.dirFile = dirFile;}
24+
25+
@Override
26+
public Severity getSeverity() {
27+
return Severity.CRITICAL;
28+
}
29+
30+
@Override
31+
public String toString() {
32+
return String.format("File %s is empty, expected content", dirFile);
33+
}
34+
35+
/*
36+
TODO: remove dirFile and parent dir, Change severity to WARN
37+
@Override
38+
public void fix(Path pathToVault, VaultConfig config, Masterkey masterkey, Cryptor cryptor) throws IOException {
39+
Files.delete(dirFile);
40+
Files.delete(dirFile.getParent());
41+
42+
}
43+
*/
44+
45+
@Override
46+
public Map<String, String> details() {
47+
return Map.of(DIR_ID_FILE, dirFile.toString());
48+
}
49+
}

src/test/java/org/cryptomator/cryptofs/health/dirid/DirIdCheckTest.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class DirIdCheckTest {
3636
AA/aaaa/baz=.c9r/symlink.c9r = linktarget
3737
BB/bbbb/foo=.c9r/dir.c9r = CCcccc
3838
BB/bbbb/bar=.c9r/dir.c9r = ffffffffffff-aaaaaaaaaaaa-tttttttttttt
39+
BB/bbbb/baz=.c9r/dir.c9r = [EMPTY]
3940
BB/bbbb/foo=.c9r/unrelated/dir.c9r = unrelatedfile
4041
CC/cccc/foo=.c9r = file
4142
""";
@@ -121,16 +122,32 @@ public void testVisitorDetectsObeseDirId() throws IOException {
121122
MatcherAssert.assertThat(resultCaptor.getAllValues(), Matchers.hasItem(CustomMatchers.matching(ObeseDirFile.class, expectedObeseFile, "Obese dir file: /d/BB/bbbb/bar=.c9r/dir.c9r")));
122123
}
123124

125+
@Test
126+
@DisplayName("detects empty dirID file in /d/BB/bbbb/baz=.c9r/dir.c9r")
127+
public void testVisitorDetectsEmptyDirId() throws IOException {
128+
Files.walkFileTree(dataRoot, Set.of(), 4, visitor);
129+
130+
Predicate<EmptyDirFile> expectedEmptyFile = emptyDirFile -> "/d/BB/bbbb/baz=.c9r/dir.c9r".equals(emptyDirFile.dirFile.toString());
131+
ArgumentCaptor<DiagnosticResult> resultCaptor = ArgumentCaptor.forClass(DiagnosticResult.class);
132+
Mockito.verify(resultsCollector, Mockito.atLeastOnce()).accept(resultCaptor.capture());
133+
MatcherAssert.assertThat(resultCaptor.getAllValues(), Matchers.hasItem(CustomMatchers.matching(EmptyDirFile.class, expectedEmptyFile, "Empty dir file: /d/BB/bbbb/baz=.c9r/dir.c9r")));
134+
}
135+
124136
}
125137

126138
private static void initDirStructure(Path root, String line) throws UncheckedIOException {
127139
try {
128140
if (line.contains(" = ")) {
129141
var sep = line.indexOf(" = ");
130-
var file = line.substring(0, sep);
142+
var file = root.resolve(line.substring(0, sep));
131143
var contents = line.substring(sep + 3);
132-
Files.createDirectories(root.resolve(file).getParent());
133-
Files.writeString(root.resolve(file), contents, StandardCharsets.US_ASCII, StandardOpenOption.CREATE_NEW);
144+
Files.createDirectories(file.getParent());
145+
if (contents.equals("[EMPTY]")) {
146+
Files.createFile(file);
147+
} else {
148+
Files.writeString(file, contents, StandardCharsets.US_ASCII, StandardOpenOption.CREATE_NEW);
149+
150+
}
134151
} else {
135152
Files.createDirectories(root.resolve(line));
136153
}

0 commit comments

Comments
 (0)