Delete automatically generated mount point after locking, attempt to fix #773

This commit is contained in:
Sebastian Stenzel
2019-01-31 15:38:05 +01:00
parent 384c9de7aa
commit 98cab7e4d8

View File

@@ -1,14 +1,5 @@
package org.cryptomator.ui.model;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.inject.Inject;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystem;
@@ -20,65 +11,84 @@ import org.cryptomator.frontend.fuse.mount.Mount;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FuseVolume implements Volume {
private static final Logger LOG = LoggerFactory.getLogger(FuseVolume.class);
/**
* TODO: dont use fixed Strings and rather set them in some system environment variables in the cryptomator installer and load those!
*/
// TODO: dont use fixed Strings and rather set them in some system environment variables in the cryptomator installer and load those!
private static final String DEFAULT_MOUNTROOTPATH_MAC = System.getProperty("user.home") + "/Library/Application Support/Cryptomator";
private static final String DEFAULT_MOUNTROOTPATH_LINUX = System.getProperty("user.home") + "/.Cryptomator";
private static final int MAX_TMPMOUNTPOINT_CREATION_RETRIES = 10;
private final VaultSettings vaultSettings;
private Mount fuseMnt;
private Path mountPath;
private boolean extraDirCreated;
private Path mountPoint;
private boolean createdTemporaryMountPoint;
@Inject
public FuseVolume(VaultSettings vaultSettings) {
this.vaultSettings = vaultSettings;
this.extraDirCreated = false;
this.createdTemporaryMountPoint = false;
}
@Override
public void mount(CryptoFileSystem fs) throws IOException, FuseNotSupportedException, VolumeException {
String mountPath;
if (vaultSettings.usesIndividualMountPath().get()) {
//specific path given
mountPath = vaultSettings.individualMountPath().get();
Path customMountPoint = Paths.get(vaultSettings.individualMountPath().get());
checkProvidedMountPoint(customMountPoint);
this.mountPoint = customMountPoint;
LOG.debug("Successfully checked custom mount point: {}", mountPoint);
} else {
//choose default path & create extra directory
mountPath = createDirIfNotExist(SystemUtils.IS_OS_MAC ? DEFAULT_MOUNTROOTPATH_MAC : DEFAULT_MOUNTROOTPATH_LINUX, vaultSettings.mountName().get());
extraDirCreated = true;
this.mountPoint = createTemporaryMountPoint();
createdTemporaryMountPoint = true;
LOG.debug("Successfully created mount point: {}", mountPoint);
}
this.mountPath = Paths.get(mountPath).toAbsolutePath();
mount(fs.getPath("/"));
}
private String createDirIfNotExist(String prefix, String dirName) throws IOException {
Path p = Paths.get(prefix, dirName + vaultSettings.getId());
if (Files.isDirectory(p)) {
try (DirectoryStream<Path> emptyCheck = Files.newDirectoryStream(p)) {
if (emptyCheck.iterator().hasNext()) {
throw new DirectoryNotEmptyException("Mount point is not empty.");
} else {
LOG.info("Directory already exists and is empty. Using it as mount point.");
return p.toString();
}
}
} else {
Files.createDirectory(p);
return p.toString();
private void checkProvidedMountPoint(Path mountPoint) throws IOException {
if (!Files.isDirectory(mountPoint)) {
throw new NotDirectoryException(mountPoint.toString());
}
try (DirectoryStream<Path> ds = Files.newDirectoryStream(mountPoint)) {
if (ds.iterator().hasNext()) {
throw new DirectoryNotEmptyException(mountPoint.toString());
}
}
}
private Path createTemporaryMountPoint() throws IOException {
Path parent = Paths.get(SystemUtils.IS_OS_MAC ? DEFAULT_MOUNTROOTPATH_MAC : DEFAULT_MOUNTROOTPATH_LINUX);
String basename = vaultSettings.getId();
for (int i = 0; i < MAX_TMPMOUNTPOINT_CREATION_RETRIES; i++) {
try {
Path mountPath = parent.resolve(basename + "_" + i);
Files.createDirectory(mountPath);
return mountPath;
} catch (FileAlreadyExistsException e) {
continue;
}
}
LOG.error("Failed to create mount path at {}/{}_x. Giving up after {} attempts.", parent, basename, MAX_TMPMOUNTPOINT_CREATION_RETRIES);
throw new FileAlreadyExistsException(parent.toString() + "/" + basename);
}
private void mount(Path root) throws VolumeException {
try {
EnvironmentVariables envVars = EnvironmentVariables.create()
.withMountName(vaultSettings.mountName().getValue())
.withMountPath(mountPath)
EnvironmentVariables envVars = EnvironmentVariables.create() //
.withMountName(vaultSettings.mountName().getValue()) //
.withMountPath(mountPoint) //
.build();
this.fuseMnt = FuseMountFactory.getMounter().mount(root, envVars);
} catch (CommandFailedException e) {
@@ -91,7 +101,7 @@ public class FuseVolume implements Volume {
try {
fuseMnt.revealInFileManager();
} catch (CommandFailedException e) {
LOG.info("Revealing the vault in file manger failed: " + e.getMessage());
LOG.debug("Revealing the vault in file manger failed: " + e.getMessage());
throw new VolumeException(e);
}
}
@@ -103,15 +113,16 @@ public class FuseVolume implements Volume {
} catch (CommandFailedException e) {
throw new VolumeException(e);
}
cleanup();
deleteTemporaryMountPoint();
}
private void cleanup() {
if (extraDirCreated) {
private void deleteTemporaryMountPoint() {
if (createdTemporaryMountPoint) {
try {
Files.delete(mountPath);
Files.delete(mountPoint);
LOG.debug("Successfully deleted mount point: {}", mountPoint);
} catch (IOException e) {
LOG.warn("Could not delete mounting directory:" + e.getMessage());
LOG.warn("Could not delete mount point: {}", e.getMessage());
}
}
}