diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93c80624..655ddc1a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,15 +10,18 @@ env: jobs: linux: - name: Test jfuse-linux packages strategy: + fail-fast: false matrix: include: - os: ubuntu-latest arch: x86_64 + fuseLibPath: /usr/lib/x86_64-linux-gnu/libfuse3.so.3 - os: ubuntu-24.04-arm arch: aarch64 + fuseLibPath: /usr/lib/aarch64-linux-gnu/libfuse3.so.3 runs-on: ${{ matrix.os }} + name: Test jfuse-linux-${{ matrix.arch }} steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 @@ -31,7 +34,7 @@ jobs: sudo apt-get update sudo apt-get install fuse3 libfuse3-dev - name: Maven build - run: mvn -B verify -Dfuse.lib.path="/lib/${{ matrix.arch }}-linux-gnu/libfuse3.so.3" --no-transfer-progress + run: mvn -B verify -Dfuse.lib.path="${{ matrix.fuseLibPath }}" --no-transfer-progress - uses: actions/upload-artifact@v4 with: name: coverage-linux-${{ matrix.arch }} diff --git a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseFFIHelper.java b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseFFIHelper.java index 858df5ae..8745923e 100644 --- a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseFFIHelper.java +++ b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseFFIHelper.java @@ -5,24 +5,19 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; /** - * Class for not jextract'able symbols, e.g. fuse_new_31 + * Class for not jextract'able versioned symbols, e.g. fuse_new@FUSE_3.0 */ public class FuseFFIHelper { - - static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() - .or(Linker.nativeLinker().defaultLookup()); - static MemorySegment findOrThrow(String symbol) { - return SYMBOL_LOOKUP.find(symbol) + return FuseSymbolLookup.getInstance().find(symbol) .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); } - private static class fuse_new_31 { + private static class fuse_new { public static final FunctionDescriptor DESC = FunctionDescriptor.of( fuse_h.C_POINTER, fuse_h.C_POINTER, @@ -32,38 +27,17 @@ private static class fuse_new_31 { ); public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle( - findOrThrow("fuse_new_31"), + findOrThrow("fuse_new@FUSE_3.0"), DESC); } - /** - * Function descriptor for: - * {@snippet lang = c: - * struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data) - *} - */ - public static FunctionDescriptor fuse_new_31$descriptor() { - return fuse_new_31.DESC; - } - - - /** - * Downcall method handle for: - * {@snippet lang = c: - * struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data) - *} - */ - public static MethodHandle fuse_new_31$handle() { - return fuse_new_31.HANDLE; - } - /** * {@snippet lang = c: * struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data) *} */ - public static MemorySegment fuse_new_31(MemorySegment args, MemorySegment op, long op_size, MemorySegment private_data) { - var mh$ = fuse_new_31.HANDLE; + public static MemorySegment fuse_new(MemorySegment args, MemorySegment op, long op_size, MemorySegment private_data) { + var mh$ = fuse_new.HANDLE; try { return (MemorySegment) mh$.invokeExact(args, op, op_size, private_data); } catch (Throwable ex$) { diff --git a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseImpl.java b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseImpl.java index 46107004..be6eb47d 100644 --- a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseImpl.java +++ b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseImpl.java @@ -37,7 +37,7 @@ protected FuseMount mount(List args) throws FuseMountFailedException { @VisibleForTesting MemorySegment createFuseFS(FuseArgs fuseArgs) throws FuseMountFailedException { - var fuse = FuseFFIHelper.fuse_new_31(fuseArgs.args(), fuseOperationsStruct, fuseOperationsStruct.byteSize(), MemorySegment.NULL); + var fuse = FuseFFIHelper.fuse_new(fuseArgs.args(), fuseOperationsStruct, fuseOperationsStruct.byteSize(), MemorySegment.NULL); if (MemorySegment.NULL.equals(fuse)) { throw new FuseMountFailedException("fuse_new failed"); } diff --git a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseSymbolLookup.java b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseSymbolLookup.java new file mode 100644 index 00000000..f9631f41 --- /dev/null +++ b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseSymbolLookup.java @@ -0,0 +1,95 @@ +package org.cryptomator.jfuse.linux.aarch64; + +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.invoke.MethodHandle; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_INT; + +public class FuseSymbolLookup implements SymbolLookup { + + private static final int RTLD_NOW = 0x02; + + // https://man7.org/linux/man-pages/man3/dlopen.3.html + private static final FunctionDescriptor DLOPEN = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_INT); + private static final FunctionDescriptor DLERROR = FunctionDescriptor.of(ADDRESS); + + // https://man7.org/linux/man-pages/man3/dlvsym.3.html + private static final FunctionDescriptor DLVSYM = FunctionDescriptor.of(ADDRESS, ADDRESS, ADDRESS, ADDRESS); + private static final FunctionDescriptor DLSYM = FunctionDescriptor.of(ADDRESS, ADDRESS, ADDRESS); + + private final MethodHandle dlopen; + private final MethodHandle dlerror; + private final MethodHandle dlvsym; + private final MethodHandle dlsym; + private final AtomicReference libHandle = new AtomicReference<>(); + + private FuseSymbolLookup() { + var linker = Linker.nativeLinker(); + var defaultLookup = linker.defaultLookup(); + this.dlopen = linker.downcallHandle(defaultLookup.find("dlopen").orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol dlopen")), DLOPEN); + this.dlerror = linker.downcallHandle(defaultLookup.find("dlerror").orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol dlerror")), DLERROR); + this.dlvsym = linker.downcallHandle(defaultLookup.find("dlvsym").orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol dlvsym")), DLVSYM); + this.dlsym = linker.downcallHandle(defaultLookup.find("dlsym").orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol dlsym")), DLSYM); + } + + public static FuseSymbolLookup getInstance() { + return Holder.INSTANCE; + } + + private static class Holder { + private static final FuseSymbolLookup INSTANCE = new FuseSymbolLookup(); + } + + public void open(String libPath) { + try (var session = Arena.ofConfined()) { + MemorySegment handle = (MemorySegment) dlopen.invokeExact(session.allocateFrom(libPath), RTLD_NOW); + libHandle.set(handle); + } catch (Throwable e) { + throw new AssertionError(e); + } + } + + /** + * {@inheritDoc} + * + * @param nameAndVersion the symbol name and version separated by '@'. + */ + @Override + public Optional find(String nameAndVersion) { + var handle = libHandle.get(); + if (handle == null) { + return Optional.empty(); + } + var sep = nameAndVersion.indexOf('@'); + try (var session = Arena.ofConfined()) { + MemorySegment addr = MemorySegment.NULL; + if (sep != -1) { + String name = nameAndVersion.substring(0, sep); + String version = nameAndVersion.substring(sep + 1); + addr = (MemorySegment) dlvsym.invokeExact(handle, session.allocateFrom(name), session.allocateFrom(version)); + } + + if (MemorySegment.NULL.equals(addr)) { + addr = (MemorySegment) dlsym.invokeExact(handle, session.allocateFrom(nameAndVersion)); + } + + if (MemorySegment.NULL.equals(addr)) { + var error = (MemorySegment) dlerror.invokeExact(); + System.err.println("dlvsym failed for symbol " + nameAndVersion + ": " + error.getString(0)); + return Optional.empty(); + } else { + return Optional.of(addr); + } + } catch (Throwable e) { + return Optional.empty(); + } + } + +} \ No newline at end of file diff --git a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/LinuxFuseBuilder.java b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/LinuxFuseBuilder.java index c76abf3f..1cde010e 100644 --- a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/LinuxFuseBuilder.java +++ b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/LinuxFuseBuilder.java @@ -37,6 +37,7 @@ public void setLibraryPath(String libraryPath) { @Override public Fuse build(FuseOperations fuseOperations) throws UnsatisfiedLinkError { if (libraryPath != null) { + FuseSymbolLookup.getInstance().open(libraryPath); System.load(libraryPath); } else { System.loadLibrary(DEFAULT_LIBNAME); diff --git a/jfuse-linux-aarch64/src/test/java/org/cryptomator/jfuse/linux/aarch64/FuseImplTest.java b/jfuse-linux-aarch64/src/test/java/org/cryptomator/jfuse/linux/aarch64/FuseImplTest.java index dd096f58..b8f91c95 100644 --- a/jfuse-linux-aarch64/src/test/java/org/cryptomator/jfuse/linux/aarch64/FuseImplTest.java +++ b/jfuse-linux-aarch64/src/test/java/org/cryptomator/jfuse/linux/aarch64/FuseImplTest.java @@ -4,15 +4,13 @@ import org.cryptomator.jfuse.api.FuseMountFailedException; import org.cryptomator.jfuse.api.FuseOperations; import org.cryptomator.jfuse.api.TimeSpec; -import org.cryptomator.jfuse.linux.aarch64.extr.fuse3_lowlevel.fuse_cmdline_opts; import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.fuse_config; import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.fuse_conn_info; import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.fuse_file_info; import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.fuse_h; import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.timespec; -import org.junit.jupiter.api.AfterEach; +import org.cryptomator.jfuse.linux.aarch64.extr.fuse3_lowlevel.fuse_cmdline_opts; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -20,7 +18,6 @@ import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Answers; -import org.mockito.MockedStatic; import org.mockito.Mockito; import java.lang.foreign.Arena; @@ -45,7 +42,7 @@ public class Mount { @DisplayName("MountFailedException when fuse_new fails") public void testFuseNewFails() { try (var fuseH = Mockito.mockStatic(FuseFFIHelper.class)) { - fuseH.when(() -> FuseFFIHelper.fuse_new_31(Mockito.any(), Mockito.any(), Mockito.anyLong(), Mockito.any())).thenReturn(MemorySegment.NULL); + fuseH.when(() -> FuseFFIHelper.fuse_new(Mockito.any(), Mockito.any(), Mockito.anyLong(), Mockito.any())).thenReturn(MemorySegment.NULL); var thrown = Assertions.assertThrows(FuseMountFailedException.class, () -> fuseImplSpy.createFuseFS(Mockito.mock(FuseArgs.class))); Assertions.assertEquals("fuse_new failed", thrown.getMessage()); } diff --git a/jfuse-linux-amd64/pom.xml b/jfuse-linux-amd64/pom.xml index 834377b0..2c8c3393 100644 --- a/jfuse-linux-amd64/pom.xml +++ b/jfuse-linux-amd64/pom.xml @@ -100,6 +100,8 @@ _FILE_OFFSET_BITS=64 FUSE_USE_VERSION=317 + __x86_64__=1 + __LP64__=1 fuse_version @@ -144,6 +146,8 @@ _FILE_OFFSET_BITS=64 FUSE_USE_VERSION=317 + __x86_64__=1 + __LP64__=1 fuse_cmdline_opts @@ -159,6 +163,10 @@ ${linux.headerSearchPath}/errno.h org.cryptomator.jfuse.linux.amd64.extr.errno errno_h + + __x86_64__=1 + __LP64__=1 + ENOENT ENOSYS @@ -190,6 +198,10 @@ ${linux.headerSearchPath}/sys/stat.h org.cryptomator.jfuse.linux.amd64.extr.stat stat_h + + __x86_64__=1 + __LP64__=1 + UTIME_NOW UTIME_OMIT @@ -203,8 +215,12 @@ ${linux.headerSearchPath}/fcntl.h - fcntl_h org.cryptomator.jfuse.linux.amd64.extr.fcntl + fcntl_h + + __x86_64__=1 + __LP64__=1 + O_RDONLY O_WRONLY @@ -229,6 +245,8 @@ stdio_h _GNU_SOURCE=1 + __x86_64__=1 + __LP64__=1 diff --git a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseFFIHelper.java b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseFFIHelper.java index 0bb3d97b..1750f24d 100644 --- a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseFFIHelper.java +++ b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseFFIHelper.java @@ -5,24 +5,19 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; /** - * Class for not jextract'able symbols, e.g. fuse_new_31 + * Class for not jextract'able versioned symbols, e.g. fuse_new@FUSE_3.0 */ public class FuseFFIHelper { - - static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup() - .or(Linker.nativeLinker().defaultLookup()); - static MemorySegment findOrThrow(String symbol) { - return SYMBOL_LOOKUP.find(symbol) + return FuseSymbolLookup.getInstance().find(symbol) .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); } - private static class fuse_new_31 { + private static class fuse_new { public static final FunctionDescriptor DESC = FunctionDescriptor.of( fuse_h.C_POINTER, fuse_h.C_POINTER, @@ -32,38 +27,17 @@ private static class fuse_new_31 { ); public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle( - findOrThrow("fuse_new_31"), + findOrThrow("fuse_new@FUSE_3.0"), DESC); } - /** - * Function descriptor for: - * {@snippet lang = c: - * struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data) - *} - */ - public static FunctionDescriptor fuse_new_31$descriptor() { - return fuse_new_31.DESC; - } - - - /** - * Downcall method handle for: - * {@snippet lang = c: - * struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data) - *} - */ - public static MethodHandle fuse_new_31$handle() { - return fuse_new_31.HANDLE; - } - /** * {@snippet lang = c: * struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data) *} */ - public static MemorySegment fuse_new_31(MemorySegment args, MemorySegment op, long op_size, MemorySegment private_data) { - var mh$ = fuse_new_31.HANDLE; + public static MemorySegment fuse_new(MemorySegment args, MemorySegment op, long op_size, MemorySegment private_data) { + var mh$ = fuse_new.HANDLE; try { return (MemorySegment) mh$.invokeExact(args, op, op_size, private_data); } catch (Throwable ex$) { diff --git a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseImpl.java b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseImpl.java index 504d3e13..4a9503b0 100644 --- a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseImpl.java +++ b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseImpl.java @@ -37,7 +37,7 @@ protected FuseMount mount(List args) throws FuseMountFailedException { @VisibleForTesting MemorySegment createFuseFS(FuseArgs fuseArgs) throws FuseMountFailedException { - var fuse = FuseFFIHelper.fuse_new_31(fuseArgs.args(), fuseOperationsStruct, fuseOperationsStruct.byteSize(), MemorySegment.NULL); + var fuse = FuseFFIHelper.fuse_new(fuseArgs.args(), fuseOperationsStruct, fuseOperationsStruct.byteSize(), MemorySegment.NULL); if (MemorySegment.NULL.equals(fuse)) { throw new FuseMountFailedException("fuse_new failed"); } diff --git a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseSymbolLookup.java b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseSymbolLookup.java new file mode 100644 index 00000000..875c0f20 --- /dev/null +++ b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/FuseSymbolLookup.java @@ -0,0 +1,95 @@ +package org.cryptomator.jfuse.linux.amd64; + +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.invoke.MethodHandle; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_INT; + +public class FuseSymbolLookup implements SymbolLookup { + + private static final int RTLD_NOW = 0x02; + + // https://man7.org/linux/man-pages/man3/dlopen.3.html + private static final FunctionDescriptor DLOPEN = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_INT); + private static final FunctionDescriptor DLERROR = FunctionDescriptor.of(ADDRESS); + + // https://man7.org/linux/man-pages/man3/dlvsym.3.html + private static final FunctionDescriptor DLVSYM = FunctionDescriptor.of(ADDRESS, ADDRESS, ADDRESS, ADDRESS); + private static final FunctionDescriptor DLSYM = FunctionDescriptor.of(ADDRESS, ADDRESS, ADDRESS); + + private final MethodHandle dlopen; + private final MethodHandle dlerror; + private final MethodHandle dlvsym; + private final MethodHandle dlsym; + private final AtomicReference libHandle = new AtomicReference<>(); + + private FuseSymbolLookup() { + var linker = Linker.nativeLinker(); + var defaultLookup = linker.defaultLookup(); + this.dlopen = linker.downcallHandle(defaultLookup.find("dlopen").orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol dlopen")), DLOPEN); + this.dlerror = linker.downcallHandle(defaultLookup.find("dlerror").orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol dlerror")), DLERROR); + this.dlvsym = linker.downcallHandle(defaultLookup.find("dlvsym").orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol dlvsym")), DLVSYM); + this.dlsym = linker.downcallHandle(defaultLookup.find("dlsym").orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol dlsym")), DLSYM); + } + + public static FuseSymbolLookup getInstance() { + return Holder.INSTANCE; + } + + private static class Holder { + private static final FuseSymbolLookup INSTANCE = new FuseSymbolLookup(); + } + + public void open(String libPath) { + try (var session = Arena.ofConfined()) { + MemorySegment handle = (MemorySegment) dlopen.invokeExact(session.allocateFrom(libPath), RTLD_NOW); + libHandle.set(handle); + } catch (Throwable e) { + throw new AssertionError(e); + } + } + + /** + * {@inheritDoc} + * + * @param nameAndVersion the symbol name and version separated by '@'. + */ + @Override + public Optional find(String nameAndVersion) { + var handle = libHandle.get(); + if (handle == null) { + return Optional.empty(); + } + var sep = nameAndVersion.indexOf('@'); + try (var session = Arena.ofConfined()) { + MemorySegment addr = MemorySegment.NULL; + if (sep != -1) { + String name = nameAndVersion.substring(0, sep); + String version = nameAndVersion.substring(sep + 1); + addr = (MemorySegment) dlvsym.invokeExact(handle, session.allocateFrom(name), session.allocateFrom(version)); + } + + if (MemorySegment.NULL.equals(addr)) { + addr = (MemorySegment) dlsym.invokeExact(handle, session.allocateFrom(nameAndVersion)); + } + + if (MemorySegment.NULL.equals(addr)) { + var error = (MemorySegment) dlerror.invokeExact(); + System.err.println("dlvsym failed for symbol " + nameAndVersion + ": " + error.getString(0)); + return Optional.empty(); + } else { + return Optional.of(addr); + } + } catch (Throwable e) { + return Optional.empty(); + } + } + +} \ No newline at end of file diff --git a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/LinuxFuseBuilder.java b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/LinuxFuseBuilder.java index bdfebc18..5b4cea90 100644 --- a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/LinuxFuseBuilder.java +++ b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/LinuxFuseBuilder.java @@ -37,6 +37,7 @@ public void setLibraryPath(String libraryPath) { @Override public Fuse build(FuseOperations fuseOperations) throws UnsatisfiedLinkError { if (libraryPath != null) { + FuseSymbolLookup.getInstance().open(libraryPath); System.load(libraryPath); } else { System.loadLibrary(DEFAULT_LIBNAME); diff --git a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/extr/fuse3/statvfs.java b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/extr/fuse3/statvfs.java index 5c0730b7..d6078a5f 100644 --- a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/extr/fuse3/statvfs.java +++ b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/extr/fuse3/statvfs.java @@ -26,8 +26,7 @@ * unsigned long f_fsid; * unsigned long f_flag; * unsigned long f_namemax; - * unsigned int f_type; - * int __f_spare[5]; + * int __f_spare[6]; * } * } */ @@ -49,8 +48,7 @@ public class statvfs { fuse_h.C_LONG.withName("f_fsid"), fuse_h.C_LONG.withName("f_flag"), fuse_h.C_LONG.withName("f_namemax"), - fuse_h.C_INT.withName("f_type"), - MemoryLayout.sequenceLayout(5, fuse_h.C_INT).withName("__f_spare") + MemoryLayout.sequenceLayout(6, fuse_h.C_INT).withName("__f_spare") ).withName("statvfs"); /** @@ -544,68 +542,24 @@ public static void f_namemax(MemorySegment struct, long fieldValue) { struct.set(f_namemax$LAYOUT, f_namemax$OFFSET, fieldValue); } - private static final OfInt f_type$LAYOUT = (OfInt)$LAYOUT.select(groupElement("f_type")); - - /** - * Layout for field: - * {@snippet lang=c : - * unsigned int f_type - * } - */ - public static final OfInt f_type$layout() { - return f_type$LAYOUT; - } - - private static final long f_type$OFFSET = 88; - - /** - * Offset for field: - * {@snippet lang=c : - * unsigned int f_type - * } - */ - public static final long f_type$offset() { - return f_type$OFFSET; - } - - /** - * Getter for field: - * {@snippet lang=c : - * unsigned int f_type - * } - */ - public static int f_type(MemorySegment struct) { - return struct.get(f_type$LAYOUT, f_type$OFFSET); - } - - /** - * Setter for field: - * {@snippet lang=c : - * unsigned int f_type - * } - */ - public static void f_type(MemorySegment struct, int fieldValue) { - struct.set(f_type$LAYOUT, f_type$OFFSET, fieldValue); - } - private static final SequenceLayout __f_spare$LAYOUT = (SequenceLayout)$LAYOUT.select(groupElement("__f_spare")); /** * Layout for field: * {@snippet lang=c : - * int __f_spare[5] + * int __f_spare[6] * } */ public static final SequenceLayout __f_spare$layout() { return __f_spare$LAYOUT; } - private static final long __f_spare$OFFSET = 92; + private static final long __f_spare$OFFSET = 88; /** * Offset for field: * {@snippet lang=c : - * int __f_spare[5] + * int __f_spare[6] * } */ public static final long __f_spare$offset() { @@ -615,7 +569,7 @@ public static void f_type(MemorySegment struct, int fieldValue) { /** * Getter for field: * {@snippet lang=c : - * int __f_spare[5] + * int __f_spare[6] * } */ public static MemorySegment __f_spare(MemorySegment struct) { @@ -625,19 +579,19 @@ public static MemorySegment __f_spare(MemorySegment struct) { /** * Setter for field: * {@snippet lang=c : - * int __f_spare[5] + * int __f_spare[6] * } */ public static void __f_spare(MemorySegment struct, MemorySegment fieldValue) { MemorySegment.copy(fieldValue, 0L, struct, __f_spare$OFFSET, __f_spare$LAYOUT.byteSize()); } - private static long[] __f_spare$DIMS = { 5 }; + private static long[] __f_spare$DIMS = { 6 }; /** * Dimensions for array field: * {@snippet lang=c : - * int __f_spare[5] + * int __f_spare[6] * } */ public static long[] __f_spare$dimensions() { @@ -648,7 +602,7 @@ public static void __f_spare(MemorySegment struct, MemorySegment fieldValue) { /** * Indexed getter for field: * {@snippet lang=c : - * int __f_spare[5] + * int __f_spare[6] * } */ public static int __f_spare(MemorySegment struct, long index0) { @@ -658,7 +612,7 @@ public static int __f_spare(MemorySegment struct, long index0) { /** * Indexed setter for field: * {@snippet lang=c : - * int __f_spare[5] + * int __f_spare[6] * } */ public static void __f_spare(MemorySegment struct, long index0, int fieldValue) { diff --git a/jfuse-linux-amd64/src/test/java/org/cryptomator/jfuse/linux/amd64/FuseImplTest.java b/jfuse-linux-amd64/src/test/java/org/cryptomator/jfuse/linux/amd64/FuseImplTest.java index 242d35a2..35db3fa3 100644 --- a/jfuse-linux-amd64/src/test/java/org/cryptomator/jfuse/linux/amd64/FuseImplTest.java +++ b/jfuse-linux-amd64/src/test/java/org/cryptomator/jfuse/linux/amd64/FuseImplTest.java @@ -42,7 +42,7 @@ public class Mount { @DisplayName("MountFailedException when fuse_new fails") public void testFuseNewFails() { try (var fuseH = Mockito.mockStatic(FuseFFIHelper.class)) { - fuseH.when(() -> FuseFFIHelper.fuse_new_31(Mockito.any(), Mockito.any(), Mockito.anyLong(), Mockito.any())).thenReturn(MemorySegment.NULL); + fuseH.when(() -> FuseFFIHelper.fuse_new(Mockito.any(), Mockito.any(), Mockito.anyLong(), Mockito.any())).thenReturn(MemorySegment.NULL); var thrown = Assertions.assertThrows(FuseMountFailedException.class, () -> fuseImplSpy.createFuseFS(Mockito.mock(FuseArgs.class))); Assertions.assertEquals("fuse_new failed", thrown.getMessage()); } diff --git a/jfuse-tests/src/test/java/org/cryptomator/jfuse/tests/MirrorIT.java b/jfuse-tests/src/test/java/org/cryptomator/jfuse/tests/MirrorIT.java index 4b5b80d0..c6f6bff0 100644 --- a/jfuse-tests/src/test/java/org/cryptomator/jfuse/tests/MirrorIT.java +++ b/jfuse-tests/src/test/java/org/cryptomator/jfuse/tests/MirrorIT.java @@ -69,7 +69,7 @@ public void setup(@TempDir Path tmpDir) throws IOException, FuseMountFailedExcep builder.setLibraryPath(libPath); } List flags = new ArrayList<>(); - flags.add("-s"); + //flags.add("-s"); mirror = tmpDir.resolve("mirror"); orig = tmpDir.resolve("orig"); Files.createDirectories(orig);