Skip to content

Commit

Permalink
Merge branch 'release/1.1.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
markuskreusch committed Mar 21, 2017
2 parents 9ef9923 + c79d960 commit 186968f
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 17 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.1.1</version>
<version>1.1.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 @@ -20,7 +20,11 @@ public DirectoryIdLoader() {
@Override
public String load(Path dirFilePath) throws IOException {
if (Files.exists(dirFilePath)) {
return new String(Files.readAllBytes(dirFilePath), StandardCharsets.UTF_8);
byte[] bytes = Files.readAllBytes(dirFilePath);
if (bytes.length == 0) {
throw new IOException("Invalid, empty directory file: " + dirFilePath);
}
return new String(bytes, StandardCharsets.UTF_8);
} else {
return UUID.randomUUID().toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,11 @@ private boolean isSupported(OpenOption option) {
return StandardOpenOption.class.isInstance(option);
}

// TODO do not add write if filesystem is in readonly mode
public Set<OpenOption> createOpenOptionsForEncryptedFile() {
Set<OpenOption> result = new HashSet<>(options);
result.add(READ); // also needed during write
result.add(WRITE); // maybe needed when opening writable channel afterwards
result.remove(APPEND);
return result;
}
Expand Down
17 changes: 11 additions & 6 deletions src/main/java/org/cryptomator/cryptofs/FinallyUtil.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.cryptomator.cryptofs;

import static java.util.Arrays.asList;

import java.util.Arrays;
import java.util.Iterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import javax.inject.Inject;

Expand All @@ -13,14 +14,18 @@ class FinallyUtil {
public FinallyUtil() {
}

@SuppressWarnings({"rawtypes", "unchecked"})
@SuppressWarnings({"unchecked"})
public <E extends Exception> void guaranteeInvocationOf(RunnableThrowingException<? extends E>... tasks) throws E {
guaranteeInvocationOf((Iterator) asList(tasks).iterator());
guaranteeInvocationOf(Arrays.stream(tasks));
}

@SuppressWarnings({"rawtypes", "unchecked"})
public <E extends Exception> void guaranteeInvocationOf(Iterable<RunnableThrowingException<? extends E>> tasks) throws E {
guaranteeInvocationOf((Iterator) tasks.iterator());
guaranteeInvocationOf(StreamSupport.stream(tasks.spliterator(), false));
}

@SuppressWarnings({"unchecked"})
public <E extends Exception> void guaranteeInvocationOf(Stream<RunnableThrowingException<? extends E>> tasks) throws E {
guaranteeInvocationOf(tasks.map(t -> (RunnableThrowingException<E>) t).iterator());
}

@SuppressWarnings("unchecked")
Expand Down
90 changes: 90 additions & 0 deletions src/test/java/org/cryptomator/cryptofs/DirectoryIdLoaderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.cryptomator.cryptofs;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.spi.FileSystemProvider;

import org.cryptomator.cryptofs.mocks.SeekableByteChannelMock;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class DirectoryIdLoaderTest {

@Rule
public ExpectedException thrown = ExpectedException.none();

private FileSystemProvider provider = mock(FileSystemProvider.class);
private FileSystem fileSystem = mock(FileSystem.class);
private Path dirFilePath = mock(Path.class);
private Path otherDirFilePath = mock(Path.class);

private DirectoryIdLoader inTest = new DirectoryIdLoader();

@Before
public void setup() {
when(dirFilePath.getFileSystem()).thenReturn(fileSystem);
when(otherDirFilePath.getFileSystem()).thenReturn(fileSystem);
when(fileSystem.provider()).thenReturn(provider);
}

@Test
public void testDirectoryIdsForTwoNonExistingFilesDiffer() throws IOException {
doThrow(new IOException()).when(provider).checkAccess(dirFilePath);
doThrow(new IOException()).when(provider).checkAccess(otherDirFilePath);

String first = inTest.load(dirFilePath);
String second = inTest.load(otherDirFilePath);

assertThat(first, is(not(second)));
}

@Test
public void testDirectoryIdForNonExistingFileIsNotEmpty() throws IOException {
doThrow(new IOException()).when(provider).checkAccess(dirFilePath);

String result = inTest.load(dirFilePath);

assertThat(result, is(notNullValue()));
assertThat(result, is(not("")));
}

@Test
public void testDirectoryIdIsReadFromExistingFile() throws IOException {
String expectedId = "asdüßT°z¬╚‗";
byte[] expectedIdBytes = expectedId.getBytes(UTF_8);
SeekableByteChannel channel = new SeekableByteChannelMock(ByteBuffer.wrap(expectedIdBytes));
when(provider.newByteChannel(eq(dirFilePath), any())).thenReturn(channel);

String result = inTest.load(dirFilePath);

assertThat(result, is(expectedId));
}

@Test
public void testIOExceptionWhenExistingFileIsEmpty() throws IOException {
SeekableByteChannel channel = new SeekableByteChannelMock(ByteBuffer.allocate(0));
when(provider.newByteChannel(eq(dirFilePath), any())).thenReturn(channel);

thrown.expect(IOException.class);
thrown.expectMessage("Invalid, empty directory file");

inTest.load(dirFilePath);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void testEmpty() {
assertFalse(inTest.truncateExisting());
assertFalse(inTest.writable());

assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ));
assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, WRITE));
}

@Test
Expand Down Expand Up @@ -97,7 +97,7 @@ public void testCreate() {
assertFalse(inTest.truncateExisting());
assertFalse(inTest.writable());

assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ));
assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, WRITE));
}

