Skip to content

Commit

Permalink
Merge branch 'release/1.6.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
infeo committed Nov 21, 2018
2 parents a7f380f + 2452c4b commit 483693e
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 109 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>1.6.1</version>
<version>1.6.2</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 @@ -46,7 +46,9 @@ public final S readAttributes() throws IOException {
public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException {
readonlyFlag.assertWritable();
delegate.setTimes(lastModifiedTime, lastAccessTime, createTime);
openCryptoFile.ifPresent(file -> file.setLastModifiedTime(lastModifiedTime));
if(lastModifiedTime != null){
openCryptoFile.ifPresent(file -> file.setLastModifiedTime(lastModifiedTime));
}
}

}
17 changes: 17 additions & 0 deletions src/main/java/org/cryptomator/cryptofs/CurrentOpenFilePath.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.cryptomator.cryptofs;

import javax.inject.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* The current Path of an OpenCryptoFile.
* @see OriginalOpenFilePath
*/
@Qualifier
@Documented
@Retention(RUNTIME)
@interface CurrentOpenFilePath {
}
24 changes: 10 additions & 14 deletions src/main/java/org/cryptomator/cryptofs/OpenCryptoFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.FileTime;
Expand All @@ -25,6 +24,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

import static java.lang.Math.max;
import static java.lang.Math.min;
Expand All @@ -43,16 +43,15 @@ class OpenCryptoFile {
private final CryptoFileSystemStats stats;
private final ExceptionsDuringWrite exceptionsDuringWrite;
private final FinallyUtil finallyUtil;
private final BasicFileAttributeView attributeView;
private final Supplier<BasicFileAttributeView> attributeViewProvider;
private final AtomicBoolean headerWritten;
private final AtomicReference<Instant> lastModified;
private final AtomicInteger openChannelCounter;

private Path currentFilePath;
private final AtomicReference<Path> currentFilePath;

@Inject
public OpenCryptoFile(Cryptor cryptor, FileChannel channel, FileHeader header, @OpenFileSize AtomicLong size, CryptoFileChannelFactory cryptoFileChannelFactory,
ChunkCache chunkCache, OpenCryptoFiles openCryptoFileFactory, CryptoFileSystemStats stats, ExceptionsDuringWrite exceptionsDuringWrite, FinallyUtil finallyUtil, BasicFileAttributeView attrView) {
ChunkCache chunkCache, OpenCryptoFiles openCryptoFileFactory, CryptoFileSystemStats stats, ExceptionsDuringWrite exceptionsDuringWrite, FinallyUtil finallyUtil, Supplier<BasicFileAttributeView> attrViewProvider, @CurrentOpenFilePath AtomicReference<Path> currentFilePath) {
this.cryptor = cryptor;
this.channel = channel;
this.header = header;
Expand All @@ -63,11 +62,12 @@ public OpenCryptoFile(Cryptor cryptor, FileChannel channel, FileHeader header, @
this.stats = stats;
this.exceptionsDuringWrite = exceptionsDuringWrite;
this.finallyUtil = finallyUtil;
this.attributeView = attrView;
this.attributeViewProvider = attrViewProvider;
this.currentFilePath = currentFilePath;
this.headerWritten = new AtomicBoolean(false);
this.lastModified = new AtomicReference<>();
try {
lastModified.set(attrView.readAttributes().lastModifiedTime().toInstant());
lastModified.set(attrViewProvider.get().readAttributes().lastModifiedTime().toInstant());
} catch (IOException e) {
lastModified.set(Instant.ofEpochSecond(0));
}
Expand Down Expand Up @@ -194,11 +194,7 @@ public synchronized void force(boolean metaData, EffectiveOpenOptions options) t
exceptionsDuringWrite.throwIfPresent();
}
channel.force(metaData);
try {
attributeView.setTimes(FileTime.from(lastModified.get()), null, null);
} catch (NoSuchFileException e) {
//NO-OP because file is already deleted
}
attributeViewProvider.get().setTimes(FileTime.from(lastModified.get()), null, null);
}

public FileLock lock(long position, long size, boolean shared) throws IOException {
Expand All @@ -220,11 +216,11 @@ void decreaseOpenChannelCounter() throws IOException {
}

public Path getCurrentFilePath() {
return currentFilePath;
return currentFilePath.get();
}

public void setCurrentFilePath(Path currentFilePath) {
this.currentFilePath = currentFilePath;
this.currentFilePath.set(currentFilePath);
}

public void close() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dagger.Subcomponent;

@Subcomponent(modules = {OpenCryptoFileModule.class, OpenCryptoFileFactoryModule.class})
@Subcomponent(modules = {OpenCryptoFileModule.class})
@PerOpenFile
interface OpenCryptoFileComponent {

Expand Down

This file was deleted.

87 changes: 83 additions & 4 deletions src/main/java/org/cryptomator/cryptofs/OpenCryptoFileModule.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
package org.cryptomator.cryptofs;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

import dagger.Module;
import dagger.Provides;
import org.cryptomator.cryptolib.api.Cryptor;
import org.cryptomator.cryptolib.api.FileHeader;

import static org.cryptomator.cryptofs.UncheckedThrows.rethrowUnchecked;
import static org.cryptomator.cryptolib.Cryptors.cleartextSize;

@Module
class OpenCryptoFileModule {

private final Path path;
private final Path originalPath;
private final AtomicReference<Path> currentPath;
private final EffectiveOpenOptions options;

private OpenCryptoFileModule(Builder builder) {
this.path = builder.path;
this.originalPath = builder.path;
this.currentPath = new AtomicReference<>(builder.path);
this.options = builder.options;
}

@Provides
@PerOpenFile
@OriginalOpenFilePath
public Path providePath() {
return path;
public Path provideOriginalPath() {
return originalPath;
}

@Provides
@PerOpenFile
@CurrentOpenFilePath
public AtomicReference<Path> provideCurrentPath() {
return currentPath;
}

@Provides
Expand All @@ -29,6 +50,64 @@ public EffectiveOpenOptions provideOptions() {
return options;
}

@Provides
@PerOpenFile
public FileChannel provideFileChannel(EffectiveOpenOptions options) {
return rethrowUnchecked(IOException.class).from(() -> originalPath.getFileSystem().provider().newFileChannel(originalPath, options.createOpenOptionsForEncryptedFile()));
}

@Provides
@PerOpenFile
public Supplier<BasicFileAttributeView> provideBasicFileAttributeViewSupplier() {
return () -> {
Path path = currentPath.get();
return path.getFileSystem().provider().getFileAttributeView(path, BasicFileAttributeView.class);
};
}

@Provides
@PerOpenFile
@OpenFileSize
public AtomicLong provideFileSize(FileChannel channel, Cryptor cryptor) {
return rethrowUnchecked(IOException.class).from(() -> {
long size = channel.size();
if (size == 0) {
return new AtomicLong();
} else {
int headerSize = cryptor.fileHeaderCryptor().headerSize();
return new AtomicLong(cleartextSize(size - headerSize, cryptor));
}
});
}

@Provides
@PerOpenFile
public FileHeader provideFileHeader(FileChannel channel, Cryptor cryptor, EffectiveOpenOptions options) {
return rethrowUnchecked(IOException.class).from(() -> {
if (options.truncateExisting() || isNewFile(channel, options)) {
FileHeader newHeader = cryptor.fileHeaderCryptor().create();
channel.position(0);
channel.write(cryptor.fileHeaderCryptor().encryptHeader(newHeader));
channel.force(false);
return newHeader;
} else {
ByteBuffer existingHeaderBuf = ByteBuffer.allocate(cryptor.fileHeaderCryptor().headerSize());
channel.position(0);
channel.read(existingHeaderBuf);
existingHeaderBuf.flip();
try {
return cryptor.fileHeaderCryptor().decryptHeader(existingHeaderBuf);
} catch (IllegalArgumentException e) {
throw new IOException(e);
}
}
});
}

private boolean isNewFile(FileChannel channel, EffectiveOpenOptions options) throws IOException {
return options.createNew() || options.create() && channel.size() == 0;
}

public static Builder openCryptoFileModule() {
return new Builder();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ private OpenCryptoFile create(Path normalizedPath, EffectiveOpenOptions options)
.withOptions(options) //
.build();
OpenCryptoFile file = component.newOpenCryptoFileComponent(module).openCryptoFile();
//TODO: is this call necessary?
file.setCurrentFilePath(normalizedPath);
return file;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

/**
* The Path used to create an OpenCryptoFile
* @see CurrentOpenFilePath
*/
@Qualifier
@Documented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.UserPrincipal;
import java.time.Instant;
import java.util.Map;

import static java.lang.Boolean.FALSE;
Expand Down Expand Up @@ -137,6 +138,25 @@ public void testLastModifiedDateUpdatesOnlyDuringWrite() throws IOException, Int
Assert.assertEquals(t3.toMillis(), t4.toMillis()); // round to millis, since in-memory times of opened files may have sub-milli resolution
}

@Test
public void testFileAttributeViewUpdatesAfterMove() throws IOException {
Path oldpath = fileSystem.getPath("/x");
Path newpath = fileSystem.getPath("/y");
try (FileChannel channel = FileChannel.open(oldpath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)) {
BasicFileAttributeView attrView = Files.getFileAttributeView(oldpath, BasicFileAttributeView.class);
FileTime now = FileTime.from(Instant.ofEpochSecond(123456789L));
attrView.setTimes(now, null, null);
Files.move(oldpath, newpath);
channel.force(true);
BasicFileAttributeView attrView2 = Files.getFileAttributeView(newpath, BasicFileAttributeView.class);
Assert.assertEquals(now, attrView2.readAttributes().lastModifiedTime());

thrown.expect(NoSuchFileException.class);
Files.getFileAttributeView(oldpath, BasicFileAttributeView.class).readAttributes();
}

}

private static Matcher<FileTime> isAfter(FileTime previousFileTime) {
return new BaseMatcher<FileTime>() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public void testBuilder() {
.build();

assertThat(inTest.provideOptions(), is(options));
assertThat(inTest.providePath(), is(path));
assertThat(inTest.provideOriginalPath(), is(path));
assertThat(inTest.provideCurrentPath().get(), is(path));
}

@Test
Expand Down
Loading

0 comments on commit 483693e

Please sign in to comment.