Skip to content

Commit

Permalink
add conflictResolved event
Browse files Browse the repository at this point in the history
  • Loading branch information
infeo committed Jan 29, 2025
1 parent fecb0a2 commit 1689c58
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public Optional<FileStore> provideNativeFileStore(@PathToVault Path pathToVault)

@Provides
@CryptoFileSystemScoped
@Named("Babadook")
public Consumer<FilesystemEvent> provideFilesystemEventConsumer(CryptoFileSystemProperties fsProps) {
return (Consumer<FilesystemEvent>) fsProps.get(CryptoFileSystemProperties.PROPERTY_NOTIFY_METHOD);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.google.common.io.RecursiveDeleteOption;
import org.cryptomator.cryptofs.VaultConfig;
import org.cryptomator.cryptofs.common.Constants;
import org.cryptomator.cryptofs.event.ConflictResolvedEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import org.cryptomator.cryptolib.api.Cryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -14,10 +16,12 @@
import javax.inject.Named;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.function.Consumer;
import java.util.stream.Stream;

import static org.cryptomator.cryptofs.common.Constants.DIR_FILE_NAME;
Expand All @@ -33,14 +37,18 @@ class C9rConflictResolver {
private final Cryptor cryptor;
private final byte[] dirId;
private final int maxC9rFileNameLength;
private final Path cleartextPath;
private final int maxCleartextFileNameLength;
private final Consumer<FilesystemEvent> eventConsumer;

@Inject
public C9rConflictResolver(Cryptor cryptor, @Named("dirId") String dirId, VaultConfig vaultConfig) {
public C9rConflictResolver(Cryptor cryptor, @Named("dirId") String dirId, VaultConfig vaultConfig, Consumer<FilesystemEvent> eventConsumer, @Named("cleartextPath") Path cleartextPath) {
this.cryptor = cryptor;
this.dirId = dirId.getBytes(StandardCharsets.US_ASCII);
this.maxC9rFileNameLength = vaultConfig.getShorteningThreshold();
this.cleartextPath = cleartextPath;
this.maxCleartextFileNameLength = (maxC9rFileNameLength - 4) / 4 * 3 - 16; // math from FileSystemCapabilityChecker.determineSupportedCleartextFileNameLength()
this.eventConsumer = eventConsumer;
}

public Stream<Node> process(Node node) {
Expand All @@ -62,6 +70,7 @@ public Stream<Node> process(Node node) {
return resolveConflict(node, canonicalPath);
} catch (IOException e) {
LOG.error("Failed to resolve conflict for " + node.ciphertextPath, e);
//TODO: notify!
return Stream.empty();
}
}
Expand Down Expand Up @@ -111,6 +120,7 @@ private Node renameConflictingFile(Path canonicalPath, Path conflictingPath, Str
Node node = new Node(alternativePath);
node.cleartextName = alternativeCleartext;
node.extractedCiphertext = alternativeCiphertext;
eventConsumer.accept(new ConflictResolvedEvent(cleartextPath.resolve(cleartext), canonicalPath, cleartextPath.resolve(alternativeCleartext),alternativePath));
return node;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.cryptomator.cryptofs.event;

public class ConflictResolutionFailedEvent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.cryptomator.cryptofs.event;

import java.nio.file.Path;

public record ConflictResolvedEvent(Path cleartextPath, Path ciphertextPath, Path oldVersionCleartextPath, Path oldVersionCiphertextPath) implements FilesystemEvent{

@Override
public Type getType() {
return Type.CONFLICT_RESOLVED;
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/cryptomator/cryptofs/fh/ChunkLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ChunkLoader {
private final BufferPool bufferPool;

@Inject
public ChunkLoader(@Named("Babadook") Consumer<FilesystemEvent> eventConsumer, @CurrentOpenFilePath AtomicReference<Path> path, Cryptor cryptor, ChunkIO ciphertext, FileHeaderHolder headerHolder, CryptoFileSystemStats stats, BufferPool bufferPool) {
public ChunkLoader(Consumer<FilesystemEvent> eventConsumer, @CurrentOpenFilePath AtomicReference<Path> path, Cryptor cryptor, ChunkIO ciphertext, FileHeaderHolder headerHolder, CryptoFileSystemStats stats, BufferPool bufferPool) {
this.eventConsumer = eventConsumer;
this.path = path;
this.cryptor = cryptor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class FileHeaderHolder {
private final AtomicBoolean isPersisted = new AtomicBoolean();

@Inject
public FileHeaderHolder(@Named("Babadook") Consumer<FilesystemEvent> eventConsumer, Cryptor cryptor, @CurrentOpenFilePath AtomicReference<Path> path) {
public FileHeaderHolder(Consumer<FilesystemEvent> eventConsumer, Cryptor cryptor, @CurrentOpenFilePath AtomicReference<Path> path) {
this.eventConsumer = eventConsumer;
this.cryptor = cryptor;
this.path = path;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
package org.cryptomator.cryptofs.dir;

import org.cryptomator.cryptofs.VaultConfig;
import org.cryptomator.cryptofs.event.ConflictResolvedEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import org.cryptomator.cryptolib.api.Cryptor;
import org.cryptomator.cryptolib.api.FileNameCryptor;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
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.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentMatcher;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Consumer;
import java.util.stream.Stream;

import static org.mockito.Mockito.verify;

public class C9rConflictResolverTest {

private Cryptor cryptor;
private FileNameCryptor fileNameCryptor;
private VaultConfig vaultConfig;
private Consumer<FilesystemEvent> eventConsumer = Mockito.mock(Consumer.class);
private Path cleartextPath = Mockito.mock(Path.class, "/clear/text/path/");
private C9rConflictResolver conflictResolver;

@BeforeEach
Expand All @@ -32,9 +40,10 @@ public void setup() {
vaultConfig = Mockito.mock(VaultConfig.class);
Mockito.when(cryptor.fileNameCryptor()).thenReturn(fileNameCryptor);
Mockito.when(vaultConfig.getShorteningThreshold()).thenReturn(44); // results in max cleartext size = 14
conflictResolver = new C9rConflictResolver(cryptor, "foo", vaultConfig);
Mockito.when(cleartextPath.resolve(Mockito.anyString())).thenReturn(cleartextPath);
conflictResolver = new C9rConflictResolver(cryptor, "foo", vaultConfig, eventConsumer, cleartextPath);
}

@Test
public void testResolveNonConflictingNode() {
Node unresolved = new Node(Paths.get("foo.c9r"));
Expand Down Expand Up @@ -75,6 +84,8 @@ public void testResolveConflictingFileByChoosingNewName(@TempDir Path dir) throw
Assertions.assertEquals("bar (1).txt", resolved.cleartextName);
Assertions.assertTrue(Files.exists(resolved.ciphertextPath));
Assertions.assertFalse(Files.exists(unresolved.ciphertextPath));
var isConflictResolvedEvent = (ArgumentMatcher<FilesystemEvent>) ev -> ev instanceof ConflictResolvedEvent;
verify(eventConsumer).accept(ArgumentMatchers.argThat(isConflictResolvedEvent));
}

@Test
Expand All @@ -94,6 +105,8 @@ public void testResolveConflictingFileByChoosingNewLengthLimitedName(@TempDir Pa
Assertions.assertEquals("hello (1).txt", resolved.cleartextName);
Assertions.assertTrue(Files.exists(resolved.ciphertextPath));
Assertions.assertFalse(Files.exists(unresolved.ciphertextPath));
var isConflictResolvedEvent = (ArgumentMatcher<FilesystemEvent>) ev -> ev instanceof ConflictResolvedEvent;
verify(eventConsumer).accept(ArgumentMatchers.argThat(isConflictResolvedEvent));
}

@Test
Expand Down

0 comments on commit 1689c58

Please sign in to comment.