Skip to content

Commit

Permalink
Merge branch 'release/2.6.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
infeo committed Apr 4, 2023
2 parents 470bcb5 + b6f15b3 commit b3755f3
Show file tree
Hide file tree
Showing 22 changed files with 643 additions and 315 deletions.
18 changes: 17 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId>
<version>2.6.2</version>
<version>2.6.3</version>
<name>Cryptomator Crypto Filesystem</name>
<description>This library provides the Java filesystem provider used by Cryptomator.</description>
<url>https://github.com/cryptomator/cryptofs</url>
Expand All @@ -22,6 +22,7 @@
<jwt.version>4.3.0</jwt.version>
<dagger.version>2.44.2</dagger.version>
<guava.version>31.1-jre</guava.version>
<caffeine.version>3.1.4</caffeine.version>
<slf4j.version>2.0.3</slf4j.version>

<!-- test dependencies -->
Expand Down Expand Up @@ -81,6 +82,21 @@
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>${caffeine.version}</version>
<exclusions>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.common.CiphertextFileType;
import org.cryptomator.cryptofs.health.api.HealthCheck;
import org.cryptomator.cryptofs.health.dirid.DirIdCheck;
import org.cryptomator.cryptofs.health.shortened.ShortenedNamesCheck;
Expand All @@ -10,6 +9,7 @@
module org.cryptomator.cryptofs {
requires transitive org.cryptomator.cryptolib;
requires com.google.common;
requires com.github.benmanes.caffeine;
requires org.slf4j;
requires dagger;
requires com.auth0.jwt;
Expand Down
31 changes: 16 additions & 15 deletions src/main/java/org/cryptomator/cryptofs/CryptoPathMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
*******************************************************************************/
package org.cryptomator.cryptofs;

import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.io.BaseEncoding;
import org.cryptomator.cryptofs.common.CiphertextFileType;
import org.cryptomator.cryptofs.common.Constants;
Expand All @@ -22,6 +20,7 @@

import javax.inject.Inject;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
Expand All @@ -32,7 +31,6 @@
import java.time.Duration;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;

import static org.cryptomator.cryptofs.common.Constants.DATA_DIR_NAME;

Expand Down Expand Up @@ -61,8 +59,8 @@ public class CryptoPathMapper {
this.dirIdProvider = dirIdProvider;
this.longFileNameProvider = longFileNameProvider;
this.vaultConfig = vaultConfig;
this.ciphertextNames = CacheBuilder.newBuilder().maximumSize(MAX_CACHED_CIPHERTEXT_NAMES).build(CacheLoader.from(this::getCiphertextFileName));
this.ciphertextDirectories = CacheBuilder.newBuilder().maximumSize(MAX_CACHED_DIR_PATHS).expireAfterWrite(MAX_CACHE_AGE).build();
this.ciphertextNames = Caffeine.newBuilder().maximumSize(MAX_CACHED_CIPHERTEXT_NAMES).build(this::getCiphertextFileName);
this.ciphertextDirectories = Caffeine.newBuilder().maximumSize(MAX_CACHED_DIR_PATHS).expireAfterWrite(MAX_CACHE_AGE).build();
this.rootDirectory = resolveDirectory(Constants.ROOT_DIR_ID);
}

Expand Down Expand Up @@ -127,7 +125,7 @@ public CiphertextFilePath getCiphertextFilePath(CryptoPath cleartextPath) throws
}

