Skip to content

Commit 8bd2fab

Browse files
Merge branch 'release/0.1.6'
# Conflicts: # pom.xml
2 parents b3e65c0 + 940e5b8 commit 8bd2fab

17 files changed

+330
-68
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
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>0.1.5</version>
5+
<version>0.1.6</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>

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ public boolean wasWritten() {
3838
return written;
3939
}
4040

41+
public void truncate(int length) {
42+
if (this.length > length) {
43+
this.length = length;
44+
this.written = true;
45+
}
46+
}
47+
4148
public CopyWithoutDirection copyData() {
4249
return copyDataStartingAt(0);
4350
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ final class Constants {
1515
public static final String DATA_DIR_NAME = "d";
1616
public static final String METADATA_DIR_NAME = "m";
1717
public static final String DIR_PREFIX = "0";
18-
public static final int NAME_SHORTENING_THRESHOLD = 80; // TODO markuskreusch: set correct value
19-
public static final int VAULT_VERSION = 4;
18+
public static final int NAME_SHORTENING_THRESHOLD = 129;
19+
public static final int VAULT_VERSION = 5;
2020

2121
public static final String SEPARATOR = "/";
2222

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

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@
1616
import java.nio.file.Path;
1717
import java.nio.file.attribute.BasicFileAttributeView;
1818
import java.nio.file.attribute.BasicFileAttributes;
19+
import java.nio.file.attribute.DosFileAttributeView;
1920
import java.nio.file.attribute.DosFileAttributes;
2021
import java.nio.file.attribute.FileAttributeView;
2122
import java.nio.file.attribute.FileTime;
23+
import java.nio.file.attribute.GroupPrincipal;
24+
import java.nio.file.attribute.PosixFileAttributeView;
2225
import java.nio.file.attribute.PosixFileAttributes;
26+
import java.nio.file.attribute.UserPrincipal;
2327
import java.util.Collection;
2428
import java.util.HashMap;
2529
import java.util.Map;
@@ -48,10 +52,10 @@ class CryptoFileAttributeByNameProvider {
4852
attribute("basic:size", BasicFileAttributes.class, BasicFileAttributes::size);
4953
attribute("basic:fileKey", BasicFileAttributes.class, BasicFileAttributes::fileKey);
5054

51-
attribute("dos:isReadOnly", DosFileAttributes.class, DosFileAttributes::isReadOnly);
52-
attribute("dos:isHidden", DosFileAttributes.class, DosFileAttributes::isHidden);
53-
attribute("dos:isArchive", DosFileAttributes.class, DosFileAttributes::isArchive);
54-
attribute("dos:isSystem", DosFileAttributes.class, DosFileAttributes::isSystem);
55+
attribute("dos:readOnly", DosFileAttributes.class, DosFileAttributes::isReadOnly);
56+
attribute("dos:hidden", DosFileAttributes.class, DosFileAttributes::isHidden);
57+
attribute("dos:archive", DosFileAttributes.class, DosFileAttributes::isArchive);
58+
attribute("dos:system", DosFileAttributes.class, DosFileAttributes::isSystem);
5559

5660
attribute("posix:owner", PosixFileAttributes.class, PosixFileAttributes::owner);
5761
attribute("posix:group", PosixFileAttributes.class, PosixFileAttributes::group);
@@ -64,14 +68,14 @@ class CryptoFileAttributeByNameProvider {
6468
attribute("basic:lastAccessTime", BasicFileAttributeView.class, FileTime.class, (view, lastAccessTime) -> view.setTimes(null, lastAccessTime, null));
6569
attribute("basic:creationTime", BasicFileAttributeView.class, FileTime.class, (view, creationTime) -> view.setTimes(null, null, creationTime));
6670

67-
attribute("dos:isReadOnly", DosFileAttributes.class, DosFileAttributes::isReadOnly);
68-
attribute("dos:isHidden", DosFileAttributes.class, DosFileAttributes::isHidden);
69-
attribute("dos:isArchive", DosFileAttributes.class, DosFileAttributes::isArchive);
70-
attribute("dos:isSystem", DosFileAttributes.class, DosFileAttributes::isSystem);
71+
attribute("dos:readOnly", DosFileAttributeView.class, Boolean.class, DosFileAttributeView::setReadOnly);
72+
attribute("dos:hidden", DosFileAttributeView.class, Boolean.class, DosFileAttributeView::setHidden);
73+
attribute("dos:archive", DosFileAttributeView.class, Boolean.class, DosFileAttributeView::setArchive);
74+
attribute("dos:system", DosFileAttributeView.class, Boolean.class, DosFileAttributeView::setSystem);
7175

72-
attribute("posix:owner", PosixFileAttributes.class, PosixFileAttributes::owner);
73-
attribute("posix:group", PosixFileAttributes.class, PosixFileAttributes::group);
74-
attribute("posix:permissions", PosixFileAttributes.class, PosixFileAttributes::permissions);
76+
attribute("posix:owner", PosixFileAttributeView.class, UserPrincipal.class, PosixFileAttributeView::setOwner);
77+
attribute("posix:group", PosixFileAttributeView.class, GroupPrincipal.class, PosixFileAttributeView::setGroup);
78+
attribute("posix:permissions", PosixFileAttributeView.class, Set.class, PosixFileAttributeView::setPermissions);
7579
}
7680

7781
private <T extends BasicFileAttributes> void attribute(String name, Class<T> type, Function<T, ?> getter) {

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ void createDirectory(CryptoPath cleartextDir, FileAttribute<?>... attrs) throws
322322
} finally {
323323
if (!success) {
324324
Files.delete(ciphertextDirFile);
325-
dirIdProvider.invalidate(ciphertextDirFile);
325+
dirIdProvider.delete(ciphertextDirFile);
326326
}
327327
}
328328
}
@@ -350,7 +350,7 @@ void delete(CryptoPath cleartextPath) throws IOException {
350350
// should not happen. Nevertheless this is a valid state, so who no big deal...
351351
LOG.warn("Successfully deleted dir {}, but didn't find corresponding dir file {}", ciphertextDir, ciphertextDirFile);
352352
}
353-
dirIdProvider.invalidate(ciphertextDirFile);
353+
dirIdProvider.delete(ciphertextDirFile);
354354
} catch (NoSuchFileException e) {
355355
// translate ciphertext path to cleartext path
356356
throw new NoSuchFileException(cleartextPath.toString());
@@ -458,11 +458,10 @@ void move(CryptoPath cleartextSource, CryptoPath cleartextTarget, CopyOption...
458458
}
459459
}
460460
Files.delete(ciphertextTargetDir);
461-
dirIdProvider.invalidate(ciphertextTargetDirFile);
462461
}
463462
Files.move(ciphertextSourceDirFile, ciphertextTargetDirFile, options);
464463
}
465-
dirIdProvider.invalidate(ciphertextSourceDirFile);
464+
dirIdProvider.move(ciphertextSourceDirFile, ciphertextTargetDirFile);
466465
} else {
467466
throw new NoSuchFileException(cleartextSource.toString());
468467
}

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public AsynchronousFileChannel newAsynchronousFileChannel(Path cleartextPath, Se
156156

157157
@Override
158158
public FileChannel newFileChannel(Path cleartextPath, Set<? extends OpenOption> optionsSet, FileAttribute<?>... attrs) throws IOException {
159-
return fileSystem(cleartextPath).newFileChannel(CryptoPath.cast(cleartextPath), optionsSet, attrs);
159+
return fileSystem(cleartextPath).newFileChannel(CryptoPath.castAndAssertAbsolute(cleartextPath), optionsSet, attrs);
160160
}
161161

162162
@Override
@@ -166,27 +166,27 @@ public SeekableByteChannel newByteChannel(Path cleartextPath, Set<? extends Open
166166

167167
@Override
168168
public DirectoryStream<Path> newDirectoryStream(Path cleartextDir, Filter<? super Path> filter) throws IOException {
169-
return fileSystem(cleartextDir).newDirectoryStream(CryptoPath.cast(cleartextDir), filter);
169+
return fileSystem(cleartextDir).newDirectoryStream(CryptoPath.castAndAssertAbsolute(cleartextDir), filter);
170170
}
171171

172172
@Override
173173
public void createDirectory(Path cleartextDir, FileAttribute<?>... attrs) throws IOException {
174-
fileSystem(cleartextDir).createDirectory(CryptoPath.cast(cleartextDir), attrs);
174+
fileSystem(cleartextDir).createDirectory(CryptoPath.castAndAssertAbsolute(cleartextDir), attrs);
175175
}
176176

177177
@Override
178178
public void delete(Path cleartextPath) throws IOException {
179-
fileSystem(cleartextPath).delete(CryptoPath.cast(cleartextPath));
179+
fileSystem(cleartextPath).delete(CryptoPath.castAndAssertAbsolute(cleartextPath));
180180
}
181181

182182
@Override
183183
public void copy(Path cleartextSource, Path cleartextTarget, CopyOption... options) throws IOException {
184-
copyAndMoveOperations.copy(CryptoPath.cast(cleartextSource), CryptoPath.cast(cleartextTarget), options);
184+
copyAndMoveOperations.copy(CryptoPath.castAndAssertAbsolute(cleartextSource), CryptoPath.castAndAssertAbsolute(cleartextTarget), options);
185185
}
186186

187187
@Override
188188
public void move(Path cleartextSource, Path cleartextTarget, CopyOption... options) throws IOException {
189-
copyAndMoveOperations.move(CryptoPath.cast(cleartextSource), CryptoPath.cast(cleartextTarget), options);
189+
copyAndMoveOperations.move(CryptoPath.castAndAssertAbsolute(cleartextSource), CryptoPath.castAndAssertAbsolute(cleartextTarget), options);
190190
}
191191

192192
@Override
@@ -197,7 +197,7 @@ public boolean isSameFile(Path cleartextPath, Path cleartextPath2) throws IOExce
197197

198198
@Override
199199
public boolean isHidden(Path cleartextPath) throws IOException {
200-
return fileSystem(cleartextPath).isHidden(CryptoPath.cast(cleartextPath));
200+
return fileSystem(cleartextPath).isHidden(CryptoPath.castAndAssertAbsolute(cleartextPath));
201201
}
202202

203203
@Override
@@ -207,27 +207,27 @@ public FileStore getFileStore(Path cleartextPath) throws IOException {
207207

208208
@Override
209209
public void checkAccess(Path cleartextPath, AccessMode... modes) throws IOException {
210-
fileSystem(cleartextPath).checkAccess(CryptoPath.cast(cleartextPath), modes);
210+
fileSystem(cleartextPath).checkAccess(CryptoPath.castAndAssertAbsolute(cleartextPath), modes);
211211
}
212212

213213
@Override
214214
public <V extends FileAttributeView> V getFileAttributeView(Path cleartextPath, Class<V> type, LinkOption... options) {
215-
return fileSystem(cleartextPath).getFileAttributeView(CryptoPath.cast(cleartextPath), type, options);
215+
return fileSystem(cleartextPath).getFileAttributeView(CryptoPath.castAndAssertAbsolute(cleartextPath), type, options);
216216
}
217217

218218
@Override
219219
public <A extends BasicFileAttributes> A readAttributes(Path cleartextPath, Class<A> type, LinkOption... options) throws IOException {
220-
return fileSystem(cleartextPath).readAttributes(CryptoPath.cast(cleartextPath), type, options);
220+
return fileSystem(cleartextPath).readAttributes(CryptoPath.castAndAssertAbsolute(cleartextPath), type, options);
221221
}
222222

223223
@Override
224224
public Map<String, Object> readAttributes(Path cleartextPath, String attributes, LinkOption... options) throws IOException {
225-
return fileSystem(cleartextPath).readAttributes(CryptoPath.cast(cleartextPath), attributes, options);
225+
return fileSystem(cleartextPath).readAttributes(CryptoPath.castAndAssertAbsolute(cleartextPath), attributes, options);
226226
}
227227

228228
@Override
229229
public void setAttribute(Path cleartextPath, String attribute, Object value, LinkOption... options) throws IOException {
230-
fileSystem(cleartextPath).setAttribute(CryptoPath.cast(cleartextPath), attribute, value, options);
230+
fileSystem(cleartextPath).setAttribute(CryptoPath.castAndAssertAbsolute(cleartextPath), attribute, value, options);
231231
}
232232

233233
private CryptoFileSystem fileSystem(Path path) {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ public CryptoPath(CryptoFileSystem fileSystem, List<String> elements, boolean ab
4141
this.absolute = absolute;
4242
}
4343

44+
public static CryptoPath castAndAssertAbsolute(Path path) {
45+
CryptoPath result = cast(path);
46+
if (!result.isAbsolute()) {
47+
throw new IllegalArgumentException("Path must be absolute but was " + path);
48+
}
49+
return result;
50+
}
51+
4452
public static CryptoPath cast(Path path) {
4553
if (path instanceof CryptoPath) {
4654
CryptoPath cryptoPath = (CryptoPath) path;

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,29 @@ public String load(Path dirFilePath) throws IOException {
5454
}
5555
}
5656

57-
public void invalidate(Path dirFilePath) {
57+
/**
58+
* Removes the id currently associated with <code>dirFilePath</code> from cache. Useful during folder delete operations.
59+
* This method has no effect if the content of the given dirFile is not currently cached.
60+
*
61+
* @param dirFilePath The dirFile for which the cache should be deleted.
62+
*/
63+
public void delete(Path dirFilePath) {
5864
ids.invalidate(dirFilePath);
5965
}
6066

67+
/**
68+
* Transfers ownership from the id currently associated with <code>srcDirFilePath</code> to <code>dstDirFilePath</code>. Usefule during folder move operations.
69+
* This method has no effect if the content of the source dirFile is not currently cached.
70+
*
71+
* @param srcDirFilePath The dirFile that contained the cached id until now.
72+
* @param dstDirFilePath The dirFile that will contain the id from now on.
73+
*/
74+
public void move(Path srcDirFilePath, Path dstDirFilePath) {
75+
String id = ids.getIfPresent(srcDirFilePath);
76+
if (id != null) {
77+
ids.put(dstDirFilePath, id);
78+
ids.invalidate(srcDirFilePath);
79+
}
80+
}
81+
6182
}

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import static java.lang.Math.min;
1313
import static org.cryptomator.cryptofs.OpenCounter.OpenState.ALREADY_CLOSED;
1414
import static org.cryptomator.cryptofs.OpenCounter.OpenState.WAS_OPEN;
15+
import static org.cryptomator.cryptolib.Cryptors.ciphertextSize;
1516

1617
import java.io.IOException;
1718
import java.nio.ByteBuffer;
@@ -51,8 +52,6 @@ public OpenCryptoFile(EffectiveOpenOptions options, Cryptor cryptor, FileChannel
5152
this.header = header;
5253
this.size = size;
5354
this.stats = stats;
54-
55-
size.set(header.getFilesize());
5655
}
5756

5857
public FileChannel newFileChannel(EffectiveOpenOptions options) throws IOException {
@@ -135,13 +134,22 @@ public long size() {
135134
}
136135

137136
public synchronized void truncate(long size) throws IOException {
138-
// TODO
137+
long originalSize = this.size.getAndUpdate(current -> min(size, current));
138+
if (originalSize > size) {
139+
int cleartextChunkSize = cryptor.fileContentCryptor().cleartextChunkSize();
140+
long indexOfLastChunk = (size + cleartextChunkSize - 1) / cleartextChunkSize - 1;
141+
int sizeOfIncompleteChunk = (int) (size % cleartextChunkSize);
142+
if (sizeOfIncompleteChunk > 0) {
143+
chunkCache.get(indexOfLastChunk).truncate(sizeOfIncompleteChunk);
144+
}
145+
long ciphertextFileSize = cryptor.fileHeaderCryptor().headerSize() + ciphertextSize(size, cryptor);
146+
channel.truncate(ciphertextFileSize);
147+
}
139148
}
140149

141150
public synchronized void force(boolean metaData, EffectiveOpenOptions options) throws IOException {
142151
chunkCache.invalidateAll(); // TODO increase performance by writing chunks but keeping them cached
143152
if (options.writable()) {
144-
header.setFilesize(size.get());
145153
channel.write(cryptor.fileHeaderCryptor().encryptHeader(header), 0);
146154
}
147155
channel.force(metaData);

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.cryptomator.cryptofs;
22

33
import static org.cryptomator.cryptofs.UncheckedThrows.rethrowUnchecked;
4+
import static org.cryptomator.cryptolib.Cryptors.cleartextSize;
45

56
import java.io.IOException;
67
import java.nio.ByteBuffer;
@@ -26,8 +27,16 @@ public FileChannel provideFileChannel(@OpenFilePath Path path, EffectiveOpenOpti
2627
@Provides
2728
@PerOpenFile
2829
@OpenFileSize
29-
public AtomicLong provideFileSize() {
30-
return new AtomicLong();
30+
public AtomicLong provideFileSize(FileChannel channel, Cryptor cryptor) {
31+
return rethrowUnchecked(IOException.class).from(() -> {
32+
long size = channel.size();
33+
if (size == 0) {
34+
return new AtomicLong();
35+
} else {
36+
int headerSize = cryptor.fileHeaderCryptor().headerSize();
37+
return new AtomicLong(cleartextSize(size - headerSize, cryptor));
38+
}
39+
});
3140
}
3241

3342
@Provides

0 commit comments

Comments
 (0)