mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-18 10:41:26 +00:00
fixes #948
This commit is contained in:
@@ -11,8 +11,10 @@ import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.binding.StringBinding;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
@@ -25,7 +27,6 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Module
|
||||
public class VaultModule {
|
||||
@@ -52,94 +53,87 @@ public class VaultModule {
|
||||
@PerVault
|
||||
@DefaultMountFlags
|
||||
public StringBinding provideDefaultMountFlags(Settings settings, VaultSettings vaultSettings) {
|
||||
BooleanBinding isMacFuse = new ReadOnlyBooleanWrapper(SystemUtils.IS_OS_MAC_OSX).and(settings.preferredVolumeImpl().isEqualTo(VolumeImpl.FUSE));
|
||||
BooleanBinding isLinuxFuse = new ReadOnlyBooleanWrapper(SystemUtils.IS_OS_LINUX).and(settings.preferredVolumeImpl().isEqualTo(VolumeImpl.FUSE));
|
||||
BooleanBinding isWinDokany = new ReadOnlyBooleanWrapper(SystemUtils.IS_OS_WINDOWS).and(settings.preferredVolumeImpl().isEqualTo(VolumeImpl.DOKANY));
|
||||
ObjectProperty<VolumeImpl> preferredVolumeImpl = settings.preferredVolumeImpl();
|
||||
StringProperty mountName = vaultSettings.mountName();
|
||||
BooleanProperty readOnly = vaultSettings.usesReadOnlyMode();
|
||||
|
||||
return Bindings.when(isMacFuse) // IF isMacFuse
|
||||
.then(getMacFuseDefaultMountFlags(vaultSettings)) //
|
||||
.otherwise(Bindings.when(isLinuxFuse) // ELSE IF isLinuxFuse
|
||||
.then(getLinuxFuseDefaultMountFlags(vaultSettings)) //
|
||||
.otherwise(Bindings.when(isWinDokany) // ELSE IF isWinDokany
|
||||
.then(getDokanyDefaultMountFlags(vaultSettings)) //
|
||||
.otherwise("--flags-supported-on-FUSE-or-DOKANY-only") // ELSE
|
||||
) //
|
||||
);
|
||||
return Bindings.createStringBinding(() -> {
|
||||
VolumeImpl v = preferredVolumeImpl.get();
|
||||
if (v == VolumeImpl.FUSE && SystemUtils.IS_OS_MAC) {
|
||||
return getMacFuseDefaultMountFlags(mountName, readOnly);
|
||||
} else if (v == VolumeImpl.FUSE && SystemUtils.IS_OS_LINUX) {
|
||||
return getLinuxFuseDefaultMountFlags(readOnly);
|
||||
} else if (v == VolumeImpl.DOKANY && SystemUtils.IS_OS_WINDOWS) {
|
||||
return getDokanyDefaultMountFlags(readOnly);
|
||||
} else {
|
||||
return "--flags-supported-on-FUSE-or-DOKANY-only";
|
||||
}
|
||||
}, mountName, readOnly, preferredVolumeImpl);
|
||||
}
|
||||
|
||||
// see: https://github.com/osxfuse/osxfuse/wiki/Mount-options
|
||||
private StringBinding getMacFuseDefaultMountFlags(VaultSettings vaultSettings) {
|
||||
private String getMacFuseDefaultMountFlags(ReadOnlyStringProperty mountName, ReadOnlyBooleanProperty readOnly) {
|
||||
assert SystemUtils.IS_OS_MAC_OSX;
|
||||
StringProperty mountName = vaultSettings.mountName();
|
||||
BooleanProperty readOnly = vaultSettings.usesReadOnlyMode();
|
||||
return Bindings.createStringBinding(() -> {
|
||||
StringBuilder flags = new StringBuilder();
|
||||
if (readOnly.get()) {
|
||||
flags.append(" -ordonly");
|
||||
}
|
||||
flags.append(" -ovolname=").append(mountName.get());
|
||||
flags.append(" -oatomic_o_trunc");
|
||||
flags.append(" -oauto_xattr");
|
||||
flags.append(" -oauto_cache");
|
||||
flags.append(" -omodules=iconv,from_code=UTF-8,to_code=UTF-8-MAC"); // show files names in Unicode NFD encoding
|
||||
flags.append(" -onoappledouble"); // vastly impacts performance for some reason...
|
||||
flags.append(" -odefault_permissions"); // let the kernel assume permissions based on file attributes etc
|
||||
StringBuilder flags = new StringBuilder();
|
||||
if (readOnly.get()) {
|
||||
flags.append(" -ordonly");
|
||||
}
|
||||
flags.append(" -ovolname=").append(mountName.get());
|
||||
flags.append(" -oatomic_o_trunc");
|
||||
flags.append(" -oauto_xattr");
|
||||
flags.append(" -oauto_cache");
|
||||
flags.append(" -omodules=iconv,from_code=UTF-8,to_code=UTF-8-MAC"); // show files names in Unicode NFD encoding
|
||||
flags.append(" -onoappledouble"); // vastly impacts performance for some reason...
|
||||
flags.append(" -odefault_permissions"); // let the kernel assume permissions based on file attributes etc
|
||||
|
||||
try {
|
||||
Path userHome = Paths.get(System.getProperty("user.home"));
|
||||
int uid = (int) Files.getAttribute(userHome, "unix:uid");
|
||||
int gid = (int) Files.getAttribute(userHome, "unix:gid");
|
||||
flags.append(" -ouid=").append(uid);
|
||||
flags.append(" -ogid=").append(gid);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Could not read uid/gid from USER_HOME", e);
|
||||
}
|
||||
try {
|
||||
Path userHome = Paths.get(System.getProperty("user.home"));
|
||||
int uid = (int) Files.getAttribute(userHome, "unix:uid");
|
||||
int gid = (int) Files.getAttribute(userHome, "unix:gid");
|
||||
flags.append(" -ouid=").append(uid);
|
||||
flags.append(" -ogid=").append(gid);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Could not read uid/gid from USER_HOME", e);
|
||||
}
|
||||
|
||||
return flags.toString().strip();
|
||||
}, mountName, readOnly);
|
||||
return flags.toString().strip();
|
||||
}
|
||||
|
||||
// see https://manpages.debian.org/testing/fuse/mount.fuse.8.en.html
|
||||
private StringBinding getLinuxFuseDefaultMountFlags(VaultSettings vaultSettings) {
|
||||
private String getLinuxFuseDefaultMountFlags(ReadOnlyBooleanProperty readOnly) {
|
||||
assert SystemUtils.IS_OS_LINUX;
|
||||
BooleanProperty readOnly = vaultSettings.usesReadOnlyMode();
|
||||
return Bindings.createStringBinding(() -> {
|
||||
StringBuilder flags = new StringBuilder();
|
||||
if (readOnly.get()) {
|
||||
flags.append(" -oro");
|
||||
}
|
||||
flags.append(" -oauto_unmount");
|
||||
StringBuilder flags = new StringBuilder();
|
||||
if (readOnly.get()) {
|
||||
flags.append(" -oro");
|
||||
}
|
||||
flags.append(" -oauto_unmount");
|
||||
|
||||
try {
|
||||
Path userHome = Paths.get(System.getProperty("user.home"));
|
||||
int uid = (int) Files.getAttribute(userHome, "unix:uid");
|
||||
int gid = (int) Files.getAttribute(userHome, "unix:gid");
|
||||
flags.append(" -ouid=").append(uid);
|
||||
flags.append(" -ogid=").append(gid);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Could not read uid/gid from USER_HOME", e);
|
||||
}
|
||||
try {
|
||||
Path userHome = Paths.get(System.getProperty("user.home"));
|
||||
int uid = (int) Files.getAttribute(userHome, "unix:uid");
|
||||
int gid = (int) Files.getAttribute(userHome, "unix:gid");
|
||||
flags.append(" -ouid=").append(uid);
|
||||
flags.append(" -ogid=").append(gid);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Could not read uid/gid from USER_HOME", e);
|
||||
}
|
||||
|
||||
return flags.toString().strip();
|
||||
}, readOnly);
|
||||
return flags.toString().strip();
|
||||
}
|
||||
|
||||
// see https://github.com/cryptomator/dokany-nio-adapter/blob/develop/src/main/java/org/cryptomator/frontend/dokany/MountUtil.java#L30-L34
|
||||
private StringBinding getDokanyDefaultMountFlags(VaultSettings vaultSettings) {
|
||||
private String getDokanyDefaultMountFlags(ReadOnlyBooleanProperty readOnly) {
|
||||
assert SystemUtils.IS_OS_WINDOWS;
|
||||
BooleanProperty readOnly = vaultSettings.usesReadOnlyMode();
|
||||
return Bindings.createStringBinding(() -> {
|
||||
StringBuilder flags = new StringBuilder();
|
||||
flags.append(" --options CURRENT_SESSION");
|
||||
if (readOnly.get()) {
|
||||
flags.append(",WRITE_PROTECTION");
|
||||
}
|
||||
flags.append(" --thread-count 5");
|
||||
flags.append(" --timeout 10000");
|
||||
flags.append(" --allocation-unit-size 4096");
|
||||
flags.append(" --sector-size 4096");
|
||||
return flags.toString().strip();
|
||||
}, readOnly);
|
||||
StringBuilder flags = new StringBuilder();
|
||||
flags.append(" --options CURRENT_SESSION");
|
||||
if (readOnly.get()) {
|
||||
flags.append(",WRITE_PROTECTION");
|
||||
}
|
||||
flags.append(" --thread-count 5");
|
||||
flags.append(" --timeout 10000");
|
||||
flags.append(" --allocation-unit-size 4096");
|
||||
flags.append(" --sector-size 4096");
|
||||
return flags.toString().strip();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.cryptomator.common.vaults;
|
||||
|
||||
import javafx.beans.binding.StringBinding;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.common.settings.VolumeImpl;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public class VaultModuleTest {
|
||||
|
||||
private final Settings settings = Mockito.mock(Settings.class);
|
||||
private final VaultSettings vaultSettings = Mockito.mock(VaultSettings.class);
|
||||
|
||||
private final VaultModule module = new VaultModule();
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
Mockito.when(vaultSettings.mountName()).thenReturn(new SimpleStringProperty("TEST"));
|
||||
Mockito.when(vaultSettings.usesReadOnlyMode()).thenReturn(new SimpleBooleanProperty(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provideDefaultMountFlags on Mac/FUSE")
|
||||
@EnabledOnOs(OS.MAC)
|
||||
public void testMacFuseDefaultMountFlags() {
|
||||
Mockito.when(settings.preferredVolumeImpl()).thenReturn(new SimpleObjectProperty<>(VolumeImpl.FUSE));
|
||||
|
||||
StringBinding result = module.provideDefaultMountFlags(settings, vaultSettings);
|
||||
|
||||
MatcherAssert.assertThat(result.get(), CoreMatchers.containsString("-ovolname=TEST"));
|
||||
MatcherAssert.assertThat(result.get(), CoreMatchers.containsString("-ordonly"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provideDefaultMountFlags on Linux/FUSE")
|
||||
@EnabledOnOs(OS.LINUX)
|
||||
public void testLinuxFuseDefaultMountFlags() {
|
||||
Mockito.when(settings.preferredVolumeImpl()).thenReturn(new SimpleObjectProperty<>(VolumeImpl.FUSE));
|
||||
|
||||
StringBinding result = module.provideDefaultMountFlags(settings, vaultSettings);
|
||||
|
||||
MatcherAssert.assertThat(result.get(), CoreMatchers.containsString("-oro"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provideDefaultMountFlags on Windows/Dokany")
|
||||
@EnabledOnOs(OS.WINDOWS)
|
||||
public void testWinDokanyDefaultMountFlags() {
|
||||
Mockito.when(settings.preferredVolumeImpl()).thenReturn(new SimpleObjectProperty<>(VolumeImpl.DOKANY));
|
||||
|
||||
StringBinding result = module.provideDefaultMountFlags(settings, vaultSettings);
|
||||
|
||||
MatcherAssert.assertThat(result.get(), CoreMatchers.containsString("--options CURRENT_SESSION,WRITE_PROTECTION"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user