Skip to content

Commit 7987c32

Browse files
committed
Merge branch 'release/1.9.13'
2 parents 4a0ec07 + ddeb77b commit 7987c32

File tree

9 files changed

+125
-35
lines changed

9 files changed

+125
-35
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>org.cryptomator</groupId>
44
<artifactId>cryptofs</artifactId>
5-
<version>1.9.12</version>
5+
<version>1.9.13</version>
66
<name>Cryptomator Crypto Filesystem</name>
77
<description>This library provides the Java filesystem provider used by Cryptomator.</description>
88
<url>https://github.com/cryptomator/cryptofs</url>
@@ -16,7 +16,7 @@
1616
<properties>
1717
<cryptolib.version>1.3.2</cryptolib.version>
1818
<dagger.version>2.27</dagger.version>
19-
<guava.version>29.0-jre</guava.version>
19+
<guava.version>30.0-jre</guava.version>
2020
<slf4j.version>1.7.30</slf4j.version>
2121

2222
<junit.jupiter.version>5.6.2</junit.jupiter.version>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,10 @@ private FileChannel newFileChannel(CryptoPath cleartextFilePath, EffectiveOpenOp
372372
FileChannel ch = openCryptoFiles.getOrCreate(ciphertextFilePath).newFileChannel(options); // might throw FileAlreadyExists
373373
if (options.writable()) {
374374
ciphertextPath.persistLongFileName();
375+
stats.incrementAccessesWritten();
376+
}
377+
if (options.readable()) {
378+
stats.incrementAccessesRead();
375379
}
376380
return ch;
377381
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public Cryptor provideCryptor(CryptorProvider cryptorProvider, @PathToVault Path
4040
byte[] keyFileContents = Files.readAllBytes(masterKeyPath);
4141
Cryptor cryptor = cryptorProvider.createFromKeyFile(KeyFile.parse(keyFileContents), properties.passphrase(), properties.pepper(), Constants.VAULT_VERSION);
4242
if (!readonlyFlag.isSet()) {
43-
MasterkeyBackupHelper.backupMasterKey(masterKeyPath);
43+
MasterkeyBackupHelper.attemptMasterKeyBackup(masterKeyPath);
4444
}
4545
return cryptor;
4646
} catch (IOException e) {

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

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@ public class CryptoFileSystemStats {
1818
private final LongAdder bytesWritten = new LongAdder();
1919
private final LongAdder bytesDecrypted = new LongAdder();
2020
private final LongAdder bytesEncrypted = new LongAdder();
21+
private final LongAdder totalBytesRead = new LongAdder();
22+
private final LongAdder totalBytesWritten = new LongAdder();
23+
private final LongAdder totalBytesDecrypted = new LongAdder();
24+
private final LongAdder totalBytesEncrypted = new LongAdder();
2125
private final LongAdder chunkCacheAccesses = new LongAdder();
2226
private final LongAdder chunkCacheMisses = new LongAdder();
2327
private final LongAdder chunkCacheHits = new LongAdder();
28+
private final LongAdder amountOfAccessesRead = new LongAdder();
29+
private final LongAdder amountOfAccessesWritten = new LongAdder();
2430

2531
@Inject
2632
CryptoFileSystemStats() {
@@ -30,32 +36,52 @@ public long pollBytesRead() {
3036
return bytesRead.sumThenReset();
3137
}
3238

39+
public long pollTotalBytesRead() {
40+
return totalBytesRead.sum();
41+
}
42+
3343
public void addBytesRead(long numBytes) {
3444
bytesRead.add(numBytes);
45+
totalBytesRead.add(numBytes);
3546
}
3647

3748
public long pollBytesWritten() {
3849
return bytesWritten.sumThenReset();
3950
}
4051

52+
public long pollTotalBytesWritten() {
53+
return totalBytesWritten.sum();
54+
}
55+
4156
public void addBytesWritten(long numBytes) {
4257
bytesWritten.add(numBytes);
58+
totalBytesWritten.add(numBytes);
4359
}
4460

4561
public long pollBytesDecrypted() {
4662
return bytesDecrypted.sumThenReset();
4763
}
4864

65+
public long pollTotalBytesDecrypted() {
66+
return totalBytesDecrypted.sum();
67+
}
68+
4969
public void addBytesDecrypted(long numBytes) {
5070
bytesDecrypted.add(numBytes);
71+
totalBytesDecrypted.add(numBytes);
5172
}
5273

5374
public long pollBytesEncrypted() {
5475
return bytesEncrypted.sumThenReset();
5576
}
5677

78+
public long pollTotalBytesEncrypted() {
79+
return totalBytesEncrypted.sum();
80+
}
81+
5782
public void addBytesEncrypted(long numBytes) {
5883
bytesEncrypted.add(numBytes);
84+
totalBytesEncrypted.add(numBytes);
5985
}
6086

6187
public long pollChunkCacheAccesses() {
@@ -80,4 +106,20 @@ public void addChunkCacheMiss() {
80106
chunkCacheHits.decrement();
81107
}
82108

83-
}
109+
public long pollAmountOfAccessesRead() {
110+
return amountOfAccessesRead.sum();
111+
}
112+
113+
public void incrementAccessesRead() {
114+
amountOfAccessesRead.increment();
115+
}
116+
117+
public long pollAmountOfAccessesWritten() {
118+
return amountOfAccessesWritten.sum();
119+
}
120+
121+
public void incrementAccessesWritten() {
122+
amountOfAccessesWritten.increment();
123+
}
124+
125+
}

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

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,22 @@
55
import org.slf4j.LoggerFactory;
66

77
import java.io.IOException;
8-
import java.io.InputStream;
98
import java.nio.ByteBuffer;
10-
import java.nio.channels.FileChannel;
119
import java.nio.channels.ReadableByteChannel;
12-
import java.nio.channels.SeekableByteChannel;
1310
import java.nio.channels.WritableByteChannel;
1411
import java.nio.file.AccessDeniedException;
12+
import java.nio.file.FileAlreadyExistsException;
1513
import java.nio.file.Files;
16-
import java.nio.file.NoSuchFileException;
1714
import java.nio.file.Path;
1815
import java.nio.file.StandardOpenOption;
1916
import java.security.MessageDigest;
2017
import java.security.NoSuchAlgorithmException;
21-
import java.util.Arrays;
22-
23-
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
2418

2519
/**
2620
* Utility class for generating a suffix for the backup file to make it unique to its original master key file.
2721
*/
2822
public final class MasterkeyBackupHelper {
29-
23+
3024
private static final Logger LOG = LoggerFactory.getLogger(MasterkeyBackupHelper.class);
3125

3226
/**
@@ -46,38 +40,42 @@ public static String generateFileIdSuffix(byte[] fileBytes) {
4640
}
4741

4842
/**
49-
* Do a best-effort attempt to backup the masterkey at the given path. Fail silently if a valid backup already exists.
50-
*
43+
* Do a best-effort attempt to backup the masterkey at the given path.
44+
* Fails silently if a _valid_ backup already exists and fails with a log entry, if any IO error occurs while creating or reading the backup file.
45+
*
5146
* @param masterKeyPath The masterkey file to backup
52-
* @throws IOException Any non-recoverable I/O exception that occurs during this attempt
47+
* @throws IOException If the masterkey cannot be read.
5348
*/
54-
public static Path backupMasterKey(Path masterKeyPath) throws IOException {
49+
public static Path attemptMasterKeyBackup(Path masterKeyPath) throws IOException {
5550
byte[] keyFileContents = Files.readAllBytes(masterKeyPath);
5651
String backupFileName = masterKeyPath.getFileName().toString() + generateFileIdSuffix(keyFileContents) + Constants.MASTERKEY_BACKUP_SUFFIX;
5752
Path backupFilePath = masterKeyPath.resolveSibling(backupFileName);
58-
try (WritableByteChannel ch = Files.newByteChannel(backupFilePath, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
53+
try (WritableByteChannel ch = Files.newByteChannel(backupFilePath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)) {
5954
ch.write(ByteBuffer.wrap(keyFileContents));
60-
} catch (AccessDeniedException e) {
61-
LOG.info("Storage device does not allow writing backup file. Comparing masterkey with backup directly.");
55+
} catch (AccessDeniedException | FileAlreadyExistsException e) {
6256
assertExistingBackupMatchesContent(backupFilePath, ByteBuffer.wrap(keyFileContents));
57+
} catch (IOException e) {
58+
LOG.warn("Failed to backup valid masterkey file.");
6359
}
6460
return backupFilePath;
6561
}
66-
67-
private static void assertExistingBackupMatchesContent(Path backupFilePath, ByteBuffer expectedContent) throws IOException {
62+
63+
private static void assertExistingBackupMatchesContent(Path backupFilePath, ByteBuffer expectedContent) {
6864
if (Files.exists(backupFilePath)) {
6965
// TODO replace by Files.mismatch() when using JDK > 12
7066
ByteBuffer buf = ByteBuffer.allocateDirect(expectedContent.remaining() + 1);
7167
try (ReadableByteChannel ch = Files.newByteChannel(backupFilePath, StandardOpenOption.READ)) {
7268
ch.read(buf);
7369
buf.flip();
7470
if (buf.compareTo(expectedContent) != 0) {
75-
throw new IllegalStateException("Corrupt masterkey backup: " + backupFilePath);
71+
LOG.warn("Corrupt masterkey backup {}. Please replace it manually or unlock the vault on a writable storage device.", backupFilePath);
72+
} else {
73+
LOG.debug("Verified backup file: {}", backupFilePath);
7674
}
77-
LOG.debug("Verified backup file: {}", backupFilePath);
78-
} catch (NoSuchFileException e) {
79-
LOG.warn("Did not find backup file: {}", backupFilePath);
75+
} catch (IOException e) {
76+
LOG.warn("Failed to compare valid masterkey with backup file.", e);
8077
}
8178
}
8279
}
80+
8381
}

src/main/java/org/cryptomator/cryptofs/migration/v6/Version6Migrator.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,13 @@
88
import java.io.IOException;
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
11-
import java.nio.file.StandardCopyOption;
1211
import java.nio.file.StandardOpenOption;
1312
import java.text.Normalizer;
1413
import java.text.Normalizer.Form;
1514

1615
import javax.inject.Inject;
1716

1817
import org.cryptomator.cryptofs.common.MasterkeyBackupHelper;
19-
import org.cryptomator.cryptofs.common.Constants;
2018
import org.cryptomator.cryptofs.migration.api.MigrationContinuationListener;
2119
import org.cryptomator.cryptofs.migration.api.MigrationProgressListener;
2220
import org.cryptomator.cryptofs.migration.api.Migrator;
@@ -48,7 +46,7 @@ public void migrate(Path vaultRoot, String masterkeyFilename, CharSequence passp
4846
KeyFile keyFile = KeyFile.parse(fileContentsBeforeUpgrade);
4947
try (Cryptor cryptor = cryptorProvider.createFromKeyFile(keyFile, passphrase, 5)) {
5048
// create backup, as soon as we know the password was correct:
51-
Path masterkeyBackupFile = MasterkeyBackupHelper.backupMasterKey(masterkeyFile);
49+
Path masterkeyBackupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(masterkeyFile);
5250
LOG.info("Backed up masterkey from {} to {}.", masterkeyFile.getFileName(), masterkeyBackupFile.getFileName());
5351

5452
progressListener.update(MigrationProgressListener.ProgressState.FINALIZING, 0.0);

src/main/java/org/cryptomator/cryptofs/migration/v7/Version7Migrator.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package org.cryptomator.cryptofs.migration.v7;
77

88
import org.cryptomator.cryptofs.FileNameTooLongException;
9-
import org.cryptomator.cryptofs.common.Constants;
109
import org.cryptomator.cryptofs.common.DeletingFileVisitor;
1110
import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker;
1211
import org.cryptomator.cryptofs.common.MasterkeyBackupHelper;
@@ -28,7 +27,6 @@
2827
import java.nio.file.FileVisitOption;
2928
import java.nio.file.Files;
3029
import java.nio.file.Path;
31-
import java.nio.file.StandardCopyOption;
3230
import java.nio.file.StandardOpenOption;
3331
import java.util.EnumSet;
3432

@@ -52,7 +50,7 @@ public void migrate(Path vaultRoot, String masterkeyFilename, CharSequence passp
5250
KeyFile keyFile = KeyFile.parse(fileContentsBeforeUpgrade);
5351
try (Cryptor cryptor = cryptorProvider.createFromKeyFile(keyFile, passphrase, 6)) {
5452
// create backup, as soon as we know the password was correct:
55-
Path masterkeyBackupFile = MasterkeyBackupHelper.backupMasterKey(masterkeyFile);
53+
Path masterkeyBackupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(masterkeyFile);
5654
LOG.info("Backed up masterkey from {} to {}.", masterkeyFile.getFileName(), masterkeyBackupFile.getFileName());
5755

5856
// check file system capabilities:

src/test/java/org/cryptomator/cryptofs/CryptoFileSystemStatsTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,54 @@ public void testPollChunkCacheMisses() {
9797
Assertions.assertEquals(2l, inTest.pollChunkCacheMisses());
9898
}
9999

100+
@Test
101+
public void testPollTotalBytesRead() {
102+
Assertions.assertEquals(0l, inTest.pollTotalBytesRead());
103+
inTest.addBytesRead(1l);
104+
Assertions.assertEquals(1l, inTest.pollTotalBytesRead());
105+
inTest.addBytesRead(5l);
106+
Assertions.assertEquals(6l, inTest.pollTotalBytesRead());
107+
}
108+
109+
@Test
110+
public void testPollTotalBytesWritten() {
111+
Assertions.assertEquals(0l, inTest.pollTotalBytesWritten());
112+
inTest.addBytesWritten(1l);
113+
Assertions.assertEquals(1l, inTest.pollTotalBytesWritten());
114+
inTest.addBytesWritten(5l);
115+
Assertions.assertEquals(6l, inTest.pollTotalBytesWritten());
116+
}
117+
118+
@Test
119+
public void testPollTotalBytesDecrypted() {
120+
Assertions.assertEquals(0l, inTest.pollTotalBytesDecrypted());
121+
inTest.addBytesDecrypted(1l);
122+
Assertions.assertEquals(1l, inTest.pollTotalBytesDecrypted());
123+
inTest.addBytesDecrypted(5l);
124+
Assertions.assertEquals(6l, inTest.pollTotalBytesDecrypted());
125+
}
126+
127+
@Test
128+
public void testPollTotalBytesEncrypted() {
129+
Assertions.assertEquals(0l, inTest.pollTotalBytesEncrypted());
130+
inTest.addBytesEncrypted(1l);
131+
Assertions.assertEquals(1l, inTest.pollTotalBytesEncrypted());
132+
inTest.addBytesEncrypted(5l);
133+
Assertions.assertEquals(6l, inTest.pollTotalBytesEncrypted());
134+
}
135+
136+
@Test
137+
public void testPollAmountOfFilesRead() {
138+
Assertions.assertEquals(0l, inTest.pollAmountOfAccessesRead());
139+
inTest.incrementAccessesRead();
140+
Assertions.assertEquals(1l, inTest.pollAmountOfAccessesRead());
141+
}
142+
143+
@Test
144+
public void testPollAmountOfFilesWritten() {
145+
Assertions.assertEquals(0l, inTest.pollAmountOfAccessesWritten());
146+
inTest.incrementAccessesWritten();
147+
Assertions.assertEquals(1l, inTest.pollAmountOfAccessesWritten());
148+
}
149+
100150
}

src/test/java/org/cryptomator/cryptofs/common/MasterkeyBackupHelperTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ public void testBackupFilePosix(byte[] contents, @TempDir Path tmp) throws IOExc
2424
Path originalFile = tmp.resolve("original");
2525
Files.write(originalFile, contents);
2626

27-
Path backupFile = MasterkeyBackupHelper.backupMasterKey(originalFile);
27+
Path backupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(originalFile);
2828
Assertions.assertArrayEquals(contents, Files.readAllBytes(backupFile));
2929

3030
Files.setPosixFilePermissions(backupFile, PosixFilePermissions.fromString("r--r--r--"));
31-
Path backupFile2 = MasterkeyBackupHelper.backupMasterKey(originalFile);
31+
Path backupFile2 = MasterkeyBackupHelper.attemptMasterKeyBackup(originalFile);
3232
Assertions.assertEquals(backupFile, backupFile2);
3333
}
3434

@@ -39,11 +39,11 @@ public void testBackupFileWin(byte[] contents, @TempDir Path tmp) throws IOExcep
3939
Path originalFile = tmp.resolve("original");
4040
Files.write(originalFile, contents);
4141

42-
Path backupFile = MasterkeyBackupHelper.backupMasterKey(originalFile);
42+
Path backupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(originalFile);
4343
Assertions.assertArrayEquals(contents, Files.readAllBytes(backupFile));
4444

4545
Files.getFileAttributeView(backupFile, DosFileAttributeView.class).setReadOnly(true);
46-
Path backupFile2 = MasterkeyBackupHelper.backupMasterKey(originalFile);
46+
Path backupFile2 = MasterkeyBackupHelper.attemptMasterKeyBackup(originalFile);
4747
Assertions.assertEquals(backupFile, backupFile2);
4848
}
4949

0 commit comments

Comments
 (0)