From ef8302d0197db280fe8a36043ba17a9b7c1f31a2 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Oct 2022 12:17:22 +0200 Subject: [PATCH 1/4] add accessors for st_uid and st_gid --- .../java/org/cryptomator/jfuse/api/Stat.java | 8 +++ .../org/cryptomator/jfuse/api/StatTest.java | 70 +++---------------- .../jfuse/linux/aarch64/StatImpl.java | 20 ++++++ .../jfuse/linux/amd64/StatImpl.java | 20 ++++++ .../org/cryptomator/jfuse/mac/StatImpl.java | 20 ++++++ .../org/cryptomator/jfuse/win/StatImpl.java | 20 ++++++ 6 files changed, 99 insertions(+), 59 deletions(-) diff --git a/jfuse-api/src/main/java/org/cryptomator/jfuse/api/Stat.java b/jfuse-api/src/main/java/org/cryptomator/jfuse/api/Stat.java index 9d16d292..6fdb3503 100644 --- a/jfuse-api/src/main/java/org/cryptomator/jfuse/api/Stat.java +++ b/jfuse-api/src/main/java/org/cryptomator/jfuse/api/Stat.java @@ -107,6 +107,14 @@ public interface Stat { int getMode(); + void setUid(int uid); + + int getUid(); + + void setGid(int gid); + + int getGid(); + void setNLink(short count); long getNLink(); diff --git a/jfuse-api/src/test/java/org/cryptomator/jfuse/api/StatTest.java b/jfuse-api/src/test/java/org/cryptomator/jfuse/api/StatTest.java index cfcfa811..b6e3f68b 100644 --- a/jfuse-api/src/test/java/org/cryptomator/jfuse/api/StatTest.java +++ b/jfuse-api/src/test/java/org/cryptomator/jfuse/api/StatTest.java @@ -18,7 +18,7 @@ public class StatTest { private static final int MAGIC = 123456;//some rando number - public Stat stat = Mockito.spy(new StubStatImpl()); + public Stat stat = Mockito.mock(Stat.class); @Nested @DisplayName("Test File Type Predicates") @@ -99,7 +99,8 @@ public class Permissions { "0010644,rw-r--r--" }) public void getPermissions(String mode, String perms) { - Mockito.when(stat.getMode()).thenReturn(Integer.valueOf(mode, 8)); + Mockito.doReturn(Integer.valueOf(mode, 8)).when(stat).getMode(); + Mockito.doCallRealMethod().when(stat).getPermissions(); var expected = PosixFilePermissions.fromString(perms); var result = stat.getPermissions(); @@ -114,7 +115,8 @@ public void getPermissions(String mode, String perms) { "0644,rw-r--r--", }) public void setPermissions(String mode, String perms) { - Mockito.when(stat.getMode()).thenReturn(S_IFDIR); + Mockito.doReturn(S_IFDIR).when(stat).getMode(); + Mockito.doCallRealMethod().when(stat).setPermissions(Mockito.any()); var permissions = PosixFilePermissions.fromString(perms); stat.setPermissions(permissions); @@ -127,7 +129,8 @@ public void setPermissions(String mode, String perms) { @ParameterizedTest @ValueSource(booleans = {true, false}) public void testHasMode(boolean isPresent) { - Mockito.when(stat.getMode()).thenReturn(isPresent ? MAGIC : ~MAGIC); + Mockito.doReturn(isPresent ? MAGIC : ~MAGIC).when(stat).getMode(); + Mockito.doCallRealMethod().when(stat).hasMode(Mockito.anyInt()); boolean result = stat.hasMode(MAGIC); @@ -137,7 +140,8 @@ public void testHasMode(boolean isPresent) { @Test @DisplayName("setModeBits()") public void testSetModeBits() { - Mockito.when(stat.getMode()).thenReturn(0755); + Mockito.doReturn(0755).when(stat).getMode(); + Mockito.doCallRealMethod().when(stat).setModeBits(Mockito.anyInt()); stat.setModeBits(S_IFDIR); @@ -147,64 +151,12 @@ public void testSetModeBits() { @Test @DisplayName("unsetModeBits()") public void testUnsetModeBits() { - Mockito.when(stat.getMode()).thenReturn(S_IFDIR | 0755); + Mockito.doReturn(S_IFDIR | 0755).when(stat).getMode(); + Mockito.doCallRealMethod().when(stat).unsetModeBits(Mockito.anyInt()); stat.unsetModeBits(S_IFDIR); Mockito.verify(stat).setMode(0755); } - private static class StubStatImpl implements Stat { - - @Override - public TimeSpec aTime() { - return null; - } - - @Override - public TimeSpec cTime() { - return null; - } - - @Override - public TimeSpec mTime() { - return null; - } - - @Override - public TimeSpec birthTime() { - return null; - } - - @Override - public void setMode(int mode) { - - } - - @Override - public int getMode() { - return 0; - } - - @Override - public void setNLink(short count) { - - } - - @Override - public long getNLink() { - return 0; - } - - @Override - public void setSize(long size) { - - } - - @Override - public long getSize() { - return 0; - } - } - } diff --git a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/StatImpl.java b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/StatImpl.java index 35be683d..2f75b36b 100644 --- a/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/StatImpl.java +++ b/jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/StatImpl.java @@ -46,6 +46,26 @@ public int getMode() { return stat.st_mode$get(segment); } + @Override + public void setUid(int uid) { + stat.st_uid$set(segment, uid); + } + + @Override + public int getUid() { + return stat.st_uid$get(segment); + } + + @Override + public void setGid(int gid) { + stat.st_gid$set(segment, gid); + } + + @Override + public int getGid() { + return stat.st_gid$get(segment); + } + @Override public void setNLink(short count) { stat.st_nlink$set(segment, count); diff --git a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/StatImpl.java b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/StatImpl.java index ad68f710..9200e5ef 100644 --- a/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/StatImpl.java +++ b/jfuse-linux-amd64/src/main/java/org/cryptomator/jfuse/linux/amd64/StatImpl.java @@ -45,6 +45,26 @@ public int getMode() { return stat.st_mode$get(segment); } + @Override + public void setUid(int uid) { + stat.st_uid$set(segment, uid); + } + + @Override + public int getUid() { + return stat.st_uid$get(segment); + } + + @Override + public void setGid(int gid) { + stat.st_gid$set(segment, gid); + } + + @Override + public int getGid() { + return stat.st_gid$get(segment); + } + @Override public void setNLink(short count) { stat.st_nlink$set(segment, count); diff --git a/jfuse-mac/src/main/java/org/cryptomator/jfuse/mac/StatImpl.java b/jfuse-mac/src/main/java/org/cryptomator/jfuse/mac/StatImpl.java index e4e0af51..56bb8ab1 100644 --- a/jfuse-mac/src/main/java/org/cryptomator/jfuse/mac/StatImpl.java +++ b/jfuse-mac/src/main/java/org/cryptomator/jfuse/mac/StatImpl.java @@ -45,6 +45,26 @@ public int getMode() { return stat.st_mode$get(segment); } + @Override + public void setUid(int uid) { + stat.st_uid$set(segment, uid); + } + + @Override + public int getUid() { + return stat.st_uid$get(segment); + } + + @Override + public void setGid(int gid) { + stat.st_gid$set(segment, gid); + } + + @Override + public int getGid() { + return stat.st_gid$get(segment); + } + @Override public void setNLink(short count) { stat.st_nlink$set(segment, count); diff --git a/jfuse-win/src/main/java/org/cryptomator/jfuse/win/StatImpl.java b/jfuse-win/src/main/java/org/cryptomator/jfuse/win/StatImpl.java index 38221522..49e6b92a 100644 --- a/jfuse-win/src/main/java/org/cryptomator/jfuse/win/StatImpl.java +++ b/jfuse-win/src/main/java/org/cryptomator/jfuse/win/StatImpl.java @@ -44,6 +44,26 @@ public int getMode() { return fuse_stat.st_mode$get(segment); } + @Override + public void setUid(int uid) { + fuse_stat.st_uid$set(segment, uid); + } + + @Override + public int getUid() { + return fuse_stat.st_uid$get(segment); + } + + @Override + public void setGid(int gid) { + fuse_stat.st_gid$set(segment, gid); + } + + @Override + public int getGid() { + return fuse_stat.st_gid$get(segment); + } + @Override public void setNLink(short count) { fuse_stat.st_nlink$set(segment, count); From c62671039ba4b9b0134b3fdb6cbdeb335e7afb55 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Oct 2022 13:15:28 +0200 Subject: [PATCH 2/4] add unit tests for `StatImpl` --- .../jfuse/linux/aarch64/StatImplTest.java | 76 +++++++++++++++++++ .../jfuse/linux/amd64/StatImplTest.java | 76 +++++++++++++++++++ .../cryptomator/jfuse/mac/StatImplTest.java | 76 +++++++++++++++++++ .../cryptomator/jfuse/win/StatImplTest.java | 76 +++++++++++++++++++ 4 files changed, 304 insertions(+) create mode 100644 jfuse-linux-aarch64/src/test/java/org/cryptomator/jfuse/linux/aarch64/StatImplTest.java create mode 100644 jfuse-linux-amd64/src/test/java/org/cryptomator/jfuse/linux/amd64/StatImplTest.java create mode 100644 jfuse-mac/src/test/java/org/cryptomator/jfuse/mac/StatImplTest.java create mode 100644 jfuse-win/src/test/java/org/cryptomator/jfuse/win/StatImplTest.java diff --git a/jfuse-linux-aarch64/src/test/java/org/cryptomator/jfuse/linux/aarch64/StatImplTest.java b/jfuse-linux-aarch64/src/test/java/org/cryptomator/jfuse/linux/aarch64/StatImplTest.java new file mode 100644 index 00000000..b13b839f --- /dev/null +++ b/jfuse-linux-aarch64/src/test/java/org/cryptomator/jfuse/linux/aarch64/StatImplTest.java @@ -0,0 +1,76 @@ +package org.cryptomator.jfuse.linux.aarch64; + +import org.cryptomator.jfuse.api.Stat; +import org.cryptomator.jfuse.linux.aarch64.extr.stat; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Named; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Stream; + +public class StatImplTest { + + @DisplayName("test getters") + @ParameterizedTest(name = "{1}") + @MethodSource + public void testGetters(SetInMemorySegment setter, GetInStat getter, Number value) { + try (var scope = MemorySession.openConfined()) { + var segment = stat.allocate(scope); + var stat = new StatImpl(segment.address(), scope); + + setter.accept(segment, value); + + Assertions.assertEquals(value.longValue(), getter.apply(stat).longValue()); + } + } + + public static Stream testGetters() { + return Stream.of( + Arguments.arguments((SetInMemorySegment) stat::st_mode$set, Named.of("getMode()", (GetInStat) Stat::getMode), 42), + Arguments.arguments((SetInMemorySegment) stat::st_uid$set, Named.of("getUid()", (GetInStat) Stat::getUid), 42), + Arguments.arguments((SetInMemorySegment) stat::st_gid$set, Named.of("getGid()", (GetInStat) Stat::getGid), 42), + Arguments.arguments((SetInMemorySegment) stat::st_nlink$set, Named.of("getNLink()", (GetInStat) Stat::getNLink), 42), + Arguments.arguments((SetInMemorySegment) stat::st_size$set, Named.of("getSize()", (GetInStat) Stat::getSize), 42L) + ); + } + + private interface SetInMemorySegment extends BiConsumer {} + + private interface GetInStat extends Function {} + + @DisplayName("test setters") + @ParameterizedTest(name = "{0}") + @MethodSource + public void testSetters(SetInStat setter, GetInMemorySegment getter, Number value) { + try (var scope = MemorySession.openConfined()) { + var segment = stat.allocate(scope); + var stat = new StatImpl(segment.address(), scope); + + setter.accept(stat, value); + + Assertions.assertEquals(value.longValue(), getter.apply(segment).longValue()); + } + } + + public static Stream testSetters() { + return Stream.of( + Arguments.arguments(Named.of("setMode()", (SetInStat) Stat::setMode), (GetInMemorySegment) stat::st_mode$get, 42), + Arguments.arguments(Named.of("setUid()", (SetInStat) Stat::setUid), (GetInMemorySegment) stat::st_uid$get, 42), + Arguments.arguments(Named.of("setGid()", (SetInStat) Stat::setGid), (GetInMemorySegment) stat::st_gid$get, 42), + Arguments.arguments(Named.of("setNLink()", (SetInStat) Stat::setNLink), (GetInMemorySegment) stat::st_nlink$get, (short) 42), + Arguments.arguments(Named.of("setSize()", (SetInStat) Stat::setSize), (GetInMemorySegment) stat::st_size$get, 42L) + ); + } + + private interface SetInStat extends BiConsumer {} + + private interface GetInMemorySegment extends Function {} + +} \ No newline at end of file diff --git a/jfuse-linux-amd64/src/test/java/org/cryptomator/jfuse/linux/amd64/StatImplTest.java b/jfuse-linux-amd64/src/test/java/org/cryptomator/jfuse/linux/amd64/StatImplTest.java new file mode 100644 index 00000000..d898189a --- /dev/null +++ b/jfuse-linux-amd64/src/test/java/org/cryptomator/jfuse/linux/amd64/StatImplTest.java @@ -0,0 +1,76 @@ +package org.cryptomator.jfuse.linux.amd64; + +import org.cryptomator.jfuse.api.Stat; +import org.cryptomator.jfuse.linux.amd64.extr.stat; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Named; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Stream; + +public class StatImplTest { + + @DisplayName("test getters") + @ParameterizedTest(name = "{1}") + @MethodSource + public void testGetters(SetInMemorySegment setter, GetInStat getter, Number value) { + try (var scope = MemorySession.openConfined()) { + var segment = stat.allocate(scope); + var stat = new StatImpl(segment.address(), scope); + + setter.accept(segment, value); + + Assertions.assertEquals(value.longValue(), getter.apply(stat).longValue()); + } + } + + public static Stream testGetters() { + return Stream.of( + Arguments.arguments((SetInMemorySegment) stat::st_mode$set, Named.of("getMode()", (GetInStat) Stat::getMode), 42), + Arguments.arguments((SetInMemorySegment) stat::st_uid$set, Named.of("getUid()", (GetInStat) Stat::getUid), 42), + Arguments.arguments((SetInMemorySegment) stat::st_gid$set, Named.of("getGid()", (GetInStat) Stat::getGid), 42), + Arguments.arguments((SetInMemorySegment) stat::st_nlink$set, Named.of("getNLink()", (GetInStat) Stat::getNLink), 42L), + Arguments.arguments((SetInMemorySegment) stat::st_size$set, Named.of("getSize()", (GetInStat) Stat::getSize), 42L) + ); + } + + private interface SetInMemorySegment extends BiConsumer {} + + private interface GetInStat extends Function {} + + @DisplayName("test setters") + @ParameterizedTest(name = "{0}") + @MethodSource + public void testSetters(SetInStat setter, GetInMemorySegment getter, Number value) { + try (var scope = MemorySession.openConfined()) { + var segment = stat.allocate(scope); + var stat = new StatImpl(segment.address(), scope); + + setter.accept(stat, value); + + Assertions.assertEquals(value.longValue(), getter.apply(segment).longValue()); + } + } + + public static Stream testSetters() { + return Stream.of( + Arguments.arguments(Named.of("setMode()", (SetInStat) Stat::setMode), (GetInMemorySegment) stat::st_mode$get, 42), + Arguments.arguments(Named.of("setUid()", (SetInStat) Stat::setUid), (GetInMemorySegment) stat::st_uid$get, 42), + Arguments.arguments(Named.of("setGid()", (SetInStat) Stat::setGid), (GetInMemorySegment) stat::st_gid$get, 42), + Arguments.arguments(Named.of("setNLink()", (SetInStat) Stat::setNLink), (GetInMemorySegment) stat::st_nlink$get, (short) 42), + Arguments.arguments(Named.of("setSize()", (SetInStat) Stat::setSize), (GetInMemorySegment) stat::st_size$get, 42L) + ); + } + + private interface SetInStat extends BiConsumer {} + + private interface GetInMemorySegment extends Function {} + +} \ No newline at end of file diff --git a/jfuse-mac/src/test/java/org/cryptomator/jfuse/mac/StatImplTest.java b/jfuse-mac/src/test/java/org/cryptomator/jfuse/mac/StatImplTest.java new file mode 100644 index 00000000..fb31d70f --- /dev/null +++ b/jfuse-mac/src/test/java/org/cryptomator/jfuse/mac/StatImplTest.java @@ -0,0 +1,76 @@ +package org.cryptomator.jfuse.mac; + +import org.cryptomator.jfuse.api.Stat; +import org.cryptomator.jfuse.mac.extr.stat; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Named; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Stream; + +public class StatImplTest { + + @DisplayName("test getters") + @ParameterizedTest(name = "{1}") + @MethodSource + public void testGetters(SetInMemorySegment setter, GetInStat getter, Number value) { + try (var scope = MemorySession.openConfined()) { + var segment = stat.allocate(scope); + var stat = new StatImpl(segment.address(), scope); + + setter.accept(segment, value); + + Assertions.assertEquals(value.longValue(), getter.apply(stat).longValue()); + } + } + + public static Stream testGetters() { + return Stream.of( + Arguments.arguments((SetInMemorySegment) stat::st_mode$set, Named.of("getMode()", (GetInStat) Stat::getMode), (short) 42), + Arguments.arguments((SetInMemorySegment) stat::st_uid$set, Named.of("getUid()", (GetInStat) Stat::getUid), 42), + Arguments.arguments((SetInMemorySegment) stat::st_gid$set, Named.of("getGid()", (GetInStat) Stat::getGid), 42), + Arguments.arguments((SetInMemorySegment) stat::st_nlink$set, Named.of("getNLink()", (GetInStat) Stat::getNLink), (short) 42), + Arguments.arguments((SetInMemorySegment) stat::st_size$set, Named.of("getSize()", (GetInStat) Stat::getSize), 42L) + ); + } + + private interface SetInMemorySegment extends BiConsumer {} + + private interface GetInStat extends Function {} + + @DisplayName("test setters") + @ParameterizedTest(name = "{0}") + @MethodSource + public void testSetters(SetInStat setter, GetInMemorySegment getter, Number value) { + try (var scope = MemorySession.openConfined()) { + var segment = stat.allocate(scope); + var stat = new StatImpl(segment.address(), scope); + + setter.accept(stat, value); + + Assertions.assertEquals(value.longValue(), getter.apply(segment).longValue()); + } + } + + public static Stream testSetters() { + return Stream.of( + Arguments.arguments(Named.of("setMode()", (SetInStat) Stat::setMode), (GetInMemorySegment) stat::st_mode$get, 42), + Arguments.arguments(Named.of("setUid()", (SetInStat) Stat::setUid), (GetInMemorySegment) stat::st_uid$get, 42), + Arguments.arguments(Named.of("setGid()", (SetInStat) Stat::setGid), (GetInMemorySegment) stat::st_gid$get, 42), + Arguments.arguments(Named.of("setNLink()", (SetInStat) Stat::setNLink), (GetInMemorySegment) stat::st_nlink$get, (short) 42), + Arguments.arguments(Named.of("setSize()", (SetInStat) Stat::setSize), (GetInMemorySegment) stat::st_size$get, 42L) + ); + } + + private interface SetInStat extends BiConsumer {} + + private interface GetInMemorySegment extends Function {} + +} \ No newline at end of file diff --git a/jfuse-win/src/test/java/org/cryptomator/jfuse/win/StatImplTest.java b/jfuse-win/src/test/java/org/cryptomator/jfuse/win/StatImplTest.java new file mode 100644 index 00000000..13ecddd0 --- /dev/null +++ b/jfuse-win/src/test/java/org/cryptomator/jfuse/win/StatImplTest.java @@ -0,0 +1,76 @@ +package org.cryptomator.jfuse.win; + +import org.cryptomator.jfuse.api.Stat; +import org.cryptomator.jfuse.win.extr.fuse_stat; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Named; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Stream; + +public class StatImplTest { + + @DisplayName("test getters") + @ParameterizedTest(name = "{1}") + @MethodSource + public void testGetters(SetInMemorySegment setter, GetInStat getter, Number value) { + try (var scope = MemorySession.openConfined()) { + var segment = fuse_stat.allocate(scope); + var stat = new StatImpl(segment.address(), scope); + + setter.accept(segment, value); + + Assertions.assertEquals(value.longValue(), getter.apply(stat).longValue()); + } + } + + public static Stream testGetters() { + return Stream.of( + Arguments.arguments((SetInMemorySegment) fuse_stat::st_mode$set, Named.of("getMode()", (GetInStat) Stat::getMode), 42), + Arguments.arguments((SetInMemorySegment) fuse_stat::st_uid$set, Named.of("getUid()", (GetInStat) Stat::getUid), 42), + Arguments.arguments((SetInMemorySegment) fuse_stat::st_gid$set, Named.of("getGid()", (GetInStat) Stat::getGid), 42), + Arguments.arguments((SetInMemorySegment) fuse_stat::st_nlink$set, Named.of("getNLink()", (GetInStat) Stat::getNLink), (short) 42), + Arguments.arguments((SetInMemorySegment) fuse_stat::st_size$set, Named.of("getSize()", (GetInStat) Stat::getSize), 42L) + ); + } + + private interface SetInMemorySegment extends BiConsumer {} + + private interface GetInStat extends Function {} + + @DisplayName("test setters") + @ParameterizedTest(name = "{0}") + @MethodSource + public void testSetters(SetInStat setter, GetInMemorySegment getter, Number value) { + try (var scope = MemorySession.openConfined()) { + var segment = fuse_stat.allocate(scope); + var stat = new StatImpl(segment.address(), scope); + + setter.accept(stat, value); + + Assertions.assertEquals(value.longValue(), getter.apply(segment).longValue()); + } + } + + public static Stream testSetters() { + return Stream.of( + Arguments.arguments(Named.of("setMode()", (SetInStat) Stat::setMode), (GetInMemorySegment) fuse_stat::st_mode$get, 42), + Arguments.arguments(Named.of("setUid()", (SetInStat) Stat::setUid), (GetInMemorySegment) fuse_stat::st_uid$get, 42), + Arguments.arguments(Named.of("setGid()", (SetInStat) Stat::setGid), (GetInMemorySegment) fuse_stat::st_gid$get, 42), + Arguments.arguments(Named.of("setNLink()", (SetInStat) Stat::setNLink), (GetInMemorySegment) fuse_stat::st_nlink$get, (short) 42), + Arguments.arguments(Named.of("setSize()", (SetInStat) Stat::setSize), (GetInMemorySegment) fuse_stat::st_size$get, 42L) + ); + } + + private interface SetInStat extends BiConsumer {} + + private interface GetInMemorySegment extends Function {} + +} \ No newline at end of file From ce8c829c4fbb1a7f7f0f3bde0e659f85ff526a36 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Oct 2022 15:23:18 +0200 Subject: [PATCH 3/4] add `chown` support --- .../org/cryptomator/jfuse/api/FuseOperations.java | 1 + .../cryptomator/jfuse/linux/aarch64/FuseImpl.java | 8 ++++++++ .../jfuse/linux/aarch64/FuseImplTest.java | 13 +++++++++++++ .../cryptomator/jfuse/linux/amd64/FuseImpl.java | 8 ++++++++ .../jfuse/linux/amd64/FuseImplTest.java | 14 ++++++++++++++ .../java/org/cryptomator/jfuse/mac/FuseImpl.java | 6 ++++++ .../org/cryptomator/jfuse/mac/FuseImplTest.java | 13 +++++++++++++ .../java/org/cryptomator/jfuse/win/FuseImpl.java | 8 ++++++++ .../org/cryptomator/jfuse/win/FuseImplTest.java | 14 ++++++++++++++ 9 files changed, 85 insertions(+) diff --git a/jfuse-api/src/main/java/org/cryptomator/jfuse/api/FuseOperations.java b/jfuse-api/src/main/java/org/cryptomator/jfuse/api/FuseOperations.java index 1cec1b9c..efe9e712 100644 --- a/jfuse-api/src/main/java/org/cryptomator/jfuse/api/FuseOperations.java +++ b/jfuse-api/src/main/java/org/cryptomator/jfuse/api/FuseOperations.java @@ -16,6 +16,7 @@ public interface FuseOperations { enum Operation { ACCESS, CHMOD, + CHOWN, CREATE, DESTROY, GET_ATTR, 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 a8e1edeb..25d64b17 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 @@ -76,6 +76,7 @@ private void bind(FuseOperations.Operation operation) { case INIT -> fuse_operations.init$set(fuseOps, fuse_operations.init.allocate(this::init, fuseScope).address()); case ACCESS -> fuse_operations.access$set(fuseOps, fuse_operations.access.allocate(this::access, fuseScope).address()); case CHMOD -> fuse_operations.chmod$set(fuseOps, fuse_operations.chmod.allocate(this::chmod, fuseScope).address()); + case CHOWN -> fuse_operations.chown$set(fuseOps, fuse_operations.chown.allocate(this::chown, fuseScope).address()); case CREATE -> fuse_operations.create$set(fuseOps, fuse_operations.create.allocate(this::create, fuseScope).address()); case DESTROY -> fuse_operations.destroy$set(fuseOps, fuse_operations.destroy.allocate(this::destroy, fuseScope).address()); case GET_ATTR -> fuse_operations.getattr$set(fuseOps, fuse_operations.getattr.allocate(this::getattr, fuseScope).address()); @@ -119,6 +120,13 @@ private int chmod(MemoryAddress path, int mode, MemoryAddress fi) { } } + @VisibleForTesting + int chown(MemoryAddress path, int uid, int gid, MemoryAddress fi) { + try (var scope = MemorySession.openConfined()) { + return delegate.chown(path.getUtf8String(0), uid, gid, new FileInfoImpl(fi, scope)); + } + } + private int create(MemoryAddress path, int mode, MemoryAddress fi) { try (var scope = MemorySession.openConfined()) { return delegate.create(path.getUtf8String(0), mode, new FileInfoImpl(fi, scope)); 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 a0fb328b..04afad4c 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 @@ -186,4 +186,17 @@ public void testUtimens(long sec0, long nsec0, long sec1, long nsec1) { } } + @Test + @DisplayName("chown") + public void testChown() { + try (var scope = MemorySession.openConfined()) { + var path = scope.allocateUtf8String("/foo"); + var fi = fuse_file_info.allocate(scope); + Mockito.doReturn(42).when(fuseOps).chown(Mockito.eq("/foo"), Mockito.eq(42), Mockito.eq(1337), Mockito.any()); + + var result = fuseImpl.chown(path.address(), 42, 1337, fi.address()); + + Assertions.assertEquals(42, result); + } + } } \ No newline at end of file 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 57eb3db4..0b392678 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 @@ -76,6 +76,7 @@ private void bind(FuseOperations.Operation operation) { case INIT -> fuse_operations.init$set(fuseOps, fuse_operations.init.allocate(this::init, fuseScope).address()); case ACCESS -> fuse_operations.access$set(fuseOps, fuse_operations.access.allocate(this::access, fuseScope).address()); case CHMOD -> fuse_operations.chmod$set(fuseOps, fuse_operations.chmod.allocate(this::chmod, fuseScope).address()); + case CHOWN -> fuse_operations.chown$set(fuseOps, fuse_operations.chown.allocate(this::chown, fuseScope).address()); case CREATE -> fuse_operations.create$set(fuseOps, fuse_operations.create.allocate(this::create, fuseScope).address()); case DESTROY -> fuse_operations.destroy$set(fuseOps, fuse_operations.destroy.allocate(this::destroy, fuseScope).address()); case GET_ATTR -> fuse_operations.getattr$set(fuseOps, fuse_operations.getattr.allocate(this::getattr, fuseScope).address()); @@ -119,6 +120,13 @@ private int chmod(MemoryAddress path, int mode, MemoryAddress fi) { } } + @VisibleForTesting + int chown(MemoryAddress path, int uid, int gid, MemoryAddress fi) { + try (var scope = MemorySession.openConfined()) { + return delegate.chown(path.getUtf8String(0), uid, gid, new FileInfoImpl(fi, scope)); + } + } + private int create(MemoryAddress path, int mode, MemoryAddress fi) { try (var scope = MemorySession.openConfined()) { return delegate.create(path.getUtf8String(0), mode, new FileInfoImpl(fi, scope)); 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 931f729c..774b688e 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 @@ -186,4 +186,18 @@ public void testUtimens(long sec0, long nsec0, long sec1, long nsec1) { } } + @Test + @DisplayName("chown") + public void testChown() { + try (var scope = MemorySession.openConfined()) { + var path = scope.allocateUtf8String("/foo"); + var fi = fuse_file_info.allocate(scope); + Mockito.doReturn(42).when(fuseOps).chown(Mockito.eq("/foo"), Mockito.eq(42), Mockito.eq(1337), Mockito.any()); + + var result = fuseImpl.chown(path.address(), 42, 1337, fi.address()); + + Assertions.assertEquals(42, result); + } + } + } \ No newline at end of file diff --git a/jfuse-mac/src/main/java/org/cryptomator/jfuse/mac/FuseImpl.java b/jfuse-mac/src/main/java/org/cryptomator/jfuse/mac/FuseImpl.java index 61dc604a..1449c949 100644 --- a/jfuse-mac/src/main/java/org/cryptomator/jfuse/mac/FuseImpl.java +++ b/jfuse-mac/src/main/java/org/cryptomator/jfuse/mac/FuseImpl.java @@ -78,6 +78,7 @@ private void bind(FuseOperations.Operation operation) { case INIT -> fuse_operations.init$set(fuseOps, fuse_operations.init.allocate(this::init, fuseScope).address()); case ACCESS -> fuse_operations.access$set(fuseOps, fuse_operations.access.allocate(this::access, fuseScope).address()); case CHMOD -> fuse_operations.chmod$set(fuseOps, fuse_operations.chmod.allocate(this::chmod, fuseScope).address()); + case CHOWN -> fuse_operations.chown$set(fuseOps, fuse_operations.chown.allocate(this::chown, fuseScope).address()); case CREATE -> fuse_operations.create$set(fuseOps, fuse_operations.create.allocate(this::create, fuseScope).address()); case DESTROY -> fuse_operations.destroy$set(fuseOps, fuse_operations.destroy.allocate(this::destroy, fuseScope).address()); case GET_ATTR -> { @@ -121,6 +122,11 @@ private int chmod(MemoryAddress path, short mode) { return delegate.chmod(path.getUtf8String(0), mode, null); } + @VisibleForTesting + int chown(MemoryAddress path, int uid, int gid) { + return delegate.chown(path.getUtf8String(0), uid, gid, null); + } + private int create(MemoryAddress path, short mode, MemoryAddress fi) { try (var scope = MemorySession.openConfined()) { return delegate.create(path.getUtf8String(0), mode, new FileInfoImpl(fi, scope)); diff --git a/jfuse-mac/src/test/java/org/cryptomator/jfuse/mac/FuseImplTest.java b/jfuse-mac/src/test/java/org/cryptomator/jfuse/mac/FuseImplTest.java index 9e4140d4..81ff5343 100644 --- a/jfuse-mac/src/test/java/org/cryptomator/jfuse/mac/FuseImplTest.java +++ b/jfuse-mac/src/test/java/org/cryptomator/jfuse/mac/FuseImplTest.java @@ -212,4 +212,17 @@ public void testFtruncate() { } + @Test + @DisplayName("chown") + public void testChown() { + try (var scope = MemorySession.openConfined()) { + var path = scope.allocateUtf8String("/foo"); + Mockito.doReturn(42).when(fuseOps).chown("/foo", 42, 1337, null); + + var result = fuseImpl.chown(path.address(), 42, 1337); + + Assertions.assertEquals(42, result); + } + } + } \ No newline at end of file diff --git a/jfuse-win/src/main/java/org/cryptomator/jfuse/win/FuseImpl.java b/jfuse-win/src/main/java/org/cryptomator/jfuse/win/FuseImpl.java index 750374c3..1b3293de 100644 --- a/jfuse-win/src/main/java/org/cryptomator/jfuse/win/FuseImpl.java +++ b/jfuse-win/src/main/java/org/cryptomator/jfuse/win/FuseImpl.java @@ -120,6 +120,7 @@ private void bind(FuseOperations.Operation operation) { case INIT -> fuse3_operations.init$set(fuseOps, fuse3_operations.init.allocate(this::init, fuseScope).address()); case ACCESS -> fuse3_operations.access$set(fuseOps, MemoryAddress.NULL); case CHMOD -> fuse3_operations.chmod$set(fuseOps, fuse3_operations.chmod.allocate(this::chmod, fuseScope).address()); + case CHOWN -> fuse3_operations.chown$set(fuseOps, fuse3_operations.chown.allocate(this::chown, fuseScope).address()); case CREATE -> fuse3_operations.create$set(fuseOps, fuse3_operations.create.allocate(this::create, fuseScope).address()); case DESTROY -> fuse3_operations.destroy$set(fuseOps, fuse3_operations.destroy.allocate(this::destroy, fuseScope).address()); case GET_ATTR -> fuse3_operations.getattr$set(fuseOps, fuse3_operations.getattr.allocate(this::getattr, fuseScope).address()); @@ -159,6 +160,13 @@ private int chmod(MemoryAddress path, int mode, MemoryAddress fi) { } } + @VisibleForTesting + int chown(MemoryAddress path, int uid, int gid, MemoryAddress fi) { + try (var scope = MemorySession.openConfined()) { + return delegate.chown(path.getUtf8String(0), uid, gid, new FileInfoImpl(fi, scope)); + } + } + private int create(MemoryAddress path, int mode, MemoryAddress fi) { try (var scope = MemorySession.openConfined()) { return delegate.create(path.getUtf8String(0), mode, new FileInfoImpl(fi, scope)); diff --git a/jfuse-win/src/test/java/org/cryptomator/jfuse/win/FuseImplTest.java b/jfuse-win/src/test/java/org/cryptomator/jfuse/win/FuseImplTest.java index 5f6a3bb5..f7209a35 100644 --- a/jfuse-win/src/test/java/org/cryptomator/jfuse/win/FuseImplTest.java +++ b/jfuse-win/src/test/java/org/cryptomator/jfuse/win/FuseImplTest.java @@ -244,6 +244,20 @@ public void testTruncate() { } } + @Test + @DisplayName("chown") + public void testChown() { + try (var scope = MemorySession.openConfined()) { + var path = scope.allocateUtf8String("/foo"); + var fi = fuse3_file_info.allocate(scope); + Mockito.doReturn(42).when(fuseOps).chown(Mockito.eq("/foo"), Mockito.eq(42), Mockito.eq(1337), Mockito.any()); + + var result = fuseImpl.chown(path.address(), 42, 1337, fi.address()); + + Assertions.assertEquals(42, result); + } + } + private static ArgumentMatcher usesSameMemorySegement(MemorySegment expected) { return obj -> { if (obj instanceof FileInfoImpl fiImpl) { From f29fb6ceae2c8349e875286c13ae0ff7a61a1fe0 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 18 Oct 2022 16:55:09 +0200 Subject: [PATCH 4/4] mark chown as supported [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 00c1c90c..99433e95 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Not all [`fuse_operations`](https://libfuse.github.io/doxygen/structfuse__operat | rename | :white_check_mark: | | link | :x: | | chmod | :white_check_mark: | -| chown | :x: | +| chown | :white_check_mark: | | truncate | :white_check_mark: | | ~ftruncate~ | use truncate | | ~utime~ | use utimens |