Skip to content

Commit

Permalink
Merge branch 'release/2.6.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
infeo committed Apr 17, 2023
2 parents b3755f3 + 13355c0 commit ec3871d
Show file tree
Hide file tree
Showing 19 changed files with 478 additions and 206 deletions.
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.6.3</version>
<version>2.6.4</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
11 changes: 8 additions & 3 deletions src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,11 @@ public Path getPathToVault() {
public Path getCiphertextPath(Path cleartextPath) throws IOException {
var p = CryptoPath.castAndAssertAbsolute(cleartextPath);
var nodeType = cryptoPathMapper.getCiphertextFileType(p);
if( nodeType == CiphertextFileType.DIRECTORY) {
if (nodeType == CiphertextFileType.DIRECTORY) {
return cryptoPathMapper.getCiphertextDir(p).path;
}
var cipherFile = cryptoPathMapper.getCiphertextFilePath(p);
if( nodeType == CiphertextFileType.SYMLINK) {
if (nodeType == CiphertextFileType.SYMLINK) {
return cipherFile.getSymlinkFilePath();
} else {
return cipherFile.getFilePath();
Expand Down Expand Up @@ -421,10 +421,15 @@ void delete(CryptoPath cleartextPath) throws IOException {
CiphertextFilePath ciphertextPath = cryptoPathMapper.getCiphertextFilePath(cleartextPath);
switch (ciphertextFileType) {
case DIRECTORY -> deleteDirectory(cleartextPath, ciphertextPath);
case FILE, SYMLINK -> Files.walkFileTree(ciphertextPath.getRawPath(), DeletingFileVisitor.INSTANCE);
case FILE, SYMLINK -> deleteFileOrSymlink(ciphertextPath);
}
}

private void deleteFileOrSymlink(CiphertextFilePath ciphertextPath) throws IOException {
openCryptoFiles.delete(ciphertextPath.getFilePath());
Files.walkFileTree(ciphertextPath.getRawPath(), DeletingFileVisitor.INSTANCE);
}

private void deleteDirectory(CryptoPath cleartextPath, CiphertextFilePath ciphertextPath) throws IOException {
Path ciphertextDir = cryptoPathMapper.getCiphertextDir(cleartextPath).path;
Path ciphertextDirFile = ciphertextPath.getDirFilePath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ public Set<OpenOption> createOpenOptionsForEncryptedFile() {
result.add(READ); // also needed during write
result.remove(LinkOption.NOFOLLOW_LINKS);
result.remove(APPEND);
result.remove(TRUNCATE_EXISTING);
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import dagger.BindsInstance;
import dagger.Subcomponent;
import org.cryptomator.cryptofs.EffectiveOpenOptions;
import org.cryptomator.cryptolib.api.FileHeader;

import java.nio.channels.FileChannel;

Expand All @@ -17,8 +16,6 @@ public interface ChannelComponent {
interface Factory {

ChannelComponent create(@BindsInstance FileChannel ciphertextChannel, //
@BindsInstance FileHeader fileHeader, //
@BindsInstance @MustWriteHeader boolean mustWriteHeader, //
@BindsInstance EffectiveOpenOptions options, //
@BindsInstance ChannelCloseListener listener); //
}
Expand Down
48 changes: 31 additions & 17 deletions src/main/java/org/cryptomator/cryptofs/ch/CleartextFileChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
import org.cryptomator.cryptofs.fh.BufferPool;
import org.cryptomator.cryptofs.fh.Chunk;
import org.cryptomator.cryptofs.fh.ChunkCache;
import org.cryptomator.cryptofs.fh.CurrentOpenFilePath;
import org.cryptomator.cryptofs.fh.ExceptionsDuringWrite;
import org.cryptomator.cryptofs.fh.FileHeaderHolder;
import org.cryptomator.cryptofs.fh.OpenFileModifiedDate;
import org.cryptomator.cryptofs.fh.OpenFileSize;
import org.cryptomator.cryptolib.api.Cryptor;
import org.cryptomator.cryptolib.api.FileHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -22,14 +23,14 @@
import java.nio.channels.FileLock;
import java.nio.channels.NonReadableChannelException;
import java.nio.channels.NonWritableChannelException;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.function.Supplier;

import static java.lang.Math.max;
import static java.lang.Math.min;
Expand All @@ -40,38 +41,36 @@ public class CleartextFileChannel extends AbstractFileChannel {
private static final Logger LOG = LoggerFactory.getLogger(CleartextFileChannel.class);

private final FileChannel ciphertextFileChannel;
private final FileHeader fileHeader;
private final FileHeaderHolder fileHeaderHolder;
private final Cryptor cryptor;
private final ChunkCache chunkCache;
private final BufferPool bufferPool;
private final EffectiveOpenOptions options;
private final AtomicReference<Path> currentFilePath;
private final AtomicLong fileSize;
private final AtomicReference<Instant> lastModified;
private final Supplier<BasicFileAttributeView> attrViewProvider;
private final ExceptionsDuringWrite exceptionsDuringWrite;
private final ChannelCloseListener closeListener;
private final CryptoFileSystemStats stats;
private final AtomicBoolean mustWriteHeader;

@Inject
public CleartextFileChannel(FileChannel ciphertextFileChannel, FileHeader fileHeader, @MustWriteHeader boolean mustWriteHeader, ReadWriteLock readWriteLock, Cryptor cryptor, ChunkCache chunkCache, BufferPool bufferPool, EffectiveOpenOptions options, @OpenFileSize AtomicLong fileSize, @OpenFileModifiedDate AtomicReference<Instant> lastModified, Supplier<BasicFileAttributeView> attrViewProvider, ExceptionsDuringWrite exceptionsDuringWrite, ChannelCloseListener closeListener, CryptoFileSystemStats stats) {
public CleartextFileChannel(FileChannel ciphertextFileChannel, FileHeaderHolder fileHeaderHolder, ReadWriteLock readWriteLock, Cryptor cryptor, ChunkCache chunkCache, BufferPool bufferPool, EffectiveOpenOptions options, @OpenFileSize AtomicLong fileSize, @OpenFileModifiedDate AtomicReference<Instant> lastModified, @CurrentOpenFilePath AtomicReference<Path> currentPath, ExceptionsDuringWrite exceptionsDuringWrite, ChannelCloseListener closeListener, CryptoFileSystemStats stats) {
super(readWriteLock);
this.ciphertextFileChannel = ciphertextFileChannel;
this.fileHeader = fileHeader;
this.fileHeaderHolder = fileHeaderHolder;
this.cryptor = cryptor;
this.chunkCache = chunkCache;
this.bufferPool = bufferPool;
this.options = options;
this.currentFilePath = currentPath;
this.fileSize = fileSize;
this.lastModified = lastModified;
this.attrViewProvider = attrViewProvider;
this.exceptionsDuringWrite = exceptionsDuringWrite;
this.closeListener = closeListener;
this.stats = stats;
if (options.append()) {
position = fileSize.get();
}
this.mustWriteHeader = new AtomicBoolean(mustWriteHeader);
if (options.createNew() || options.create()) {
lastModified.compareAndSet(Instant.EPOCH, Instant.now());
}
Expand Down Expand Up @@ -183,11 +182,12 @@ private long writeLockedInternal(ByteSource src, long position) throws IOExcepti
}

private void writeHeaderIfNeeded() throws IOException {
if (mustWriteHeader.getAndSet(false)) {
LOG.trace("{} - Writing file header.", this);
ByteBuffer encryptedHeader = cryptor.fileHeaderCryptor().encryptHeader(fileHeader);
ciphertextFileChannel.write(encryptedHeader, 0);
if (fileHeaderHolder.headerIsPersisted().get()) {
return;
}
LOG.trace("{} - Writing file header.", this);
ciphertextFileChannel.write(fileHeaderHolder.getEncrypted(), 0);
fileHeaderHolder.headerIsPersisted().set(true);
}

@Override
Expand All @@ -205,7 +205,7 @@ protected void truncateLocked(long newSize) throws IOException {
}
long ciphertextFileSize = cryptor.fileHeaderCryptor().headerSize() + cryptor.fileContentCryptor().ciphertextSize(newSize);
chunkCache.flush();
chunkCache.invalidateAll(); // make sure no chunks _after_ newSize exist that would otherwise be written during the next cache eviction
chunkCache.invalidateStale(); // make sure no chunks _after_ newSize exist that would otherwise be written during the next cache eviction
ciphertextFileChannel.truncate(ciphertextFileSize);
position = min(newSize, position);
fileSize.set(newSize);
Expand All @@ -229,6 +229,7 @@ private void forceInternal(boolean metaData) throws IOException {

/**
* Writes in-memory contents to the ciphertext file
*
* @throws IOException
*/
private void flush() throws IOException {
Expand All @@ -247,7 +248,13 @@ private void flush() throws IOException {
private void persistLastModified() throws IOException {
FileTime lastModifiedTime = isWritable() ? FileTime.from(lastModified.get()) : null;
FileTime lastAccessTime = FileTime.from(Instant.now());
attrViewProvider.get().setTimes(lastModifiedTime, lastAccessTime, null);
var p = currentFilePath.get();
if (p != null) {
p.getFileSystem().provider()//
.getFileAttributeView(p, BasicFileAttributeView.class)
.setTimes(lastModifiedTime, lastAccessTime, null);
}

}

@Override
Expand Down Expand Up @@ -315,7 +322,14 @@ long beginOfChunk(long cleartextPos) {
protected void implCloseChannel() throws IOException {
try {
flush();
persistLastModified();
try {
persistLastModified();
} catch (NoSuchFileException nsfe) {
//no-op, see https://github.com/cryptomator/cryptofs/issues/169
} catch (IOException e) {
//only best effort attempt
LOG.warn("Failed to persist last modified timestamp for encrypted file: {}", e.getMessage());
}
} finally {
super.implCloseChannel();
closeListener.closed(this);
Expand Down
13 changes: 0 additions & 13 deletions src/main/java/org/cryptomator/cryptofs/ch/MustWriteHeader.java

This file was deleted.

Loading

0 comments on commit ec3871d

Please sign in to comment.