public CiphertextFilePath getCiphertextFilePath(Path parentCiphertextDir, String parentDirId, String cleartextName) {
String ciphertextName = ciphertextNames.getUnchecked(new DirIdAndName(parentDirId, cleartextName));
String ciphertextName = ciphertextNames.get(new DirIdAndName(parentDirId, cleartextName));
Path c9rPath = parentCiphertextDir.resolve(ciphertextName);
if (ciphertextName.length() > vaultConfig.getShorteningThreshold()) {
LongFileNameProvider.DeflatedFileName deflatedFileName = longFileNameProvider.deflate(c9rPath);
Expand Down Expand Up @@ -160,13 +158,16 @@ public CiphertextDirectory getCiphertextDir(CryptoPath cleartextPath) throws IOE
return rootDirectory;
} else {
try {
return ciphertextDirectories.get(cleartextPath, () -> {
Path dirFile = getCiphertextFilePath(cleartextPath).getDirFilePath();
return resolveDirectory(dirFile);
return ciphertextDirectories.get(cleartextPath, p -> {
try {
Path dirFile = getCiphertextFilePath(p).getDirFilePath();
return resolveDirectory(dirFile);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
} catch (ExecutionException e) {
Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
throw new IOException("Unexpected exception", e);
} catch (UncheckedIOException e) {
throw new IOException(e);
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/org/cryptomator/cryptofs/DirectoryIdLoader.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package org.cryptomator.cryptofs;

import com.google.common.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.CacheLoader;

import javax.inject.Inject;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
Expand All @@ -14,7 +15,7 @@
import java.util.UUID;

@CryptoFileSystemScoped
class DirectoryIdLoader extends CacheLoader<Path, String> {
class DirectoryIdLoader implements CacheLoader<Path, String> {

private static final int MAX_DIR_ID_LENGTH = 1000;

Expand All @@ -23,7 +24,7 @@ public DirectoryIdLoader() {
}

@Override
public String load(Path dirFilePath) throws IOException {
public String load(Path dirFilePath) throws UncheckedIOException {
try (FileChannel ch = FileChannel.open(dirFilePath, StandardOpenOption.READ);
InputStream in = Channels.newInputStream(ch)) {
long size = ch.size();
Expand All @@ -39,6 +40,8 @@ public String load(Path dirFilePath) throws IOException {
}
} catch (NoSuchFileException e) {
return UUID.randomUUID().toString();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

Expand Down
17 changes: 9 additions & 8 deletions src/main/java/org/cryptomator/cryptofs/DirectoryIdProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
*******************************************************************************/
package org.cryptomator.cryptofs;

import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.ExecutionException;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;

import javax.inject.Inject;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;

@CryptoFileSystemScoped
class DirectoryIdProvider {
Expand All @@ -26,13 +26,13 @@ class DirectoryIdProvider {

@Inject
public DirectoryIdProvider(DirectoryIdLoader directoryIdLoader) {
ids = CacheBuilder.newBuilder().maximumSize(MAX_CACHE_SIZE).build(directoryIdLoader);
this.ids = Caffeine.newBuilder().maximumSize(MAX_CACHE_SIZE).build(directoryIdLoader);
}

public String load(Path dirFilePath) throws IOException {
try {
return ids.get(dirFilePath);
} catch (ExecutionException e) {
} catch (UncheckedIOException e) {
throw new IOException("Failed to load contents of directory file at path " + dirFilePath, e);
}
}
Expand Down Expand Up @@ -62,4 +62,5 @@ public void move(Path srcDirFilePath, Path dstDirFilePath) {
}
}


}
44 changes: 19 additions & 25 deletions src/main/java/org/cryptomator/cryptofs/LongFileNameProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
*******************************************************************************/
package org.cryptomator.cryptofs;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.io.BaseEncoding;
import org.cryptomator.cryptolib.common.MessageDigestSupplier;

Expand All @@ -24,7 +23,6 @@
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.time.Duration;
import java.util.concurrent.ExecutionException;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.cryptomator.cryptofs.common.Constants.DEFLATED_FILE_SUFFIX;
Expand All @@ -39,31 +37,28 @@ public class LongFileNameProvider {
private static final Duration MAX_CACHE_AGE = Duration.ofMinutes(1);

private final ReadonlyFlag readonlyFlag;
private final LoadingCache<Path, String> longNames; // Maps from c9s paths to inflated filenames
private final Cache<Path, String> longNames; // Maps from c9s paths to inflated filenames

@Inject
public LongFileNameProvider(ReadonlyFlag readonlyFlag) {
this.readonlyFlag = readonlyFlag;
this.longNames = CacheBuilder.newBuilder().expireAfterAccess(MAX_CACHE_AGE).build(new Loader());
this.longNames = Caffeine.newBuilder().expireAfterAccess(MAX_CACHE_AGE).build();
}

private class Loader extends CacheLoader<Path, String> {

@Override
public String load(Path c9sPath) throws IOException {
Path longNameFile = c9sPath.resolve(INFLATED_FILE_NAME);
try (SeekableByteChannel ch = Files.newByteChannel(longNameFile, StandardOpenOption.READ)) {
if (ch.size() > MAX_FILENAME_BUFFER_SIZE) {
throw new IOException("Unexpectedly large file: " + longNameFile);
}
assert ch.size() <= MAX_FILENAME_BUFFER_SIZE;
ByteBuffer buf = ByteBuffer.allocate((int) ch.size());
ch.read(buf);
buf.flip();
return UTF_8.decode(buf).toString();
private String load(Path c9sPath) throws UncheckedIOException {
Path longNameFile = c9sPath.resolve(INFLATED_FILE_NAME);
try (SeekableByteChannel ch = Files.newByteChannel(longNameFile, StandardOpenOption.READ)) {
if (ch.size() > MAX_FILENAME_BUFFER_SIZE) {
throw new IOException("Unexpectedly large file: " + longNameFile);
}
assert ch.size() <= MAX_FILENAME_BUFFER_SIZE;
ByteBuffer buf = ByteBuffer.allocate((int) ch.size());
ch.read(buf);
buf.flip();
return UTF_8.decode(buf).toString();
} catch (IOException e) {
throw new UncheckedIOException(e);
}

}

public boolean isDeflated(String possiblyDeflatedFileName) {
Expand All @@ -72,10 +67,9 @@ public boolean isDeflated(String possiblyDeflatedFileName) {

public String inflate(Path c9sPath) throws IOException {
try {
return longNames.get(c9sPath);
} catch (ExecutionException e) {
Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
throw new IllegalStateException("Unexpected exception", e);
return longNames.get(c9sPath, this::load);
} catch (UncheckedIOException e) {
throw e.getCause(); // rethrow original to keep exception types such as NoSuchFileException
}
}

Expand Down
Loading

0 comments on commit b3755f3

Please sign in to comment.