Skip to content

Commit 325b4c3

Browse files
committed
Merge branch 'release/0.6.3'
2 parents 171a297 + 77c871a commit 325b4c3

File tree

20 files changed

+147
-36
lines changed

20 files changed

+147
-36
lines changed

jfuse-api/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.cryptomator</groupId>
77
<artifactId>jfuse-parent</artifactId>
8-
<version>0.6.2</version>
8+
<version>0.6.3</version>
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111
<artifactId>jfuse-api</artifactId>

jfuse-api/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
exports org.cryptomator.jfuse.api;
1212
exports org.cryptomator.jfuse.api.platforms to org.cryptomator.jfuse.linux.aarch64, org.cryptomator.jfuse.linux.amd64, org.cryptomator.jfuse.mac, org.cryptomator.jfuse.win;
13+
exports org.cryptomator.jfuse.api.util to org.cryptomator.jfuse.linux.aarch64, org.cryptomator.jfuse.linux.amd64, org.cryptomator.jfuse.mac, org.cryptomator.jfuse.win;
1314

1415
uses FuseBuilder;
1516
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.cryptomator.jfuse.api.util;
2+
3+
import org.jetbrains.annotations.Nullable;
4+
5+
import java.lang.foreign.MemorySegment;
6+
7+
public class MemoryUtils {
8+
9+
@Nullable
10+
public static String toUtf8StringOrNull(MemorySegment string, long offset) {
11+
return MemorySegment.NULL.equals(string) ? null : string.getUtf8String(offset);
12+
}
13+
14+
@Nullable
15+
public static String toUtf8StringOrNull(MemorySegment string) {
16+
return toUtf8StringOrNull(string, 0);
17+
}
18+
}

