From 4f2120b7297f461d5d7db6335433e22d6335ee51 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Mon, 3 Aug 2020 22:20:20 +0200 Subject: [PATCH] Added support for folderbased backup-mountpoint to DokanyVol and FuseVol --- .../common/vaults/DokanyVolume.java | 64 ++++++++++++++++--- .../cryptomator/common/vaults/FuseVolume.java | 16 +++-- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java b/main/commons/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java index 7c4781aaa..d4b33315f 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java @@ -1,6 +1,7 @@ package org.cryptomator.common.vaults; import com.google.common.base.Strings; +import org.cryptomator.common.Environment; import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.cryptofs.CryptoFileSystem; import org.cryptomator.frontend.dokany.Mount; @@ -10,6 +11,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; +import java.io.File; import java.io.IOException; import java.nio.file.DirectoryNotEmptyException; import java.nio.file.DirectoryStream; @@ -23,18 +25,22 @@ import java.util.concurrent.ExecutorService; public class DokanyVolume implements Volume { private static final Logger LOG = LoggerFactory.getLogger(DokanyVolume.class); + private static final int MAX_TMPMOUNTPOINT_CREATION_RETRIES = 10; private static final String FS_TYPE_NAME = "Cryptomator File System"; private final VaultSettings vaultSettings; private final MountFactory mountFactory; + private final Environment environment; private final WindowsDriveLetters windowsDriveLetters; private Mount mount; private Path mountPoint; + private boolean createdTemporaryMountPoint; @Inject - public DokanyVolume(VaultSettings vaultSettings, ExecutorService executorService, WindowsDriveLetters windowsDriveLetters) { + public DokanyVolume(VaultSettings vaultSettings, Environment environment, ExecutorService executorService, WindowsDriveLetters windowsDriveLetters) { this.vaultSettings = vaultSettings; + this.environment = environment; this.mountFactory = new MountFactory(executorService); this.windowsDriveLetters = windowsDriveLetters; } @@ -64,15 +70,21 @@ public class DokanyVolume implements Volume { Path customMountPoint = Paths.get(optionalCustomMountPoint.get()); checkProvidedMountPoint(customMountPoint); return customMountPoint; - } else if (!Strings.isNullOrEmpty(vaultSettings.winDriveLetter().get())) { - return Path.of(vaultSettings.winDriveLetter().get().charAt(0) + ":\\"); - } else { - //auto assign drive letter - return windowsDriveLetters.getAvailableDriveLetterPath().orElseThrow(() -> { - //TODO: Error Handling/Fallback (See: FUSE) - return new VolumeException("No free drive letter available."); - }); } + if (!Strings.isNullOrEmpty(vaultSettings.winDriveLetter().get())) { + return Path.of(vaultSettings.winDriveLetter().get().charAt(0) + ":\\"); + } + + //auto assign drive letter + Optional optionalDriveLetter = windowsDriveLetters.getAvailableDriveLetterPath(); + if (optionalDriveLetter.isPresent()) { + return optionalDriveLetter.get(); + } + + //Nothing has worked so far -> Choose and prepare a folder + mountPoint = prepareTemporaryMountPoint(); + LOG.debug("Successfully created mount point: {}", mountPoint); + return mountPoint; } private void checkProvidedMountPoint(Path mountPoint) throws IOException { @@ -86,6 +98,28 @@ public class DokanyVolume implements Volume { } } + private Path chooseNonExistingTemporaryMountPoint() throws VolumeException { + Path parent = environment.getMountPointsDir().orElseThrow(); + String basename = vaultSettings.getId(); //FIXME + for (int i = 0; i < MAX_TMPMOUNTPOINT_CREATION_RETRIES; i++) { + Path mountPoint = parent.resolve(basename + "_" + i); + if (Files.notExists(mountPoint)) { + return mountPoint; + } + } + LOG.error("Failed to find feasible mountpoint at {}{}{}_x. Giving up after {} attempts.", parent, File.separator, basename, MAX_TMPMOUNTPOINT_CREATION_RETRIES); + throw new VolumeException("Did not find feasible mount point."); + } + + private Path prepareTemporaryMountPoint() throws IOException, VolumeException { + Path mountPoint = chooseNonExistingTemporaryMountPoint(); + + Files.createDirectories(mountPoint); + this.createdTemporaryMountPoint = true; + + return mountPoint; + } + @Override public void reveal() throws VolumeException { boolean success = mount.reveal(); @@ -97,6 +131,18 @@ public class DokanyVolume implements Volume { @Override public void unmount() { mount.close(); + cleanupTemporaryMountPoint(); + } + + private void cleanupTemporaryMountPoint() { + if (createdTemporaryMountPoint) { + try { + Files.delete(mountPoint); + LOG.debug("Successfully deleted mount point: {}", mountPoint); + } catch (IOException e) { + LOG.warn("Could not delete mount point: {}", e.getMessage()); + } + } } @Override diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/FuseVolume.java b/main/commons/src/main/java/org/cryptomator/common/vaults/FuseVolume.java index 8d5ebd81a..c9b08b0ed 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/FuseVolume.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/FuseVolume.java @@ -73,13 +73,15 @@ public class FuseVolume implements Volume { return mountPoint; } - mountPoint = windowsDriveLetters.getAvailableDriveLetterPath().orElseThrow(() -> { - //TODO: Error Handling/Fallback (replace Exception with Flow to folderbased?) - return new VolumeException("No free drive letter available."); - }); - return mountPoint; + //No chosen Driveltter -> Is there a free Driveletter? + Optional optionalDriveLetter = windowsDriveLetters.getAvailableDriveLetterPath(); + if(optionalDriveLetter.isPresent()) { + mountPoint = optionalDriveLetter.get(); + return mountPoint; + } + //No free or chosen Driveletter -> Continue below } - //Nothing worked so far or we are not using Windows - Choose and prepare a folder + //Nothing has worked so far -> Choose and prepare a folder mountPoint = prepareTemporaryMountPoint(); LOG.debug("Successfully created mount point: {}", mountPoint); return mountPoint; @@ -130,7 +132,7 @@ public class FuseVolume implements Volume { private Path chooseNonExistingTemporaryMountPoint() throws VolumeException { Path parent = environment.getMountPointsDir().orElseThrow(); - String basename = vaultSettings.getId(); + String basename = vaultSettings.getId(); //FIXME for (int i = 0; i < MAX_TMPMOUNTPOINT_CREATION_RETRIES; i++) { Path mountPoint = parent.resolve(basename + "_" + i); if (Files.notExists(mountPoint)) {