From 28566e50d88c775a920b331148109c891eaa1ac0 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 9 Aug 2023 12:24:02 +0200 Subject: [PATCH 1/6] rename variable --- .../cryptomator/cryptofs/CryptoFileSystemImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java index 8bd83d2d..8a69c831 100644 --- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java +++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java @@ -621,18 +621,18 @@ private void moveDirectory(CryptoPath cleartextSource, CryptoPath cleartextTarge throw new AtomicMoveNotSupportedException(cleartextSource.toString(), cleartextTarget.toString(), "Replacing directories during move requires non-atomic status checks."); } // check if dir is empty: - Path oldCiphertextDir = cryptoPathMapper.getCiphertextDir(cleartextTarget).path; - boolean oldCiphertextDirExists = true; - try (DirectoryStream ds = Files.newDirectoryStream(oldCiphertextDir)) { + Path targetCiphertextDirContentDir = cryptoPathMapper.getCiphertextDir(cleartextTarget).path; + boolean targetCiphertextDirExists = true; + try (DirectoryStream ds = Files.newDirectoryStream(targetCiphertextDirContentDir)) { if (ds.iterator().hasNext()) { throw new DirectoryNotEmptyException(cleartextTarget.toString()); } } catch (NoSuchFileException e) { - oldCiphertextDirExists = false; + targetCiphertextDirExists = false; } // cleanup dir to be replaced: - if (oldCiphertextDirExists) { - Files.walkFileTree(oldCiphertextDir, DeletingFileVisitor.INSTANCE); + if (targetCiphertextDirExists) { + Files.walkFileTree(targetCiphertextDirContentDir, DeletingFileVisitor.INSTANCE); } Files.walkFileTree(ciphertextTarget.getRawPath(), DeletingFileVisitor.INSTANCE); } From 9ed893e1a8d7a245c0c77b70c1e0da32c6e38f7c Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 9 Aug 2023 12:25:00 +0200 Subject: [PATCH 2/6] first orphanize, then remove content --- .../java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java index 8a69c831..284739d3 100644 --- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java +++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java @@ -630,11 +630,12 @@ private void moveDirectory(CryptoPath cleartextSource, CryptoPath cleartextTarge } catch (NoSuchFileException e) { targetCiphertextDirExists = false; } - // cleanup dir to be replaced: + //delete dir link + Files.walkFileTree(ciphertextTarget.getRawPath(), DeletingFileVisitor.INSTANCE); + // cleanup content dir if (targetCiphertextDirExists) { Files.walkFileTree(targetCiphertextDirContentDir, DeletingFileVisitor.INSTANCE); } - Files.walkFileTree(ciphertextTarget.getRawPath(), DeletingFileVisitor.INSTANCE); } // no exceptions until this point, so MOVE: From 7790221c0725b5e8b27554143d801325d836a721 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 9 Aug 2023 12:58:03 +0200 Subject: [PATCH 3/6] Fixes #176 --- .../cryptofs/CryptoFileSystemImpl.java | 3 ++- .../cryptofs/dir/DirIdBackupFilter.java | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/cryptomator/cryptofs/dir/DirIdBackupFilter.java diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java index 284739d3..4852db13 100644 --- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java +++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java @@ -18,6 +18,7 @@ import org.cryptomator.cryptofs.common.DeletingFileVisitor; import org.cryptomator.cryptofs.common.FinallyUtil; import org.cryptomator.cryptofs.dir.CiphertextDirectoryDeleter; +import org.cryptomator.cryptofs.dir.DirIdBackupFilter; import org.cryptomator.cryptofs.dir.DirectoryStreamFactory; import org.cryptomator.cryptofs.fh.OpenCryptoFiles; import org.cryptomator.cryptolib.api.Cryptor; @@ -623,7 +624,7 @@ private void moveDirectory(CryptoPath cleartextSource, CryptoPath cleartextTarge // check if dir is empty: Path targetCiphertextDirContentDir = cryptoPathMapper.getCiphertextDir(cleartextTarget).path; boolean targetCiphertextDirExists = true; - try (DirectoryStream ds = Files.newDirectoryStream(targetCiphertextDirContentDir)) { + try (DirectoryStream ds = Files.newDirectoryStream(targetCiphertextDirContentDir, new DirIdBackupFilter())) { if (ds.iterator().hasNext()) { throw new DirectoryNotEmptyException(cleartextTarget.toString()); } diff --git a/src/main/java/org/cryptomator/cryptofs/dir/DirIdBackupFilter.java b/src/main/java/org/cryptomator/cryptofs/dir/DirIdBackupFilter.java new file mode 100644 index 00000000..5c2806b4 --- /dev/null +++ b/src/main/java/org/cryptomator/cryptofs/dir/DirIdBackupFilter.java @@ -0,0 +1,18 @@ +package org.cryptomator.cryptofs.dir; + +import org.cryptomator.cryptofs.common.Constants; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Path; + +public class DirIdBackupFilter implements DirectoryStream.Filter { + + private final Path skippedEntry = Path.of(Constants.DIR_BACKUP_FILE_NAME); + + @Override + public boolean accept(Path entry) throws IOException { + return entry.getFileName().equals(skippedEntry); + } + +} From 139f64165c87ecd83fa174c51bb26d529cb09fca Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 9 Aug 2023 12:58:26 +0200 Subject: [PATCH 4/6] add test --- ...FileSystemProviderInMemoryIntegrationTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderInMemoryIntegrationTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderInMemoryIntegrationTest.java index c2822284..6b494ebb 100644 --- a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderInMemoryIntegrationTest.java +++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderInMemoryIntegrationTest.java @@ -58,6 +58,21 @@ public static void afterAll() throws IOException { tmpFs.close(); } + @Test + @DisplayName("Replace an existing, shortened, empty directory") + public void testReplaceExistingShortenedDirEmpty() throws IOException { + try (var fs = setupCryptoFs(50, 100, false)) { + var dirName50Chars = "/target_89_123456789_123456789_123456789_123456789_"; //since filename encryption increases filename length, 50 cleartext chars are sufficient + var source = fs.getPath("/sourceDir"); + var target = fs.getPath(dirName50Chars); + Files.createDirectory(source); + Files.createDirectory(target); + assertDoesNotThrow(() -> Files.move(source, target, REPLACE_EXISTING)); + assertTrue(Files.notExists(source)); + assertTrue(Files.exists(target)); + } + } + @Test @DisplayName("Replace an existing, shortened file") public void testReplaceExistingShortenedFile() throws IOException { From 450c4b5a93aaa73a5af1fac18b051594f1af53ce Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 9 Aug 2023 13:10:58 +0200 Subject: [PATCH 5/6] fixed wrong implementation --- .../java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java | 4 ++-- ...DirIdBackupFilter.java => ExcludeDirIdBackupFilter.java} | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) rename src/main/java/org/cryptomator/cryptofs/dir/{DirIdBackupFilter.java => ExcludeDirIdBackupFilter.java} (56%) diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java index 4852db13..76c67410 100644 --- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java +++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java @@ -18,7 +18,7 @@ import org.cryptomator.cryptofs.common.DeletingFileVisitor; import org.cryptomator.cryptofs.common.FinallyUtil; import org.cryptomator.cryptofs.dir.CiphertextDirectoryDeleter; -import org.cryptomator.cryptofs.dir.DirIdBackupFilter; +import org.cryptomator.cryptofs.dir.ExcludeDirIdBackupFilter; import org.cryptomator.cryptofs.dir.DirectoryStreamFactory; import org.cryptomator.cryptofs.fh.OpenCryptoFiles; import org.cryptomator.cryptolib.api.Cryptor; @@ -624,7 +624,7 @@ private void moveDirectory(CryptoPath cleartextSource, CryptoPath cleartextTarge // check if dir is empty: Path targetCiphertextDirContentDir = cryptoPathMapper.getCiphertextDir(cleartextTarget).path; boolean targetCiphertextDirExists = true; - try (DirectoryStream ds = Files.newDirectoryStream(targetCiphertextDirContentDir, new DirIdBackupFilter())) { + try (DirectoryStream ds = Files.newDirectoryStream(targetCiphertextDirContentDir, new ExcludeDirIdBackupFilter())) { if (ds.iterator().hasNext()) { throw new DirectoryNotEmptyException(cleartextTarget.toString()); } diff --git a/src/main/java/org/cryptomator/cryptofs/dir/DirIdBackupFilter.java b/src/main/java/org/cryptomator/cryptofs/dir/ExcludeDirIdBackupFilter.java similarity index 56% rename from src/main/java/org/cryptomator/cryptofs/dir/DirIdBackupFilter.java rename to src/main/java/org/cryptomator/cryptofs/dir/ExcludeDirIdBackupFilter.java index 5c2806b4..328a2922 100644 --- a/src/main/java/org/cryptomator/cryptofs/dir/DirIdBackupFilter.java +++ b/src/main/java/org/cryptomator/cryptofs/dir/ExcludeDirIdBackupFilter.java @@ -6,13 +6,11 @@ import java.nio.file.DirectoryStream; import java.nio.file.Path; -public class DirIdBackupFilter implements DirectoryStream.Filter { - - private final Path skippedEntry = Path.of(Constants.DIR_BACKUP_FILE_NAME); +public class ExcludeDirIdBackupFilter implements DirectoryStream.Filter { @Override public boolean accept(Path entry) throws IOException { - return entry.getFileName().equals(skippedEntry); + return !entry.equals(entry.resolveSibling(Constants.DIR_BACKUP_FILE_NAME)); } } From d653636379b166eea02264eb7eeb765b3ae521ff Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 9 Aug 2023 16:01:22 +0200 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: Sebastian Stenzel --- .../cryptofs/CryptoFileSystemImpl.java | 4 ++-- .../cryptofs/dir/DirectoryStreamFilters.java | 12 ++++++++++++ .../cryptofs/dir/ExcludeDirIdBackupFilter.java | 16 ---------------- 3 files changed, 14 insertions(+), 18 deletions(-) create mode 100644 src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamFilters.java delete mode 100644 src/main/java/org/cryptomator/cryptofs/dir/ExcludeDirIdBackupFilter.java diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java index 76c67410..d3d7af7c 100644 --- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java +++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java @@ -18,7 +18,7 @@ import org.cryptomator.cryptofs.common.DeletingFileVisitor; import org.cryptomator.cryptofs.common.FinallyUtil; import org.cryptomator.cryptofs.dir.CiphertextDirectoryDeleter; -import org.cryptomator.cryptofs.dir.ExcludeDirIdBackupFilter; +import org.cryptomator.cryptofs.dir.DirectoryStreamFilters; import org.cryptomator.cryptofs.dir.DirectoryStreamFactory; import org.cryptomator.cryptofs.fh.OpenCryptoFiles; import org.cryptomator.cryptolib.api.Cryptor; @@ -624,7 +624,7 @@ private void moveDirectory(CryptoPath cleartextSource, CryptoPath cleartextTarge // check if dir is empty: Path targetCiphertextDirContentDir = cryptoPathMapper.getCiphertextDir(cleartextTarget).path; boolean targetCiphertextDirExists = true; - try (DirectoryStream ds = Files.newDirectoryStream(targetCiphertextDirContentDir, new ExcludeDirIdBackupFilter())) { + try (DirectoryStream ds = Files.newDirectoryStream(targetCiphertextDirContentDir, DirectoryStreamFilters.EXCLUDE_DIR_ID_BACKUP)) { if (ds.iterator().hasNext()) { throw new DirectoryNotEmptyException(cleartextTarget.toString()); } diff --git a/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamFilters.java b/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamFilters.java new file mode 100644 index 00000000..13f87c11 --- /dev/null +++ b/src/main/java/org/cryptomator/cryptofs/dir/DirectoryStreamFilters.java @@ -0,0 +1,12 @@ +package org.cryptomator.cryptofs.dir; + +import org.cryptomator.cryptofs.common.Constants; + +import java.nio.file.DirectoryStream; +import java.nio.file.Path; + +public interface DirectoryStreamFilters { + + static DirectoryStream.Filter EXCLUDE_DIR_ID_BACKUP = p -> !p.equals(p.resolveSibling(Constants.DIR_BACKUP_FILE_NAME)); + +} diff --git a/src/main/java/org/cryptomator/cryptofs/dir/ExcludeDirIdBackupFilter.java b/src/main/java/org/cryptomator/cryptofs/dir/ExcludeDirIdBackupFilter.java deleted file mode 100644 index 328a2922..00000000 --- a/src/main/java/org/cryptomator/cryptofs/dir/ExcludeDirIdBackupFilter.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.cryptomator.cryptofs.dir; - -import org.cryptomator.cryptofs.common.Constants; - -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Path; - -public class ExcludeDirIdBackupFilter implements DirectoryStream.Filter { - - @Override - public boolean accept(Path entry) throws IOException { - return !entry.equals(entry.resolveSibling(Constants.DIR_BACKUP_FILE_NAME)); - } - -}