jfuse-api/src/test/java/org/cryptomator/jfuse/api/FuseTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void testWaitForMountingToComplete() throws IOException {
5050

5151
@Test
5252
@DisplayName("waitForMountingToComplete() waits returns immediately if fuse_loop fails")
53-
public void testPrematurelyFuseLoopReturn() throws IOException {
53+
public void testPrematurelyFuseLoopReturn() {
5454
Path probePath = Mockito.mock(Path.class, "/mnt/jfuse_mount_probe");
5555
FileSystem fs = Mockito.mock(FileSystem.class);
5656
FileSystemProvider fsProv = Mockito.mock(FileSystemProvider.class);
@@ -76,18 +76,26 @@ public void testMountThrowsIllegalStateIfClosed() {
7676
@Test
7777
@DisplayName("Already mounted fuseMount throws IllegalStateException on mount")
7878
public void testMountThrowsIllegalStateIfAlreadyMounted() throws InterruptedException {
79+
// mount probe succeeds immediately...
7980
Mockito.doNothing().when(fuse).waitForMountingToComplete(Mockito.eq(mountPoint), Mockito.any());
81+
// ... before fuse_loop returns
82+
Mockito.doAnswer(invocation -> {
83+
Thread.sleep(1000);
84+
return 0;
85+
}).when(fuseMount).loop();
8086
Assertions.assertDoesNotThrow(() -> fuse.mount("test3000", mountPoint));
8187
Assertions.assertThrows(IllegalStateException.class, () -> fuse.mount("test3000", mountPoint));
8288
}
8389

8490
@Test
8591
@DisplayName("If fuse_loop instantly returns with non-zero result, throw FuseMountFailedException")
8692
public void testMountThrowsFuseMountFailedIfLoopReturnsNonZero() throws InterruptedException {
93+
// mount probe takes a while...
8794
Mockito.doAnswer(invocation -> {
8895
Thread.sleep(1000);
8996
return null;
9097
}).when(fuse).waitForMountingToComplete(Mockito.eq(mountPoint), Mockito.any());
98+
// ... but fuse_loop returns immediately (with error)
9199
Mockito.doReturn(1).when(fuseMount).loop();
92100
Assertions.assertThrows(FuseMountFailedException.class, () -> fuse.mount("test3000", mountPoint));
93101
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.cryptomator.jfuse.api.util;
2+
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.api.DisplayName;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.lang.foreign.Arena;
8+
import java.lang.foreign.MemorySegment;
9+
10+
public class MemoryUtilsTest {
11+
12+
13+
@Test
14+
@DisplayName("On MemorySegment != NULL pointer, method returns utf8 string in the memory region")
15+
void testValidSegmentReturnsString() {
16+
try (var arena = Arena.ofConfined()) {
17+
var address = arena.allocate(4);
18+
address.setUtf8String(0, "abc");
19+
String result = MemoryUtils.toUtf8StringOrNull(address);
20+
Assertions.assertEquals("abc", result);
21+
}
22+
}
23+
24+
@Test
25+
@DisplayName("With offset, on MemorySegment != NULL pointer, method returns utf8 string in the memory region")
26+
void testValidSegmentReturnsStringAtOffset() {
27+
try (var arena = Arena.ofConfined()) {
28+
var address = arena.allocate(10);
29+
address.setUtf8String(5, "abc");
30+
String result = MemoryUtils.toUtf8StringOrNull(address, 5);
31+
Assertions.assertEquals("abc", result);
32+
}
33+
}
34+
35+
@Test
36+
@DisplayName("When MemorySegment == NULL pointer, method returns null")
37+
void testNullPointerSegmentReturnsNull() {
38+
String result = MemoryUtils.toUtf8StringOrNull(MemorySegment.NULL, 0);
39+
Assertions.assertNull(result);
40+
}
41+
}

jfuse-examples/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.cryptomator</groupId>
77
<artifactId>jfuse-parent</artifactId>
8-
<version>0.6.2</version>
8+
<version>0.6.3</version>
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111
<artifactId>jfuse-examples</artifactId>

jfuse-linux-aarch64/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<artifactId>jfuse-parent</artifactId>
77
<groupId>org.cryptomator</groupId>
8-
<version>0.6.2</version>
8+
<version>0.6.3</version>
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111
<artifactId>jfuse-linux-aarch64</artifactId>

jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FileInfoImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.cryptomator.jfuse.api.FileInfo;
44
import org.cryptomator.jfuse.linux.aarch64.extr.fcntl.fcntl_h;
55
import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.fuse_file_info;
6+
import org.jetbrains.annotations.Nullable;
67

78
import java.lang.foreign.Arena;
89
import java.lang.foreign.MemorySegment;
@@ -22,6 +23,18 @@ record FileInfoImpl(MemorySegment segment) implements FileInfo {
2223
private static final int O_SYNC = fcntl_h.O_SYNC();
2324
private static final int O_DSYNC = fcntl_h.O_DSYNC();
2425

26+
/**
27+
* Factory method to map native memory to an {@link FileInfo} object
28+
*
29+
* @param address the {@link MemorySegment} representing the starting address
30+
* @param scope the {@link Arena} in which this object will be alive
31+
* @return an {@link FileInfo} object or {@code null} if {@code address} is a NULL pointer
32+
*/
33+
@Nullable
34+
public static FileInfoImpl of(MemorySegment address, Arena scope) {
35+
return MemorySegment.NULL.equals(address) ? null : new FileInfoImpl(address, scope);
36+
}
37+
2538
public FileInfoImpl(MemorySegment address, Arena scope) {
2639
this(fuse_file_info.ofAddress(address, scope));
2740
}

jfuse-linux-aarch64/src/main/java/org/cryptomator/jfuse/linux/aarch64/FuseImpl.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.cryptomator.jfuse.api.FuseMount;
66
import org.cryptomator.jfuse.api.FuseMountFailedException;
77
import org.cryptomator.jfuse.api.FuseOperations;
8+
import org.cryptomator.jfuse.api.util.MemoryUtils;
89
import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.fuse_args;
910
import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.fuse_h;
1011
import org.cryptomator.jfuse.linux.aarch64.extr.fuse3.fuse_operations;
@@ -116,14 +117,14 @@ private int access(MemorySegment path, int mask) {
116117

117118
private int chmod(MemorySegment path, int mode, MemorySegment fi) {
118119
try (var arena = Arena.ofConfined()) {
119-
return fuseOperations.chmod(path.getUtf8String(0), mode, new FileInfoImpl(fi, arena));
120+
return fuseOperations.chmod(path.getUtf8String(0), mode, FileInfoImpl.of(fi, arena));
120121
}
121122
}
122123

123124
@VisibleForTesting
124125
int chown(MemorySegment path, int uid, int gid, MemorySegment fi) {
125126
try (var arena = Arena.ofConfined()) {
126-
return fuseOperations.chown(path.getUtf8String(0), uid, gid, new FileInfoImpl(fi, arena));
127+
return fuseOperations.chown(path.getUtf8String(0), uid, gid, FileInfoImpl.of(fi, arena));
127128
}
128129
}
129130

@@ -154,13 +155,13 @@ int fsync(MemorySegment path, int datasync, MemorySegment fi) {
154155
@VisibleForTesting
155156
int fsyncdir(MemorySegment path, int datasync, MemorySegment fi) {
156157
try (var arena = Arena.ofConfined()) {
157-
return fuseOperations.fsyncdir(path.getUtf8String(0), datasync, new FileInfoImpl(fi, arena));
158+
return fuseOperations.fsyncdir(MemoryUtils.toUtf8StringOrNull(path), datasync, new FileInfoImpl(fi, arena));
158159
}
159160
}
160161

161162
private int getattr(MemorySegment path, MemorySegment stat, MemorySegment fi) {
162163
try (var arena = Arena.ofConfined()) {
163-
return fuseOperations.getattr(path.getUtf8String(0), new StatImpl(stat, arena), new FileInfoImpl(fi, arena));
164+
return fuseOperations.getattr(path.getUtf8String(0), new StatImpl(stat, arena), FileInfoImpl.of(fi, arena));
164165
}
165166
}
166167

@@ -229,7 +230,7 @@ private int release(MemorySegment path, MemorySegment fi) {
229230

230231
private int releasedir(MemorySegment path, MemorySegment fi) {
231232
try (var arena = Arena.ofConfined()) {
232-
return fuseOperations.releasedir(path.getUtf8String(0), new FileInfoImpl(fi, arena));
233+
return fuseOperations.releasedir(MemoryUtils.toUtf8StringOrNull(path), new FileInfoImpl(fi, arena));
233234
}
234235
}
235236

@@ -253,7 +254,7 @@ private int symlink(MemorySegment linkname, MemorySegment target) {
253254

254255
private int truncate(MemorySegment path, long size, MemorySegment fi) {
255256
try (var arena = Arena.ofConfined()) {
256-
return fuseOperations.truncate(path.getUtf8String(0), size, new FileInfoImpl(fi, arena));
257+
return fuseOperations.truncate(path.getUtf8String(0), size, FileInfoImpl.of(fi, arena));
257258
}
258259
}
259260

@@ -271,11 +272,11 @@ int utimens(MemorySegment path, MemorySegment times, MemorySegment fi) {
271272
timespec.tv_sec$set(segment, 0);
272273
timespec.tv_nsec$set(segment, stat_h.UTIME_NOW());
273274
var time = new TimeSpecImpl(segment);
274-
return fuseOperations.utimens(path.getUtf8String(0), time, time, new FileInfoImpl(fi, arena));
275+
return fuseOperations.utimens(path.getUtf8String(0), time, time, FileInfoImpl.of(fi, arena));
275276
} else {
276277
var time0 = times.asSlice(0, timespec.$LAYOUT().byteSize());
277278
var time1 = times.asSlice(timespec.$LAYOUT().byteSize(), timespec.$LAYOUT().byteSize());
278-
return fuseOperations.utimens(path.getUtf8String(0), new TimeSpecImpl(time0), new TimeSpecImpl(time1), new FileInfoImpl(fi, arena));
279+
return fuseOperations.utimens(path.getUtf8String(0), new TimeSpecImpl(time0), new TimeSpecImpl(time1), FileInfoImpl.of(fi, arena));
279280
}
280281
}
281282
}

jfuse-linux-amd64/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.cryptomator</groupId>
77
<artifactId>jfuse-parent</artifactId>
8-
<version>0.6.2</version>
8+
<version>0.6.3</version>
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111
<artifactId>jfuse-linux-amd64</artifactId>

0 commit comments

Comments
 (0)