Sfoglia il codice sorgente

Added support for folderbased backup-mountpoint to DokanyVol and FuseVol

JaniruTEC 4 anni fa
parent
commit
4f2120b729

+ 54 - 8
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())) {
+		}
+		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.");
-			});
 		}
+
+		//auto assign drive letter
+		Optional<Path> 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

+ 9 - 7
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<Path> 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)) {