@Test
Expand Down Expand Up @@ -131,7 +131,7 @@ public void testCreateNew() {
assertFalse(inTest.truncateExisting());
assertFalse(inTest.writable());

assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ));
assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, WRITE));
}

@Test
Expand Down Expand Up @@ -182,7 +182,7 @@ public void testDeleteOnClose() {
assertFalse(inTest.truncateExisting());
assertFalse(inTest.writable());

assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, DELETE_ON_CLOSE));
assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, WRITE, DELETE_ON_CLOSE));
}

@Test
Expand All @@ -199,7 +199,7 @@ public void testRead() {
assertFalse(inTest.truncateExisting());
assertFalse(inTest.writable());

assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ));
assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, WRITE));
}

@Test
Expand All @@ -216,7 +216,7 @@ public void testSync() {
assertFalse(inTest.truncateExisting());
assertFalse(inTest.writable());

assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, SYNC));
assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, WRITE, SYNC));
}

@Test
Expand All @@ -233,7 +233,7 @@ public void testDSync() {
assertFalse(inTest.truncateExisting());
assertFalse(inTest.writable());

assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, DSYNC));
assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, WRITE, DSYNC));
}

@Test
Expand All @@ -250,7 +250,7 @@ public void testTruncateExisting() {
assertFalse(inTest.truncateExisting());
assertFalse(inTest.writable());

assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ));
assertThat(inTest.createOpenOptionsForEncryptedFile(), containsInAnyOrder(READ, WRITE));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.cryptomator.cryptofs;

import static java.nio.file.StandardOpenOption.READ;
import static org.cryptomator.cryptofs.CryptoFileSystemProperties.cryptoFileSystemProperties;
import static org.cryptomator.cryptofs.CryptoFileSystemUris.createUri;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.common.jimfs.Jimfs;

/**
* @see https://github.com/cryptomator/cryptofs/issues/10
*/
public class WriteFileWhileReadonlyChannelIsOpenTest {

private FileSystem inMemoryFs;
private FileSystem fileSystem;
private Path root;

@Before
public void setup() throws IOException {
inMemoryFs = Jimfs.newFileSystem();
Path pathToVault = inMemoryFs.getRootDirectories().iterator().next().resolve("vault");
fileSystem = new CryptoFileSystemProvider().newFileSystem(createUri(pathToVault), cryptoFileSystemProperties().withPassphrase("asd").build());
root = fileSystem.getPath("/");
}

@After
public void teardown() throws IOException {
fileSystem.close();
inMemoryFs.close();
}

@Test
public void run() throws IOException {
Path file = root.resolve("file");
Files.write(file, "foo".getBytes());
@SuppressWarnings("unused")
FileChannel readOnlyChannel = FileChannel.open(file, READ);

try (FileChannel writableChannel = FileChannel.open(file, StandardOpenOption.WRITE)) {
ByteBuffer buffer = ByteBuffer.wrap("bar".getBytes());
while (buffer.hasRemaining()) {
writableChannel.write(buffer);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;

class SeekableByteChannelMock implements SeekableByteChannel {
public class SeekableByteChannelMock implements SeekableByteChannel {

private boolean open = true;

Expand Down Expand Up @@ -58,6 +58,7 @@ public int read(ByteBuffer dst) throws IOException {
ByteBuffer limitedSrc = buf.asReadOnlyBuffer();
limitedSrc.limit(limitedSrc.position() + num);
dst.put(limitedSrc);
buf.position(buf.position() + num);
return num;
}
}
Expand Down

0 comments on commit 186968f

Please sign in to comment.