From cbd08fa2d1b8b9e30d10840c5104f8684dd3f274 Mon Sep 17 00:00:00 2001 From: andreatp Date: Fri, 30 Oct 2026 16:48:00 +0000 Subject: [PATCH] Honour lookup flags in path_filestat_set_times Times were always set on the symlink target, even without SYMLINK_FOLLOW. Enables the symlink_filestat test. --- wasi-tests/pom.xml | 2 -- .../run/endive/wasi/WasiPreview1Test.java | 34 +++++++++++++++++++ .../java/run/endive/wasi/WasiPreview1.java | 8 +++-- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/wasi-tests/pom.xml b/wasi-tests/pom.xml index ed3814a8e..36cca68d0 100644 --- a/wasi-tests/pom.xml +++ b/wasi-tests/pom.xml @@ -105,8 +105,6 @@ tests/c/testsuite/wasm32-wasip1/pwrite-with-append.wasm tests/rust/testsuite/wasm32-wasip1/dangling_symlink.wasm - - tests/rust/testsuite/wasm32-wasip1/symlink_filestat.wasm tests/rust/testsuite/wasm32-wasip1/fd_fdstat_set_rights.wasm tests/rust/testsuite/wasm32-wasip1/truncation_rights.wasm diff --git a/wasi-tests/src/test/java/run/endive/wasi/WasiPreview1Test.java b/wasi-tests/src/test/java/run/endive/wasi/WasiPreview1Test.java index 1e7e217d7..c32847eec 100644 --- a/wasi-tests/src/test/java/run/endive/wasi/WasiPreview1Test.java +++ b/wasi-tests/src/test/java/run/endive/wasi/WasiPreview1Test.java @@ -3,8 +3,11 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.Files.createDirectory; import static java.nio.file.Files.createSymbolicLink; +import static java.nio.file.Files.getLastModifiedTime; import static java.nio.file.Files.writeString; +import static java.nio.file.LinkOption.NOFOLLOW_LINKS; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -260,6 +263,37 @@ public void fdReadNegativeIovLenShouldReturnEinval() throws IOException { } } + @Test + public void pathFilestatSetTimesHonoursLookupFlags() throws IOException { + try (var fs = newZeroFs()) { + Path root = fs.getPath("test"); + createDirectory(root); + writeString(root.resolve("file"), "hello"); + createSymbolicLink(root.resolve("link"), fs.getPath("file")); + long fileTime = getLastModifiedTime(root.resolve("file")).toMillis(); + try (var wasi = wasiWithDirectory(root.toString(), root)) { + int result = + wasi.pathFilestatSetTimes( + 3, 0, "link", 0, SECONDS.toNanos(1), WasiFstFlags.MTIM); + assertEquals(WasiErrno.ESUCCESS.value(), result); + assertEquals( + 1000, getLastModifiedTime(root.resolve("link"), NOFOLLOW_LINKS).toMillis()); + assertEquals(fileTime, getLastModifiedTime(root.resolve("file")).toMillis()); + + result = + wasi.pathFilestatSetTimes( + 3, + WasiLookupFlags.SYMLINK_FOLLOW, + "link", + 0, + SECONDS.toNanos(2), + WasiFstFlags.MTIM); + assertEquals(WasiErrno.ESUCCESS.value(), result); + assertEquals(2000, getLastModifiedTime(root.resolve("file")).toMillis()); + } + } + } + @Test public void symlinkEscapeShouldReturnEacces() throws IOException { Path tmpDir = java.nio.file.Files.createTempDirectory("wasi-symlink-test"); diff --git a/wasi/src/main/java/run/endive/wasi/WasiPreview1.java b/wasi/src/main/java/run/endive/wasi/WasiPreview1.java index 12d4832e9..ac385d93c 100644 --- a/wasi/src/main/java/run/endive/wasi/WasiPreview1.java +++ b/wasi/src/main/java/run/endive/wasi/WasiPreview1.java @@ -1075,7 +1075,8 @@ public int pathFilestatSetTimes( return wasiResult(WasiErrno.EACCES); } - return wasiResult(setFileTimes(path, modifiedTime, accessTime, fstFlags)); + return wasiResult( + setFileTimes(path, modifiedTime, accessTime, fstFlags, toLinkOptions(lookupFlags))); } private static final class ResolvedSymlink { @@ -1798,7 +1799,8 @@ private long clockTime(int clockId) { } } - private WasiErrno setFileTimes(Path path, long modifiedTime, long accessTime, int flags) { + private WasiErrno setFileTimes( + Path path, long modifiedTime, long accessTime, int flags, LinkOption... options) { boolean modifiedSet = flagSet(flags, WasiFstFlags.MTIM); boolean modifiedNow = flagSet(flags, WasiFstFlags.MTIM_NOW); boolean accessSet = flagSet(flags, WasiFstFlags.ATIM); @@ -1812,7 +1814,7 @@ private WasiErrno setFileTimes(Path path, long modifiedTime, long accessTime, in FileTime lastAccessTime = toFileTime(accessTime, accessSet, accessNow); try { - Files.getFileAttributeView(path, BasicFileAttributeView.class) + Files.getFileAttributeView(path, BasicFileAttributeView.class, options) .setTimes(lastModifiedTime, lastAccessTime, null); } catch (IOException e) { return WasiErrno.EIO;