Skip to content

Commit

Permalink
Merge branch 'release/2.5.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
infeo committed Nov 23, 2022
2 parents b34eefd + 07aee13 commit fffe0f4
Show file tree
Hide file tree
Showing 48 changed files with 563 additions and 309 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-java@v2
- uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
cache: 'maven'
- name: Cache SonarCloud packages
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
Expand All @@ -36,12 +36,12 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: artifacts
path: target/*.jar
- name: Create Release
uses: actions/create-release@v1
uses: actions/create-release@v1 #NOTE: action is archived and unmaintained
if: startsWith(github.ref, 'refs/tags/')
env:
GITHUB_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} # release as "cryptobot"
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 2
- uses: actions/setup-java@v2
- uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
cache: 'maven'
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: java
- name: Build and Test
run: mvn -B install -DskipTests
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
4 changes: 2 additions & 2 deletions .github/workflows/publish-central.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
ref: "refs/tags/${{ github.event.inputs.tag }}"
- uses: actions/setup-java@v2
- uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-github.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ jobs:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') # only allow publishing tagged versions
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
Expand Down
2 changes: 1 addition & 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.4.5</version>
<version>2.5.0</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 Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,12 @@ void setAttribute(CryptoPath cleartextPath, String attribute, Object value, Link
}

Map<String, Object> readAttributes(CryptoPath cleartextPath, String attributes, LinkOption... options) throws IOException {
stats.incrementAccesses();
return fileAttributeByNameProvider.readAttributes(cleartextPath, attributes, options);
}

<A extends BasicFileAttributes> A readAttributes(CryptoPath cleartextPath, Class<A> type, LinkOption... options) throws IOException {
stats.incrementAccesses();
return fileAttributeProvider.readAttributes(cleartextPath, type, options);
}

Expand Down Expand Up @@ -387,6 +389,7 @@ private FileChannel newFileChannelFromFile(CryptoPath cleartextFilePath, Effecti
if (options.readable()) {
stats.incrementAccessesRead();
}
stats.incrementAccesses();
return ch;
} catch (Exception e) {
ch.close();
Expand Down Expand Up @@ -669,4 +672,4 @@ public String toString() {
return format("%sCryptoFileSystem(%s)", open ? "" : "closed ", pathToVault);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public static void initialize(Path pathToVault, CryptoFileSystemProperties prope
}
byte[] rawKey = new byte[0];
var config = VaultConfig.createNew().cipherCombo(properties.cipherCombo()).shorteningThreshold(properties.shorteningThreshold()).build();
try (Masterkey key = properties.keyLoader().loadKey(keyId);
try (Masterkey key = properties.keyLoader().loadKey(keyId); //
Cryptor cryptor = CryptorProvider.forScheme(config.getCipherCombo()).provide(key, strongSecureRandom())) {
rawKey = key.getEncoded();
// save vault config:
Expand All @@ -154,6 +154,8 @@ public static void initialize(Path pathToVault, CryptoFileSystemProperties prope
String dirHash = cryptor.fileNameCryptor().hashDirectoryId(Constants.ROOT_DIR_ID);
Path vaultCipherRootPath = pathToVault.resolve(Constants.DATA_DIR_NAME).resolve(dirHash.substring(0, 2)).resolve(dirHash.substring(2));
Files.createDirectories(vaultCipherRootPath);
// create dirId backup:
DirectoryIdBackup.backupManually(cryptor, new CryptoPathMapper.CiphertextDirectory(Constants.ROOT_DIR_ID, vaultCipherRootPath));
} finally {
Arrays.fill(rawKey, (byte) 0x00);
}
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/cryptomator/cryptofs/CryptoFileSystemStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public class CryptoFileSystemStats {
private final LongAdder chunkCacheHits = new LongAdder();
private final LongAdder amountOfAccessesRead = new LongAdder();
private final LongAdder amountOfAccessesWritten = new LongAdder();
private final LongAdder amountOfAccesses = new LongAdder();
private final LongAdder totalAmountOfAccessed = new LongAdder();

@Inject
CryptoFileSystemStats() {
Expand Down Expand Up @@ -122,4 +124,17 @@ public void incrementAccessesWritten() {
amountOfAccessesWritten.increment();
}

public long pollAmountOfAccesses() {
return amountOfAccesses.sumThenReset();
}

public long pollTotalAmountOfAccesses() {
return totalAmountOfAccessed.sum();
}

public void incrementAccesses() {
totalAmountOfAccessed.increment();
amountOfAccesses.increment();
}

}
4 changes: 2 additions & 2 deletions src/main/java/org/cryptomator/cryptofs/CryptoPathMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ public CiphertextDirectory getCiphertextDir(CryptoPath cleartextPath) throws IOE
} else {
try {
return ciphertextDirectories.get(cleartextPath, () -> {
Path dirIdFile = getCiphertextFilePath(cleartextPath).getDirFilePath();
return resolveDirectory(dirIdFile);
Path dirFile = getCiphertextFilePath(cleartextPath).getDirFilePath();
return resolveDirectory(dirFile);
});
} catch (ExecutionException e) {
Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/cryptomator/cryptofs/DirectoryIdBackup.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.nio.file.StandardOpenOption;

/**
* Single purpose class to backup the directory id of an encrypted directory when it is created.
* Single purpose class to back up the directory id of an encrypted directory when it is created.
*/
@CryptoFileSystemScoped
public class DirectoryIdBackup {
Expand All @@ -28,20 +28,20 @@ public DirectoryIdBackup(Cryptor cryptor) {
/**
* Performs the backup operation for the given {@link CryptoPathMapper.CiphertextDirectory} object.
* <p>
* The directory id is written via an encrypting channel to the file {@link CryptoPathMapper.CiphertextDirectory#path}/{@value Constants#DIR_ID_FILE}.
* The directory id is written via an encrypting channel to the file {@link CryptoPathMapper.CiphertextDirectory#path}/{@value Constants#DIR_BACKUP_FILE_NAME}.
*
* @param ciphertextDirectory The cipher dir object containing the dir id and the encrypted content root
* @throws IOException if an IOException is raised during the write operation
*/
public void execute(CryptoPathMapper.CiphertextDirectory ciphertextDirectory) throws IOException {
try (var channel = Files.newByteChannel(ciphertextDirectory.path.resolve(Constants.DIR_ID_FILE), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE); //
try (var channel = Files.newByteChannel(ciphertextDirectory.path.resolve(Constants.DIR_BACKUP_FILE_NAME), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE); //
var encryptingChannel = wrapEncryptionAround(channel, cryptor)) {
encryptingChannel.write(ByteBuffer.wrap(ciphertextDirectory.dirId.getBytes(StandardCharsets.US_ASCII)));
}
}

/**
* Static method to explicitly backup the directory id for a specified ciphertext directory.
* Static method to explicitly back up the directory id for a specified ciphertext directory.
*
* @param cryptor The cryptor to be used
* @param ciphertextDirectory A {@link org.cryptomator.cryptofs.CryptoPathMapper.CiphertextDirectory} for which the dirId should be back up'd.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ private void assertWritableIfWriteOrDeleteOnCloseIsPresent(Set<OpenOption> clean
}

private boolean isSupported(OpenOption option) {
return StandardOpenOption.class.isInstance(option) || LinkOption.class.isInstance(option);
return option instanceof StandardOpenOption || option instanceof LinkOption;
}

public Set<OpenOption> createOpenOptionsForEncryptedFile() {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/cryptomator/cryptofs/common/ArrayUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
public final class ArrayUtils {

private ArrayUtils() {}

public static boolean contains(Object[] array, Object objectToFind) {
return Arrays.stream(Objects.requireNonNull(array)).anyMatch(Objects.requireNonNull(objectToFind)::equals);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public final class BackupHelper {
private final static long NO_MISMATCH = -1L;
private static final Logger LOG = LoggerFactory.getLogger(BackupHelper.class);

private BackupHelper() {}

/**
* Computes the SHA-256 digest of the given byte array and returns a file suffix containing the first 4 bytes in hex string format.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ private Constants() {
public static final String SYMLINK_FILE_NAME = "symlink.c9r";
public static final String CONTENTS_FILE_NAME = "contents.c9r";
public static final String INFLATED_FILE_NAME = "name.c9s";
public static final String DIR_BACKUP_FILE_NAME = "dirid.c9r";

public static final int MAX_SYMLINK_LENGTH = 32767; // max path length on NTFS and FAT32: 32k-1
public static final int MAX_DIR_FILE_LENGTH = 36; // UUIDv4: hex-encoded 16 byte int + 4 hyphens = 36 ASCII chars
public static final int MIN_CIPHER_NAME_LENGTH = 26; //rounded up base64url encoded (16 bytes IV + 0 bytes empty string) + file suffix = 26 ASCII chars

public static final String SEPARATOR = "/";
public static final String RECOVERY_DIR_NAME = "LOST+FOUND";
public static final String DIR_ID_FILE = "dirid.c9r";
}
20 changes: 9 additions & 11 deletions src/main/java/org/cryptomator/cryptofs/common/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@
*/
public final class StringUtils {

private StringUtils() {}

/**
* Removes the suffix of a string, if the string ends with the suffix.
*
* @param str input string
* @param remove the suffix to match and remove
* @return a copy of {@code str} with the suffix removed, otherwise just {@code str}
*/
public static String removeEnd(String str, String remove) {
if (str == null || remove == null) {
return str;
Expand All @@ -16,15 +25,4 @@ public static String removeEnd(String str, String remove) {
}
}

public static String removeStart(String str, String remove) {
if (str == null || remove == null) {
return str;
}
if (str.startsWith(remove)) {
return str.substring(remove.length());
} else {
return str;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class CommonDetailKeys {

public static final String ENCRYPTED_PATH = "Encrypted Path";
public static final String DIR_ID = "Directory ID";
public static final String DIR_ID_FILE = "Directory ID File";
public static final String DIR_FILE = "Directory ID File";

private CommonDetailKeys() {};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;

public interface DiagnosticResult {

Expand All @@ -17,17 +18,24 @@ enum Severity {
GOOD,

/**
* Unexpected, but nothing to worry about. May be worth logging
* No impact on vault structure, no data lass, but noteworthy.
* <p>
* If a fix is present, applying it is recommended.
*/
INFO,

/**
* Compromises vault structure, can and should be fixed.
* Compromises vault structure, but no apparent data loss.
* <p>
* If a fix is present, applying it is highly advised to prevent data loss.
*/
WARN,

/**
* Irreversible damage, no automated way of fixing this issue.
* Compromises vault structure, data loss happened.
* <p>
* Restore from backups is advised.
* If not possible and a fix present, applying it is recommended to restore vault structure.
*/
CRITICAL;
}
Expand All @@ -40,8 +48,28 @@ enum Severity {
@Override
String toString();

/**
* A fix for the result.
* <p>
* "Fix" does not imply to restore lost data. It only implies, that the issue leading to this result is resolved.
*
* @param pathToVault path to the root directory of the vault
* @param config the vault config
* @param masterkey the masterkey of the vault
* @param cryptor
* @throws IOException
* @throws UnsupportedOperationException if no fix is implemented for this result
* @deprecated Use {@link #getFix(Path, VaultConfig, Masterkey, Cryptor)} instead
*/
@Deprecated
default void fix(Path pathToVault, VaultConfig config, Masterkey masterkey, Cryptor cryptor) throws IOException {
throw new UnsupportedOperationException("Fix for result" + this.getClass() + " not implemented");
getFix(pathToVault, config, masterkey, cryptor) //
.orElseThrow(() -> new UnsupportedOperationException("Fix for result" + this.getClass() + " not implemented")) //
.apply();
}

default Optional<Fix> getFix(Path pathToVault, VaultConfig config, Masterkey masterkey, Cryptor cryptor) {
return Optional.empty();
}

/**
Expand All @@ -52,4 +80,10 @@ default void fix(Path pathToVault, VaultConfig config, Masterkey masterkey, Cryp
default Map<String, String> details() {
return Map.of();
}

@FunctionalInterface
interface Fix {

void apply() throws IOException;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static Collection<HealthCheck> allChecks() {
}

/**
* @return A human readable name for this check
* @return A human-readable name for this check
*/
default String name() {
var canonicalName = getClass().getCanonicalName();
Expand Down
Loading

0 comments on commit fffe0f4

Please sign in to comment.