35
35
import java .nio .file .DirectoryStream .Filter ;
36
36
import java .nio .file .FileAlreadyExistsException ;
37
37
import java .nio .file .FileStore ;
38
+ import java .nio .file .FileSystemException ;
38
39
import java .nio .file .Files ;
39
40
import java .nio .file .LinkOption ;
40
41
import java .nio .file .NoSuchFileException ;
59
60
import java .util .Collections ;
60
61
import java .util .EnumSet ;
61
62
import java .util .Map ;
63
+ import java .util .Optional ;
62
64
import java .util .Set ;
63
65
import java .util .stream .Collectors ;
64
66
68
70
69
71
@ CryptoFileSystemScoped
70
72
class CryptoFileSystemImpl extends CryptoFileSystem {
71
-
73
+
72
74
private final CryptoFileSystemProvider provider ;
73
75
private final CryptoFileSystems cryptoFileSystems ;
74
76
private final Path pathToVault ;
@@ -80,6 +82,7 @@ class CryptoFileSystemImpl extends CryptoFileSystem {
80
82
private final PathMatcherFactory pathMatcherFactory ;
81
83
private final DirectoryStreamFactory directoryStreamFactory ;
82
84
private final DirectoryIdProvider dirIdProvider ;
85
+ private final DirectoryIdBackup dirIdBackup ;
83
86
private final AttributeProvider fileAttributeProvider ;
84
87
private final AttributeByNameProvider fileAttributeByNameProvider ;
85
88
private final AttributeViewProvider fileAttributeViewProvider ;
@@ -98,7 +101,7 @@ class CryptoFileSystemImpl extends CryptoFileSystem {
98
101
@ Inject
99
102
public CryptoFileSystemImpl (CryptoFileSystemProvider provider , CryptoFileSystems cryptoFileSystems , @ PathToVault Path pathToVault , Cryptor cryptor ,
100
103
CryptoFileStore fileStore , CryptoFileSystemStats stats , CryptoPathMapper cryptoPathMapper , CryptoPathFactory cryptoPathFactory ,
101
- PathMatcherFactory pathMatcherFactory , DirectoryStreamFactory directoryStreamFactory , DirectoryIdProvider dirIdProvider ,
104
+ PathMatcherFactory pathMatcherFactory , DirectoryStreamFactory directoryStreamFactory , DirectoryIdProvider dirIdProvider , DirectoryIdBackup dirIdBackup ,
102
105
AttributeProvider fileAttributeProvider , AttributeByNameProvider fileAttributeByNameProvider , AttributeViewProvider fileAttributeViewProvider ,
103
106
OpenCryptoFiles openCryptoFiles , Symlinks symlinks , FinallyUtil finallyUtil , CiphertextDirectoryDeleter ciphertextDirDeleter , ReadonlyFlag readonlyFlag ,
104
107
CryptoFileSystemProperties fileSystemProperties ) {
@@ -113,6 +116,7 @@ public CryptoFileSystemImpl(CryptoFileSystemProvider provider, CryptoFileSystems
113
116
this .pathMatcherFactory = pathMatcherFactory ;
114
117
this .directoryStreamFactory = directoryStreamFactory ;
115
118
this .dirIdProvider = dirIdProvider ;
119
+ this .dirIdBackup = dirIdBackup ;
116
120
this .fileAttributeProvider = fileAttributeProvider ;
117
121
this .fileAttributeByNameProvider = fileAttributeByNameProvider ;
118
122
this .fileAttributeViewProvider = fileAttributeViewProvider ;
@@ -235,13 +239,17 @@ <A extends BasicFileAttributes> A readAttributes(CryptoPath cleartextPath, Class
235
239
236
240
/**
237
241
* @param cleartextPath the path to the file
238
- * @param type the Class object corresponding to the file attribute view
239
- * @param options future use
242
+ * @param type the Class object corresponding to the file attribute view
243
+ * @param options future use
240
244
* @return a file attribute view of the specified type, or <code>null</code> if the attribute view type is not available
241
245
* @see AttributeViewProvider#getAttributeView(CryptoPath, Class, LinkOption...)
242
246
*/
243
247
<V extends FileAttributeView > V getFileAttributeView (CryptoPath cleartextPath , Class <V > type , LinkOption ... options ) {
244
- return fileAttributeViewProvider .getAttributeView (cleartextPath , type , options );
248
+ if (fileStore .supportsFileAttributeView (type )) {
249
+ return fileAttributeViewProvider .getAttributeView (cleartextPath , type , options );
250
+ } else {
251
+ return null ;
252
+ }
245
253
}
246
254
247
255
void checkAccess (CryptoPath cleartextPath , AccessMode ... modes ) throws IOException {
@@ -282,6 +290,10 @@ boolean isHidden(CryptoPath cleartextPath) throws IOException {
282
290
void createDirectory (CryptoPath cleartextDir , FileAttribute <?>... attrs ) throws IOException {
283
291
readonlyFlag .assertWritable ();
284
292
assertCleartextNameLengthAllowed (cleartextDir );
293
+ if (rootPath .equals (cleartextDir )) {
294
+ throw new FileAlreadyExistsException (rootPath .toString ());
295
+ }
296
+
285
297
CryptoPath cleartextParentDir = cleartextDir .getParent ();
286
298
if (cleartextParentDir == null ) {
287
299
return ;
@@ -302,6 +314,7 @@ void createDirectory(CryptoPath cleartextDir, FileAttribute<?>... attrs) throws
302
314
// create dir if and only if the dirFile has been created right now (not if it has been created before):
303
315
try {
304
316
Files .createDirectories (ciphertextDir .path );
317
+ dirIdBackup .execute (ciphertextDir );
305
318
ciphertextPath .persistLongFileName ();
306
319
} catch (IOException e ) {
307
320
// make sure there is no orphan dir file:
@@ -375,14 +388,17 @@ private FileChannel newFileChannelFromFile(CryptoPath cleartextFilePath, Effecti
375
388
stats .incrementAccessesRead ();
376
389
}
377
390
return ch ;
378
- } catch (Exception e ){
391
+ } catch (Exception e ) {
379
392
ch .close ();
380
393
throw e ;
381
394
}
382
395
}
383
396
384
397
void delete (CryptoPath cleartextPath ) throws IOException {
385
398
readonlyFlag .assertWritable ();
399
+ if (rootPath .equals (cleartextPath )) {
400
+ throw new FileSystemException ("The filesystem root cannot be deleted." );
401
+ }
386
402
CiphertextFileType ciphertextFileType = cryptoPathMapper .getCiphertextFileType (cleartextPath );
387
403
CiphertextFilePath ciphertextPath = cryptoPathMapper .getCiphertextFilePath (cleartextPath );
388
404
switch (ciphertextFileType ) {
@@ -414,6 +430,11 @@ void copy(CryptoPath cleartextSource, CryptoPath cleartextTarget, CopyOption...
414
430
if (cleartextSource .equals (cleartextTarget )) {
415
431
return ;
416
432
}
433
+
434
+ if (rootPath .equals (cleartextTarget ) && ArrayUtils .contains (options , StandardCopyOption .REPLACE_EXISTING )) {
435
+ throw new FileSystemException ("The filesystem root cannot be replaced." );
436
+ }
437
+
417
438
CiphertextFileType ciphertextFileType = cryptoPathMapper .getCiphertextFileType (cleartextSource );
418
439
if (!ArrayUtils .contains (options , StandardCopyOption .REPLACE_EXISTING )) {
419
440
cryptoPathMapper .assertNonExisting (cleartextTarget );
@@ -508,6 +529,16 @@ private void copyAttributes(Path src, Path dst) throws IOException {
508
529
void move (CryptoPath cleartextSource , CryptoPath cleartextTarget , CopyOption ... options ) throws IOException {
509
530
readonlyFlag .assertWritable ();
510
531
assertCleartextNameLengthAllowed (cleartextTarget );
532
+
533
+ if (rootPath .equals (cleartextSource )) {
534
+ throw new FileSystemException ("Filesystem root cannot be moved." );
535
+
536
+ }
537
+
538
+ if (rootPath .equals (cleartextTarget )) {
539
+ throw new FileAlreadyExistsException (rootPath .toString ());
540
+ }
541
+
511
542
if (cleartextSource .equals (cleartextTarget )) {
512
543
return ;
513
544
}
@@ -582,7 +613,7 @@ private void moveDirectory(CryptoPath cleartextSource, CryptoPath cleartextTarge
582
613
}
583
614
Files .walkFileTree (ciphertextTarget .getRawPath (), DeletingFileVisitor .INSTANCE );
584
615
}
585
-
616
+
586
617
// no exceptions until this point, so MOVE:
587
618
Files .move (ciphertextSource .getRawPath (), ciphertextTarget .getRawPath (), options );
588
619
if (ciphertextTarget .isShortened ()) {
@@ -621,7 +652,7 @@ CryptoPath getEmptyPath() {
621
652
}
622
653
623
654
void assertCleartextNameLengthAllowed (CryptoPath cleartextPath ) throws FileNameTooLongException {
624
- String filename = cleartextPath .getFileName (). toString ();
655
+ String filename = Optional . ofNullable ( cleartextPath .getFileName ()). map ( CryptoPath :: toString ). orElse ( "" ); //fs root has no explicit name
625
656
if (filename .length () > fileSystemProperties .maxCleartextNameLength ()) {
626
657
throw new FileNameTooLongException (cleartextPath .toString (), fileSystemProperties .maxCleartextNameLength ());
627
658
}
0 commit comments