Repository: tetratelabs/wazero
Pull request #1220 (2023-03-12 09:09:38)

wasi: implements path_filestat_set_times
This implements `path_filestat_set_times` which is the last remaining filesystem function in wasi we formerly stubbed.

Other minor changes:
* this removes all places we import alias path as pathutil, introducing a utility function `joinPath` where that was used to reduce name conflicts.
* this fixes places where we used different variable names for the same parameter between main and test source.

codefromthecrypt: @mathetake PTAL I added a utility function `joinPath` to reduce the main problem around path.Join, so nothing aliases it anymore.

Patch:
diff --git a/imports/wasi_snapshot_preview1/fs.go b/imports/wasi_snapshot_preview1/fs.go
index 2fdb95f6..292a5023 100644
--- a/imports/wasi_snapshot_preview1/fs.go
+++ b/imports/wasi_snapshot_preview1/fs.go
@@ -6,7 +6,7 @@ import (
 	"io"
 	"io/fs"
 	"math"
-	pathutil "path"
+	"path"
 	"reflect"
 	"syscall"
 	"unsafe"
@@ -425,6 +425,8 @@ var fdFilestatSetTimes = newHostFunc(
 
 func fdFilestatSetTimesFn(_ context.Context, mod api.Module, params []uint64) Errno {
 	fd := uint32(params[0])
+	atim := int64(params[1])
+	mtim := int64(params[2])
 	fstFlags := uint16(params[3])
 
 	sys := mod.(*wasm.CallContext).Sys
@@ -435,14 +437,32 @@ func fdFilestatSetTimesFn(_ context.Context, mod api.Module, params []uint64) Er
 		return ErrnoBadf
 	}
 
+	times, errno := toTimes(atim, mtim, fstFlags)
+	if errno != ErrnoSuccess {
+		return errno
+	}
+
+	// Try to update the file timestamps by file-descriptor.
+	err := platform.UtimensFile(f.File, &times)
+
+	// Fall back to path based, despite it being less precise.
+	switch err {
+	case syscall.EPERM, syscall.ENOSYS:
+		err = f.FS.Utimens(f.Name, &times, true)
+	}
+
+	return ToErrno(err)
+}
+
+func toTimes(atim, mtime int64, fstFlags uint16) (times [2]syscall.Timespec, errno Errno) {
 	// times[0] == atim, times[1] == mtim
-	times := [2]syscall.Timespec{}
 
 	// coerce atim into a timespec
-	if set, now := fstFlags&FileStatAdjustFlagsAtim != 0, fstFlags&FileStatAdjustFlagsAtimNow != 0; set && now {
-		return ErrnoInval
+	if set, now := fstFlags&FstflagsAtim != 0, fstFlags&FstflagsAtimNow != 0; set && now {
+		errno = ErrnoInval
+		return
 	} else if set {
-		times[0] = syscall.NsecToTimespec(int64(params[1]))
+		times[0] = syscall.NsecToTimespec(atim)
 	} else if now {
 		times[0].Nsec = platform.UTIME_NOW
 	} else {
@@ -450,26 +470,17 @@ func fdFilestatSetTimesFn(_ context.Context, mod api.Module, params []uint64) Er
 	}
 
 	// coerce mtim into a timespec
-	if set, now := fstFlags&FileStatAdjustFlagsMtim != 0, fstFlags&FileStatAdjustFlagsMtimNow != 0; set && now {
-		return ErrnoInval
+	if set, now := fstFlags&FstflagsMtim != 0, fstFlags&FstflagsMtimNow != 0; set && now {
+		errno = ErrnoInval
+		return
 	} else if set {
-		times[1] = syscall.NsecToTimespec(int64(params[2]))
+		times[1] = syscall.NsecToTimespec(mtime)
 	} else if now {
 		times[1].Nsec = platform.UTIME_NOW
 	} else {
 		times[1].Nsec = platform.UTIME_OMIT
 	}
-
-	// Try to update the file timestamps by file-descriptor.
-	err := platform.UtimensFile(f.File, &times)
-
-	// Fall back to path based, despite it being less precise.
-	switch err {
-	case syscall.EPERM, syscall.ENOSYS:
-		err = f.FS.Utimens(f.Name, &times, true)
-	}
-
-	return ToErrno(err)
+	return
 }
 
 // fdPread is the WASI function named FdPreadName which reads from a file
@@ -882,7 +893,7 @@ func dotDirents(f *sys.FileEntry) ([]*platform.Dirent, error) {
 	dotDotIno := uint64(0)
 	if !f.IsPreopen && f.Name != "." {
 		var st platform.Stat_t
-		if err = f.FS.Stat(pathutil.Dir(f.Name), &st); err != nil {
+		if err = f.FS.Stat(path.Dir(f.Name), &st); err != nil {
 			return nil, err
 		}
 		dotDotIno = st.Ino
@@ -1349,11 +1360,11 @@ var pathCreateDirectory = newHostFunc(
 func pathCreateDirectoryFn(_ context.Context, mod api.Module, params []uint64) Errno {
 	fsc := mod.(*wasm.CallContext).Sys.FS()
 
-	dirFD := uint32(params[0])
+	fd := uint32(params[0])
 	path := uint32(params[1])
 	pathLen := uint32(params[2])
 
-	preopen, pathName, errno := atPath(fsc, mod.Memory(), dirFD, path, pathLen)
+	preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen)
 	if errno != ErrnoSuccess {
 		return errno
 	}
@@ -1402,7 +1413,7 @@ var pathFilestatGet = newHostFunc(
 func pathFilestatGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
 	fsc := mod.(*wasm.CallContext).Sys.FS()
 
-	dirFD := uint32(params[0])
+	fd := uint32(params[0])
 
 	// TODO: flags is a lookupflags and it only has one bit: symlink_follow
 	// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#lookupflags
@@ -1411,7 +1422,7 @@ func pathFilestatGetFn(_ context.Context, mod api.Module, params []uint64) Errno
 	path := uint32(params[2])
 	pathLen := uint32(params[3])
 
-	preopen, pathName, errno := atPath(fsc, mod.Memory(), dirFD, path, pathLen)
+	preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen)
 	if errno != ErrnoSuccess {
 		return errno
 	}
@@ -1439,12 +1450,39 @@ func pathFilestatGetFn(_ context.Context, mod api.Module, params []uint64) Errno
 // which adjusts the timestamps of a file or directory.
 //
 // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_set_timesfd-fd-flags-lookupflags-path-string-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno
-var pathFilestatSetTimes = stubFunction(
-	PathFilestatSetTimesName,
+var pathFilestatSetTimes = newHostFunc(
+	PathFilestatSetTimesName, pathFilestatSetTimesFn,
 	[]wasm.ValueType{i32, i32, i32, i32, i64, i64, i32},
 	"fd", "flags", "path", "path_len", "atim", "mtim", "fst_flags",
 )
 
+func pathFilestatSetTimesFn(_ context.Context, mod api.Module, params []uint64) Errno {
+	fd := uint32(params[0])
+	flags := uint16(params[1])
+	path := uint32(params[2])
+	pathLen := uint32(params[3])
+	atim := int64(params[4])
+	mtim := int64(params[5])
+	fstFlags := uint16(params[6])
+
+	sys := mod.(*wasm.CallContext).Sys
+	fsc := sys.FS()
+
+	times, errno := toTimes(atim, mtim, fstFlags)
+	if errno != ErrnoSuccess {
+		return errno
+	}
+
+	preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen)
+	if errno != ErrnoSuccess {
+		return errno
+	}
+
+	symlinkFollow := flags&LOOKUP_SYMLINK_FOLLOW != 0
+	err := preopen.Utimens(pathName, &times, symlinkFollow)
+	return ToErrno(err)
+}
+
 // pathLink is the WASI function named PathLinkName which adjusts the
 // timestamps of a file or directory.
 //
@@ -1470,11 +1508,11 @@ func pathLinkFn(_ context.Context, mod api.Module, params []uint64) Errno {
 		return errno
 	}
 
-	newFd := uint32(params[4])
+	newFD := uint32(params[4])
 	newPath := uint32(params[5])
 	newPathLen := uint32(params[6])
 
-	newFS, newName, errno := atPath(fsc, mem, newFd, newPath, newPathLen)
+	newFS, newName, errno := atPath(fsc, mem, newFD, newPath, newPathLen)
 	if errno != ErrnoSuccess {
 		return errno
 	}
@@ -1611,24 +1649,24 @@ func pathOpenFn(_ context.Context, mod api.Module, params []uint64) Errno {
 //
 // Languages including Zig and Rust use only pre-opens for the FD because
 // wasi-libc `__wasilibc_find_relpath` will only return a preopen. That said,
-// our wasi.c example shows other languages act differently and can use dirFD
-// of a non-preopen.
+// our wasi.c example shows other languages act differently and can use a non
+// pre-opened file descriptor.
 //
-// We don't handle AT_FDCWD, as that's resolved in the compiler. There's no
+// We don't handle `AT_FDCWD`, as that's resolved in the compiler. There's no
 // working directory function in WASI, so most assume CWD is "/". Notably, Zig
 // has different behavior which assumes it is whatever the first pre-open name
 // is.
 //
 // See https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/libc-bottom-half/sources/at_fdcwd.c
 // See https://linux.die.net/man/2/openat
-func atPath(fsc *sys.FSContext, mem api.Memory, dirFD, path, pathLen uint32) (sysfs.FS, string, Errno) {
+func atPath(fsc *sys.FSContext, mem api.Memory, fd, path, pathLen uint32) (sysfs.FS, string, Errno) {
 	b, ok := mem.Read(path, pathLen)
 	if !ok {
 		return nil, "", ErrnoFault
 	}
 	pathName := string(b)
 
-	if f, ok := fsc.LookupFile(dirFD); !ok {
+	if f, ok := fsc.LookupFile(fd); !ok {
 		return nil, "", ErrnoBadf // closed
 	} else if _, ft, err := f.CachedStat(); err != nil {
 		return nil, "", ToErrno(err)
@@ -1637,12 +1675,13 @@ func atPath(fsc *sys.FSContext, mem api.Memory, dirFD, path, pathLen uint32) (sy
 	} else if f.IsPreopen { // don't append the pre-open name
 		return f.FS, pathName, ErrnoSuccess
 	} else {
-		return f.FS, pathutil.Join(f.Name, pathName), ErrnoSuccess
+		// Join via concat to avoid name conflict on path.Join
+		return f.FS, f.Name + "/" + pathName, ErrnoSuccess
 	}
 }
 
-func preopenPath(fsc *sys.FSContext, dirFD uint32) (string, Errno) {
-	if f, ok := fsc.LookupFile(dirFD); !ok {
+func preopenPath(fsc *sys.FSContext, fd uint32) (string, Errno) {
+	if f, ok := fsc.LookupFile(fd); !ok {
 		return "", ErrnoBadf // closed
 	} else if !f.IsPreopen {
 		return "", ErrnoBadf
@@ -1692,9 +1731,9 @@ func pathReadlinkFn(_ context.Context, mod api.Module, params []uint64) Errno {
 	fd := uint32(params[0])
 	path := uint32(params[1])
 	pathLen := uint32(params[2])
-	bufPtr := uint32(params[3])
+	buf := uint32(params[3])
 	bufLen := uint32(params[4])
-	resultBufUsedPtr := uint32(params[5])
+	resultBufused := uint32(params[5])
 
 	if pathLen == 0 || bufLen == 0 {
 		return ErrnoInval
@@ -1711,11 +1750,11 @@ func pathReadlinkFn(_ context.Context, mod api.Module, params []uint64) Errno {
 		return ToErrno(err)
 	}
 
-	if ok := mem.WriteString(bufPtr, dst); !ok {
+	if ok := mem.WriteString(buf, dst); !ok {
 		return ErrnoFault
 	}
 
-	if !mem.WriteUint32Le(resultBufUsedPtr, uint32(len(dst))) {
+	if !mem.WriteUint32Le(resultBufused, uint32(len(dst))) {
 		return ErrnoFault
 	}
 	return ErrnoSuccess
@@ -1752,11 +1791,11 @@ var pathRemoveDirectory = newHostFunc(
 func pathRemoveDirectoryFn(_ context.Context, mod api.Module, params []uint64) Errno {
 	fsc := mod.(*wasm.CallContext).Sys.FS()
 
-	dirFD := uint32(params[0])
+	fd := uint32(params[0])
 	path := uint32(params[1])
 	pathLen := uint32(params[2])
 
-	preopen, pathName, errno := atPath(fsc, mod.Memory(), dirFD, path, pathLen)
+	preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen)
 	if errno != ErrnoSuccess {
 		return errno
 	}
@@ -1802,20 +1841,20 @@ var pathRename = newHostFunc(
 func pathRenameFn(_ context.Context, mod api.Module, params []uint64) Errno {
 	fsc := mod.(*wasm.CallContext).Sys.FS()
 
-	olddirFD := uint32(params[0])
+	fd := uint32(params[0])
 	oldPath := uint32(params[1])
 	oldPathLen := uint32(params[2])
 
-	newdirFD := uint32(params[3])
+	newFD := uint32(params[3])
 	newPath := uint32(params[4])
 	newPathLen := uint32(params[5])
 
-	oldFS, oldPathName, errno := atPath(fsc, mod.Memory(), olddirFD, oldPath, oldPathLen)
+	oldFS, oldPathName, errno := atPath(fsc, mod.Memory(), fd, oldPath, oldPathLen)
 	if errno != ErrnoSuccess {
 		return errno
 	}
 
-	newFS, newPathName, errno := atPath(fsc, mod.Memory(), newdirFD, newPath, newPathLen)
+	newFS, newPathName, errno := atPath(fsc, mod.Memory(), newFD, newPath, newPathLen)
 	if errno != ErrnoSuccess {
 		return errno
 	}
@@ -1846,13 +1885,13 @@ func pathSymlinkFn(_ context.Context, mod api.Module, params []uint64) Errno {
 
 	oldPath := uint32(params[0])
 	oldPathLen := uint32(params[1])
-	dirFD := uint32(params[2])
+	fd := uint32(params[2])
 	newPath := uint32(params[3])
 	newPathLen := uint32(params[4])
 
 	mem := mod.Memory()
 
-	dir, ok := fsc.LookupFile(dirFD)
+	dir, ok := fsc.LookupFile(fd)
 	if !ok {
 		return ErrnoBadf // closed
 	} else if _, ft, err := dir.CachedStat(); err != nil {
@@ -1879,7 +1918,7 @@ func pathSymlinkFn(_ context.Context, mod api.Module, params []uint64) Errno {
 		// Do not join old path since it's only resolved when dereference the link created here.
 		// And the dereference result depends on the opening directory's file descriptor at that point.
 		bufToStr(oldPathBuf, int(oldPathLen)),
-		pathutil.Join(dir.Name, bufToStr(newPathBuf, int(newPathLen))),
+		path.Join(dir.Name, bufToStr(newPathBuf, int(newPathLen))),
 	); err != nil {
 		return ToErrno(err)
 	}
@@ -1925,11 +1964,11 @@ var pathUnlinkFile = newHostFunc(
 func pathUnlinkFileFn(_ context.Context, mod api.Module, params []uint64) Errno {
 	fsc := mod.(*wasm.CallContext).Sys.FS()
 
-	dirFD := uint32(params[0])
+	fd := uint32(params[0])
 	path := uint32(params[1])
 	pathLen := uint32(params[2])
 
-	preopen, pathName, errno := atPath(fsc, mod.Memory(), dirFD, path, pathLen)
+	preopen, pathName, errno := atPath(fsc, mod.Memory(), fd, path, pathLen)
 	if errno != ErrnoSuccess {
 		return errno
 	}
diff --git a/internal/sysfs/adapter.go b/internal/sysfs/adapter.go
index 9c0dfa3a..379add94 100644
--- a/internal/sysfs/adapter.go
+++ b/internal/sysfs/adapter.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"io/fs"
 	"os"
-	pathutil "path"
+	"path"
 	"runtime"
 	"strings"
 
@@ -70,7 +70,7 @@ func cleanPath(name string) string {
 	if name[0] == '/' {
 		cleaned = name[1:]
 	}
-	cleaned = pathutil.Clean(cleaned) // e.g. "sub/." -> "sub"
+	cleaned = path.Clean(cleaned) // e.g. "sub/." -> "sub"
 	return cleaned
 }
 
diff --git a/internal/wasi_snapshot_preview1/fs.go b/internal/wasi_snapshot_preview1/fs.go
index ede6d38a..859c4549 100644
--- a/internal/wasi_snapshot_preview1/fs.go
+++ b/internal/wasi_snapshot_preview1/fs.go
@@ -136,12 +136,23 @@ var filetypeToString = [...]string{
 
 // https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fstflags
 const (
-	FileStatAdjustFlagsAtim uint16 = 1 << iota
-	FileStatAdjustFlagsAtimNow
-	FileStatAdjustFlagsMtim
-	FileStatAdjustFlagsMtimNow
+	FstflagsAtim uint16 = 1 << iota
+	FstflagsAtimNow
+	FstflagsMtim
+	FstflagsMtimNow
 )
 
+var fstflagNames = [...]string{
+	"ATIM",
+	"ATIM_NOW",
+	"MTIM",
+	"MTIM_NOW",
+}
+
+func FstflagsString(fdflags int) string {
+	return flagsString(fstflagNames[:], fdflags)
+}
+
 // https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-advice-enumu8
 const (
 	FdAdviceNormal byte = iota
diff --git a/internal/wasi_snapshot_preview1/logging/logging.go b/internal/wasi_snapshot_preview1/logging/logging.go
index 9e2de87c..f5425300 100644
--- a/internal/wasi_snapshot_preview1/logging/logging.go
+++ b/internal/wasi_snapshot_preview1/logging/logging.go
@@ -96,7 +96,8 @@ func Config(fnd api.FunctionDefinition) (pSampler logging.ParamSampler, pLoggers
 		var logger logging.ParamLogger
 
 		if isLookupFlags(fnd, name) {
-			logger = (&logLookupflags{name, idx}).Log
+			lf := &logLookupflags{name, idx}
+			logger = lf.Log
 			pLoggers = append(pLoggers, logger)
 			continue
 		}
@@ -139,6 +140,8 @@ func Config(fnd api.FunctionDefinition) (pSampler logging.ParamSampler, pLoggers
 		switch name {
 		case "fdflags":
 			logger = logFdflags(idx).Log
+		case "fst_flags":
+			logger = logFstflags(idx).Log
 		case "oflags":
 			logger = logOflags(idx).Log
 		case "fs_rights_base":
@@ -333,6 +336,13 @@ func (i logOflags) Log(_ context.Context, _ api.Module, w logging.Writer, params
 	w.WriteString(OflagsString(int(params[i]))) //nolint
 }
 
+type logFstflags int
+
+func (i logFstflags) Log(_ context.Context, _ api.Module, w logging.Writer, params []uint64) {
+	w.WriteString("fst_flags=")                   //nolint
+	w.WriteString(FstflagsString(int(params[i]))) //nolint
+}
+
 func resultParamName(name string) string {
 	return name[7:] // without "result."
 }
diff --git a/site/content/languages/rust.md b/site/content/languages/rust.md
index 7ff1f866..15c80e6f 100644
--- a/site/content/languages/rust.md
+++ b/site/content/languages/rust.md
@@ -22,7 +22,7 @@ brevity.
 
 When Rust compiles a `%.rs` file with a `wasm32-*` target, the output `%.wasm`
 depends on a subset of features in the [WebAssembly 1.0 Core specification]
-({{< ref "/specs#core" >}}). The `wasm32-wasi` target depends on [WASI]
+({{< ref "/specs#core" >}}). The [wasm32-wasi][15] target depends on [WASI]
 ({{< ref "/specs#wasi" >}}) host functions as well.
 
 Unlike some compilers, Rust also supports importing custom host functions and
@@ -227,3 +227,4 @@ source code may reduce binary size further.
 [12]: https://github.com/rustwasm/wee_alloc
 [13]: https://doc.rust-lang.org/cargo/reference/profiles.html#profile-settings
 [14]: https://github.com/bytecodealliance/cargo-wasi
+[15]: https://github.com/rust-lang/rust/tree/1.68.0/library/std/src/sys/wasi
diff --git a/site/content/specs.md b/site/content/specs.md
index d014027c..21644e81 100644
--- a/site/content/specs.md
+++ b/site/content/specs.md
@@ -76,8 +76,9 @@ complete the below chart. If you desire something not yet implemented, please
 your use case (ex which language you are using to compile, a.k.a. target Wasm).
 
 Notes:
- * C (via clang) supports the maximum WASI functions due to [wasi-libc][16]
  * AssemblyScript has its own ABI which can optionally use [wasi-shim][17]
+ * C (via clang) supports the maximum WASI functions due to [wasi-libc][16]
+ * Rust supports WASI via its [wasm32-wasi][18] target.
 
 <details><summary>Click to see the full list of supported WASI functions</summary>
 <p>
@@ -113,7 +114,7 @@ Notes:
 | fd_write                |   ✅    | Rust,TinyGo,Zig |
 | path_create_directory   |   ✅    | Rust,TinyGo,Zig |
 | path_filestat_get       |   ✅    | Rust,TinyGo,Zig |
-| path_filestat_set_times |   ❌    |                 |
+| path_filestat_set_times |   ✅    |       Rust,libc |
 | path_link               |   ✅    |        Rust,Zig |
 | path_open               |   ✅    | Rust,TinyGo,Zig |
 | path_readlink           |   ✅    |        Rust,Zig |
@@ -152,3 +153,4 @@ Note: 💀 means the function was later removed from WASI.
 [15]: https://github.com/WebAssembly/WASI/pull/458
 [16]: https://github.com/WebAssembly/wasi-libc
 [17]: https://github.com/AssemblyScript/wasi-shim
+[18]: https://github.com/rust-lang/rust/tree/1.68.0/library/std/src/sys/wasi


Test patch:
diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go
index c36a3fb6..230a7496 100644
--- a/imports/wasi_snapshot_preview1/fs_test.go
+++ b/imports/wasi_snapshot_preview1/fs_test.go
@@ -10,6 +10,7 @@ import (
 	"os"
 	"path"
 	"runtime"
+	"strings"
 	"testing"
 	"time"
 
@@ -45,7 +46,7 @@ func Test_fdAllocate(t *testing.T) {
 	const fileName = "file.txt"
 
 	// Create the target file.
-	realPath := path.Join(tmpDir, fileName)
+	realPath := joinPath(tmpDir, fileName)
 	require.NoError(t, os.WriteFile(realPath, []byte("0123456789"), 0o600))
 
 	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFSConfig(
@@ -146,7 +147,7 @@ func Test_fdClose(t *testing.T) {
 <== errno=ESUCCESS
 `, "\n"+log.String())
 
-	// Verify fdToClose is closed and removed from the opened FDs.
+	// Verify fdToClose is closed and removed from the file descriptor table.
 	_, ok := fsc.LookupFile(fdToClose)
 	require.False(t, ok)
 
@@ -156,7 +157,7 @@ func Test_fdClose(t *testing.T) {
 
 	log.Reset()
 	t.Run("ErrnoBadF for an invalid FD", func(t *testing.T) {
-		requireErrnoResult(t, ErrnoBadf, mod, FdCloseName, uint64(42)) // 42 is an arbitrary invalid FD
+		requireErrnoResult(t, ErrnoBadf, mod, FdCloseName, uint64(42)) // 42 is an arbitrary invalid Fd
 		require.Equal(t, `
 ==> wasi_snapshot_preview1.fd_close(fd=42)
 <== errno=EBADF
@@ -186,7 +187,7 @@ func Test_fdDatasync(t *testing.T) {
 		expectedLog   string
 	}{
 		{
-			name:          "invalid fd",
+			name:          "invalid FD",
 			fd:            42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
@@ -195,7 +196,7 @@ func Test_fdDatasync(t *testing.T) {
 `,
 		},
 		{
-			name:          "valid fd",
+			name:          "valid FD",
 			fd:            fd,
 			expectedErrno: ErrnoSuccess,
 			expectedLog: `
@@ -367,7 +368,7 @@ func Test_fdFdstatSetFlags(t *testing.T) {
 	const fileName = "file.txt"
 
 	// Create the target file.
-	realPath := path.Join(tmpDir, fileName)
+	realPath := joinPath(tmpDir, fileName)
 	require.NoError(t, os.WriteFile(realPath, []byte("0123456789"), 0o600))
 
 	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFSConfig(wazero.NewFSConfig().
@@ -409,7 +410,7 @@ func Test_fdFdstatSetFlags(t *testing.T) {
 	}
 
 	requireFileContent := func(exp string) {
-		buf, err := os.ReadFile(path.Join(tmpDir, fileName))
+		buf, err := os.ReadFile(joinPath(tmpDir, fileName))
 		require.NoError(t, err)
 		require.Equal(t, exp, string(buf))
 	}
@@ -701,7 +702,7 @@ func Test_fdFilestatSetSize(t *testing.T) {
 			}
 			requireErrnoResult(t, tc.expectedErrno, mod, FdFilestatSetSizeName, uint64(fd), uint64(tc.size))
 
-			actual, err := os.ReadFile(path.Join(tmpDir, filepath))
+			actual, err := os.ReadFile(joinPath(tmpDir, filepath))
 			require.NoError(t, err)
 			require.Equal(t, tc.expectedContent, actual)
 
@@ -724,7 +725,7 @@ func Test_fdFilestatSetTimes(t *testing.T) {
 			name:          "badf",
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=5,atim=0,mtim=0,fst_flags=0)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=-1,atim=0,mtim=0,fst_flags=)
 <== errno=EBADF
 `,
 		},
@@ -734,7 +735,7 @@ func Test_fdFilestatSetTimes(t *testing.T) {
 			atime:         123451, // Must be ignored.
 			expectedErrno: ErrnoSuccess,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=123451,mtim=1234,fst_flags=0)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=123451,mtim=1234,fst_flags=)
 <== errno=ESUCCESS
 `,
 		},
@@ -743,9 +744,9 @@ func Test_fdFilestatSetTimes(t *testing.T) {
 			expectedErrno: ErrnoSuccess,
 			mtime:         1234,   // Must be ignored.
 			atime:         123451, // Must be ignored.
-			flags:         FileStatAdjustFlagsAtimNow,
+			flags:         FstflagsAtimNow,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=123451,mtim=1234,fst_flags=2)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=123451,mtim=1234,fst_flags=ATIM_NOW)
 <== errno=ESUCCESS
 `,
 		},
@@ -754,9 +755,9 @@ func Test_fdFilestatSetTimes(t *testing.T) {
 			expectedErrno: ErrnoSuccess,
 			mtime:         1234,   // Must be ignored.
 			atime:         123451, // Must be ignored.
-			flags:         FileStatAdjustFlagsMtimNow,
+			flags:         FstflagsMtimNow,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=123451,mtim=1234,fst_flags=8)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=123451,mtim=1234,fst_flags=MTIM_NOW)
 <== errno=ESUCCESS
 `,
 		},
@@ -765,20 +766,20 @@ func Test_fdFilestatSetTimes(t *testing.T) {
 			expectedErrno: ErrnoSuccess,
 			mtime:         1234,   // Must be ignored.
 			atime:         123451, // Must be ignored.
-			flags:         FileStatAdjustFlagsAtimNow | FileStatAdjustFlagsMtimNow,
+			flags:         FstflagsAtimNow | FstflagsMtimNow,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=123451,mtim=1234,fst_flags=10)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=123451,mtim=1234,fst_flags=ATIM_NOW|MTIM_NOW)
 <== errno=ESUCCESS
 `,
 		},
 		{
-			name:          "a=set,m=omit",
+			name:          "a=now,m=set",
 			expectedErrno: ErrnoSuccess,
-			mtime:         1234, // Must be ignored.
-			atime:         55555500,
-			flags:         FileStatAdjustFlagsAtim,
+			mtime:         55555500,
+			atime:         1234, // Must be ignored.
+			flags:         FstflagsAtimNow | FstflagsMtim,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=55555500,mtim=1234,fst_flags=1)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=1234,mtim=55555500,fst_flags=ATIM_NOW|MTIM)
 <== errno=ESUCCESS
 `,
 		},
@@ -787,42 +788,44 @@ func Test_fdFilestatSetTimes(t *testing.T) {
 			expectedErrno: ErrnoSuccess,
 			mtime:         1234, // Must be ignored.
 			atime:         55555500,
-			flags:         FileStatAdjustFlagsAtim | FileStatAdjustFlagsMtimNow,
+			flags:         FstflagsAtim | FstflagsMtimNow,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=55555500,mtim=1234,fst_flags=9)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=55555500,mtim=1234,fst_flags=ATIM|MTIM_NOW)
 <== errno=ESUCCESS
 `,
 		},
 		{
-			name:          "a=omit,m=set",
+			name:          "a=set,m=omit",
 			expectedErrno: ErrnoSuccess,
-			mtime:         55555500,
-			atime:         1234, // Must be ignored.
-			flags:         FileStatAdjustFlagsMtim,
+			mtime:         1234, // Must be ignored.
+			atime:         55555500,
+			flags:         FstflagsAtim,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=1234,mtim=55555500,fst_flags=4)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=55555500,mtim=1234,fst_flags=ATIM)
 <== errno=ESUCCESS
 `,
 		},
+
 		{
-			name:          "a=now,m=set",
+			name:          "a=omit,m=set",
 			expectedErrno: ErrnoSuccess,
 			mtime:         55555500,
 			atime:         1234, // Must be ignored.
-			flags:         FileStatAdjustFlagsAtimNow | FileStatAdjustFlagsMtim,
+			flags:         FstflagsMtim,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=1234,mtim=55555500,fst_flags=6)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=1234,mtim=55555500,fst_flags=MTIM)
 <== errno=ESUCCESS
 `,
 		},
+
 		{
 			name:          "a=set,m=set",
 			expectedErrno: ErrnoSuccess,
 			mtime:         55555500,
 			atime:         6666666600,
-			flags:         FileStatAdjustFlagsAtim | FileStatAdjustFlagsMtim,
+			flags:         FstflagsAtim | FstflagsMtim,
 			expectedLog: `
-==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=6666666600,mtim=55555500,fst_flags=5)
+==> wasi_snapshot_preview1.fd_filestat_set_times(fd=4,atim=6666666600,mtim=55555500,fst_flags=ATIM|MTIM)
 <== errno=ESUCCESS
 `,
 		},
@@ -840,7 +843,7 @@ func Test_fdFilestatSetTimes(t *testing.T) {
 
 			paramFd := fd
 			if filepath == "badf" {
-				paramFd = fd + 1
+				paramFd = math.MaxUint32
 			}
 
 			f, ok := fsc.LookupFile(fd)
@@ -861,16 +864,16 @@ func Test_fdFilestatSetTimes(t *testing.T) {
 
 				var st platform.Stat_t
 				require.NoError(t, f.Stat(&st))
-				if tc.flags&FileStatAdjustFlagsAtim != 0 {
+				if tc.flags&FstflagsAtim != 0 {
 					require.Equal(t, tc.atime, st.Atim)
-				} else if tc.flags&FileStatAdjustFlagsAtimNow != 0 {
+				} else if tc.flags&FstflagsAtimNow != 0 {
 					require.True(t, (sys.WalltimeNanos()-st.Atim) < time.Second.Nanoseconds())
 				} else {
 					require.Equal(t, prevAtime, st.Atim)
 				}
-				if tc.flags&FileStatAdjustFlagsMtim != 0 {
+				if tc.flags&FstflagsMtim != 0 {
 					require.Equal(t, tc.mtime, st.Mtim)
-				} else if tc.flags&FileStatAdjustFlagsMtimNow != 0 {
+				} else if tc.flags&FstflagsMtimNow != 0 {
 					require.True(t, (sys.WalltimeNanos()-st.Mtim) < time.Second.Nanoseconds())
 				} else {
 					require.Equal(t, prevMtime, st.Mtim)
@@ -1037,7 +1040,7 @@ func Test_fdPread_Errors(t *testing.T) {
 		expectedLog                      string
 	}{
 		{
-			name:          "invalid fd",
+			name:          "invalid FD",
 			fd:            42,                         // arbitrary invalid fd
 			memory:        []byte{'?', '?', '?', '?'}, // pass result.nread validation
 			expectedErrno: ErrnoBadf,
@@ -1160,7 +1163,6 @@ func Test_fdPrestatGet(t *testing.T) {
 	fsConfig := wazero.NewFSConfig().WithDirMount(t.TempDir(), "/")
 	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFSConfig(fsConfig))
 	defer r.Close(testCtx)
-	dirFD := sys.FdPreopen
 
 	resultPrestat := uint32(1) // arbitrary offset
 	expectedMemory := []byte{
@@ -1174,7 +1176,7 @@ func Test_fdPrestatGet(t *testing.T) {
 
 	maskMemory(t, mod, len(expectedMemory))
 
-	requireErrnoResult(t, ErrnoSuccess, mod, FdPrestatGetName, uint64(dirFD), uint64(resultPrestat))
+	requireErrnoResult(t, ErrnoSuccess, mod, FdPrestatGetName, uint64(sys.FdPreopen), uint64(resultPrestat))
 	require.Equal(t, `
 ==> wasi_snapshot_preview1.fd_prestat_get(fd=3)
 <== (prestat={pr_name_len=1},errno=ESUCCESS)
@@ -1199,7 +1201,7 @@ func Test_fdPrestatGet_Errors(t *testing.T) {
 	}{
 		{
 			name:          "unopened FD",
-			fd:            42, // arbitrary invalid FD
+			fd:            42, // arbitrary invalid Fd
 			resultPrestat: 0,  // valid offset
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
@@ -1245,7 +1247,6 @@ func Test_fdPrestatDirName(t *testing.T) {
 	fsConfig := wazero.NewFSConfig().WithDirMount(t.TempDir(), "/")
 	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFSConfig(fsConfig))
 	defer r.Close(testCtx)
-	dirFD := sys.FdPreopen
 
 	path := uint32(1)    // arbitrary offset
 	pathLen := uint32(0) // shorter than len("/") to prove truncation is ok
@@ -1255,7 +1256,7 @@ func Test_fdPrestatDirName(t *testing.T) {
 
 	maskMemory(t, mod, len(expectedMemory))
 
-	requireErrnoResult(t, ErrnoSuccess, mod, FdPrestatDirNameName, uint64(dirFD), uint64(path), uint64(pathLen))
+	requireErrnoResult(t, ErrnoSuccess, mod, FdPrestatDirNameName, uint64(sys.FdPreopen), uint64(path), uint64(pathLen))
 	require.Equal(t, `
 ==> wasi_snapshot_preview1.fd_prestat_dir_name(fd=3)
 <== (path=,errno=ESUCCESS)
@@ -1432,7 +1433,7 @@ func Test_fdPwrite(t *testing.T) {
 			require.Equal(t, tc.expectedMemory, actual)
 
 			// Ensure the contents were really written
-			b, err := os.ReadFile(path.Join(tmpDir, pathName))
+			b, err := os.ReadFile(joinPath(tmpDir, pathName))
 			require.NoError(t, err)
 			require.Equal(t, tc.expectedContents, string(b))
 		})
@@ -1510,7 +1511,7 @@ func Test_fdPwrite_offset(t *testing.T) {
 	require.Equal(t, expectedLog, "\n"+log.String())
 
 	// Ensure the contents were really written
-	b, err := os.ReadFile(path.Join(tmpDir, pathName))
+	b, err := os.ReadFile(joinPath(tmpDir, pathName))
 	require.NoError(t, err)
 	require.Equal(t, "wazero", string(b))
 }
@@ -1530,7 +1531,7 @@ func Test_fdPwrite_Errors(t *testing.T) {
 		expectedLog                         string
 	}{
 		{
-			name:          "invalid fd",
+			name:          "invalid FD",
 			fd:            42,                         // arbitrary invalid fd
 			memory:        []byte{'?', '?', '?', '?'}, // pass result.nwritten validation
 			expectedErrno: ErrnoBadf,
@@ -1702,7 +1703,7 @@ func Test_fdRead_Errors(t *testing.T) {
 		expectedLog                      string
 	}{
 		{
-			name:          "invalid fd",
+			name:          "invalid FD",
 			fd:            42,                         // arbitrary invalid fd
 			memory:        []byte{'?', '?', '?', '?'}, // pass result.nread validation
 			expectedErrno: ErrnoBadf,
@@ -2175,12 +2176,12 @@ func Test_fdReaddir_Rewind(t *testing.T) {
 	require.NoError(t, err)
 
 	mem := mod.Memory()
-	const resultBufUsed, buf, bufSize = 0, 8, 200
+	const resultBufused, buf, bufSize = 0, 8, 200
 	read := func(cookie, bufSize uint64) (bufUsed uint32) {
 		requireErrnoResult(t, ErrnoSuccess, mod, FdReaddirName,
-			uint64(fd), buf, bufSize, cookie, uint64(resultBufUsed))
+			uint64(fd), buf, bufSize, cookie, uint64(resultBufused))
 
-		bufUsed, ok := mem.ReadUint32Le(resultBufUsed)
+		bufUsed, ok := mem.ReadUint32Le(resultBufused)
 		require.True(t, ok)
 		return bufUsed
 	}
@@ -2262,7 +2263,7 @@ func Test_fdReaddir_Errors(t *testing.T) {
 `,
 		},
 		{
-			name: "invalid fd",
+			name: "invalid FD",
 			fd:   42,                    // arbitrary invalid fd
 			buf:  0, bufLen: DirentSize, // enough to read the dirent
 			resultBufused: 1000, // arbitrary
@@ -2355,7 +2356,7 @@ func Test_fdReaddir_Errors(t *testing.T) {
 }
 
 func Test_fdRenumber(t *testing.T) {
-	const preopenFd, fileFd, dirFd = 3, 4, 5
+	const fileFD, dirFD = 4, 5
 
 	tests := []struct {
 		name          string
@@ -2365,8 +2366,8 @@ func Test_fdRenumber(t *testing.T) {
 	}{
 		{
 			name:          "from=preopen",
-			from:          preopenFd,
-			to:            dirFd,
+			from:          sys.FdPreopen,
+			to:            dirFD,
 			expectedErrno: ErrnoNotsup,
 			expectedLog: `
 ==> wasi_snapshot_preview1.fd_renumber(fd=3,to=5)
@@ -2375,8 +2376,8 @@ func Test_fdRenumber(t *testing.T) {
 		},
 		{
 			name:          "to=preopen",
-			from:          dirFd,
-			to:            3,
+			from:          dirFD,
+			to:            sys.FdPreopen,
 			expectedErrno: ErrnoNotsup,
 			expectedLog: `
 ==> wasi_snapshot_preview1.fd_renumber(fd=5,to=3)
@@ -2385,8 +2386,8 @@ func Test_fdRenumber(t *testing.T) {
 		},
 		{
 			name:          "file to dir",
-			from:          fileFd,
-			to:            dirFd,
+			from:          fileFD,
+			to:            dirFD,
 			expectedErrno: ErrnoSuccess,
 			expectedLog: `
 ==> wasi_snapshot_preview1.fd_renumber(fd=4,to=5)
@@ -2395,8 +2396,8 @@ func Test_fdRenumber(t *testing.T) {
 		},
 		{
 			name:          "dir to file",
-			from:          dirFd,
-			to:            fileFd,
+			from:          dirFD,
+			to:            fileFD,
 			expectedErrno: ErrnoSuccess,
 			expectedLog: `
 ==> wasi_snapshot_preview1.fd_renumber(fd=5,to=4)
@@ -2405,7 +2406,7 @@ func Test_fdRenumber(t *testing.T) {
 		},
 		{
 			name:          "dir to any",
-			from:          dirFd,
+			from:          dirFD,
 			to:            12345,
 			expectedErrno: ErrnoSuccess,
 			expectedLog: `
@@ -2415,7 +2416,7 @@ func Test_fdRenumber(t *testing.T) {
 		},
 		{
 			name:          "file to any",
-			from:          fileFd,
+			from:          fileFD,
 			to:            54,
 			expectedErrno: ErrnoSuccess,
 			expectedLog: `
@@ -2435,13 +2436,13 @@ func Test_fdRenumber(t *testing.T) {
 			preopen := fsc.RootFS()
 
 			// Sanity check of the file descriptor assignment.
-			fileFdAssigned, err := fsc.OpenFile(preopen, "animals.txt", os.O_RDONLY, 0)
+			fileFDAssigned, err := fsc.OpenFile(preopen, "animals.txt", os.O_RDONLY, 0)
 			require.NoError(t, err)
-			require.Equal(t, uint32(fileFd), fileFdAssigned)
+			require.Equal(t, uint32(fileFD), fileFDAssigned)
 
-			dirFdAssigned, err := fsc.OpenFile(preopen, "dir", os.O_RDONLY, 0)
+			dirFDAssigned, err := fsc.OpenFile(preopen, "dir", os.O_RDONLY, 0)
 			require.NoError(t, err)
-			require.Equal(t, uint32(dirFd), dirFdAssigned)
+			require.Equal(t, uint32(dirFD), dirFDAssigned)
 
 			requireErrnoResult(t, tc.expectedErrno, mod, FdRenumberName, uint64(tc.from), uint64(tc.to))
 			require.Equal(t, tc.expectedLog, "\n"+log.String())
@@ -2543,7 +2544,7 @@ func Test_fdSeek(t *testing.T) {
 }
 
 func Test_fdSeek_Errors(t *testing.T) {
-	mod, fd, log, r := requireOpenFile(t, t.TempDir(), "test_path", []byte("wazero"), false)
+	mod, fileFD, log, r := requireOpenFile(t, t.TempDir(), "test_path", []byte("wazero"), false)
 	defer r.Close(testCtx)
 
 	fsc := mod.(*wasm.CallContext).Sys.FS()
@@ -2561,7 +2562,7 @@ func Test_fdSeek_Errors(t *testing.T) {
 		expectedLog             string
 	}{
 		{
-			name:          "invalid fd",
+			name:          "invalid FD",
 			fd:            42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
@@ -2571,7 +2572,7 @@ func Test_fdSeek_Errors(t *testing.T) {
 		},
 		{
 			name:          "invalid whence",
-			fd:            fd,
+			fd:            fileFD,
 			whence:        3, // invalid whence, the largest whence io.SeekEnd(2) + 1
 			expectedErrno: ErrnoInval,
 			expectedLog: `
@@ -2590,7 +2591,7 @@ func Test_fdSeek_Errors(t *testing.T) {
 		},
 		{
 			name:            "out-of-memory writing resultNewoffset",
-			fd:              fd,
+			fd:              fileFD,
 			resultNewoffset: memorySize,
 			expectedErrno:   ErrnoFault,
 			expectedLog: `
@@ -2625,7 +2626,7 @@ func Test_fdSync(t *testing.T) {
 		expectedLog   string
 	}{
 		{
-			name:          "invalid fd",
+			name:          "invalid FD",
 			fd:            42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
@@ -2634,7 +2635,7 @@ func Test_fdSync(t *testing.T) {
 `,
 		},
 		{
-			name:          "valid fd",
+			name:          "valid FD",
 			fd:            fd,
 			expectedErrno: ErrnoSuccess,
 			expectedLog: `
@@ -2712,7 +2713,7 @@ func Test_fdTell_Errors(t *testing.T) {
 		expectedLog     string
 	}{
 		{
-			name:          "invalid fd",
+			name:          "invalid FD",
 			fd:            42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
@@ -2785,7 +2786,7 @@ func Test_fdWrite(t *testing.T) {
 	require.Equal(t, expectedMemory, actual)
 
 	// Since we initialized this file, we know we can read it by path
-	buf, err := os.ReadFile(path.Join(tmpDir, pathName))
+	buf, err := os.ReadFile(joinPath(tmpDir, pathName))
 	require.NoError(t, err)
 
 	require.Equal(t, []byte("wazero"), buf) // verify the file was actually written
@@ -2851,7 +2852,7 @@ func Test_fdWrite_Errors(t *testing.T) {
 		expectedLog              string
 	}{
 		{
-			name:          "invalid fd",
+			name:          "invalid FD",
 			fd:            42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
@@ -2938,15 +2939,15 @@ func Test_pathCreateDirectory(t *testing.T) {
 
 	// set up the initial memory to include the path name starting at an offset.
 	pathName := "wazero"
-	realPath := path.Join(tmpDir, pathName)
+	realPath := joinPath(tmpDir, pathName)
 	ok := mod.Memory().Write(0, append([]byte{'?'}, pathName...))
 	require.True(t, ok)
 
-	preopenedFD := sys.FdPreopen
+	fd := sys.FdPreopen
 	name := 1
 	nameLen := len(pathName)
 
-	requireErrnoResult(t, ErrnoSuccess, mod, PathCreateDirectoryName, uint64(preopenedFD), uint64(name), uint64(nameLen))
+	requireErrnoResult(t, ErrnoSuccess, mod, PathCreateDirectoryName, uint64(fd), uint64(name), uint64(nameLen))
 	require.Equal(t, `
 ==> wasi_snapshot_preview1.path_create_directory(fd=3,path=wazero)
 <== errno=ESUCCESS
@@ -2966,12 +2967,12 @@ func Test_pathCreateDirectory_Errors(t *testing.T) {
 	defer r.Close(testCtx)
 
 	file := "file"
-	err := os.WriteFile(path.Join(tmpDir, file), []byte{}, 0o700)
+	err := os.WriteFile(joinPath(tmpDir, file), []byte{}, 0o700)
 	require.NoError(t, err)
 	fileFD := requireOpenFD(t, mod, file)
 
 	dir := "dir"
-	err = os.Mkdir(path.Join(tmpDir, dir), 0o700)
+	err = os.Mkdir(joinPath(tmpDir, dir), 0o700)
 	require.NoError(t, err)
 
 	tests := []struct {
@@ -2990,7 +2991,7 @@ func Test_pathCreateDirectory_Errors(t *testing.T) {
 `,
 		},
 		{
-			name:          "FD not a directory",
+			name:          "Fd not a directory",
 			fd:            fileFD,
 			pathName:      file,
 			path:          0,
@@ -3159,7 +3160,7 @@ func Test_pathFilestatGet(t *testing.T) {
 `,
 		},
 		{
-			name:           "FD not a directory",
+			name:           "Fd not a directory",
 			fd:             fileFD,
 			memory:         initialMemoryFile,
 			pathLen:        uint32(len(file)),
@@ -3227,54 +3228,256 @@ func Test_pathFilestatGet(t *testing.T) {
 	}
 }
 
-// Test_pathFilestatSetTimes only tests it is stubbed for GrainLang per #271
 func Test_pathFilestatSetTimes(t *testing.T) {
-	log := requireErrnoNosys(t, PathFilestatSetTimesName, 0, 0, 0, 0, 0, 0, 0)
-	require.Equal(t, `
---> wasi_snapshot_preview1.path_filestat_set_times(fd=0,flags=,path=,atim=0,mtim=0,fst_flags=0)
-<-- errno=ENOSYS
-`, log)
+	tmpDir := t.TempDir() // open before loop to ensure no locking problems.
+
+	file := "file"
+	writeFile(t, tmpDir, file, []byte("012"))
+	link := file + "-link"
+	require.NoError(t, os.Symlink(joinPath(tmpDir, file), joinPath(tmpDir, link)))
+
+	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().
+		WithSysWalltime().
+		WithFSConfig(wazero.NewFSConfig().WithDirMount(tmpDir, "")))
+	defer r.Close(testCtx)
+
+	tests := []struct {
+		name          string
+		flags         uint16
+		pathName      string
+		mtime, atime  int64
+		fstFlags      uint16
+		expectedLog   string
+		expectedErrno Errno
+	}{
+		{
+			name:  "a=omit,m=omit",
+			flags: LOOKUP_SYMLINK_FOLLOW,
+			atime: 123451, // Must be ignored.
+			mtime: 1234,   // Must be ignored.
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=123451,mtim=1234,fst_flags=)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "a=now,m=omit",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			atime:    123451, // Must be ignored.
+			mtime:    1234,   // Must be ignored.
+			fstFlags: FstflagsAtimNow,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=123451,mtim=1234,fst_flags=ATIM_NOW)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "a=omit,m=now",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			atime:    123451, // Must be ignored.
+			mtime:    1234,   // Must be ignored.
+			fstFlags: FstflagsMtimNow,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=123451,mtim=1234,fst_flags=MTIM_NOW)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "a=now,m=now",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			atime:    123451, // Must be ignored.
+			mtime:    1234,   // Must be ignored.
+			fstFlags: FstflagsAtimNow | FstflagsMtimNow,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=123451,mtim=1234,fst_flags=ATIM_NOW|MTIM_NOW)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "a=now,m=set",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			atime:    1234, // Must be ignored.
+			mtime:    55555500,
+			fstFlags: FstflagsAtimNow | FstflagsMtim,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=1234,mtim=55555500,fst_flags=ATIM_NOW|MTIM)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "a=set,m=now",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			atime:    55555500,
+			mtime:    1234, // Must be ignored.
+			fstFlags: FstflagsAtim | FstflagsMtimNow,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=55555500,mtim=1234,fst_flags=ATIM|MTIM_NOW)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "a=set,m=omit",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			atime:    55555500,
+			mtime:    1234, // Must be ignored.
+			fstFlags: FstflagsAtim,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=55555500,mtim=1234,fst_flags=ATIM)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "a=omit,m=set",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			atime:    1234, // Must be ignored.
+			mtime:    55555500,
+			fstFlags: FstflagsMtim,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=1234,mtim=55555500,fst_flags=MTIM)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "a=set,m=set",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			atime:    6666666600,
+			mtime:    55555500,
+			fstFlags: FstflagsAtim | FstflagsMtim,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=file,atim=6666666600,mtim=55555500,fst_flags=ATIM|MTIM)
+<== errno=ESUCCESS
+`,
+		},
+		{
+			name:     "not found",
+			pathName: "nope",
+			flags:    LOOKUP_SYMLINK_FOLLOW,
+			fstFlags: FstflagsAtimNow, // Choose one flag to ensure an update occurs
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=SYMLINK_FOLLOW,path=nope,atim=0,mtim=0,fst_flags=ATIM_NOW)
+<== errno=ENOENT
+`,
+			expectedErrno: ErrnoNoent,
+		},
+		{
+			name:     "no_symlink_follow",
+			pathName: link,
+			flags:    0,
+			atime:    123451, // Must be ignored.
+			mtime:    1234,   // Must be ignored.
+			fstFlags: FstflagsMtimNow,
+			expectedLog: `
+==> wasi_snapshot_preview1.path_filestat_set_times(fd=3,flags=,path=file-link,atim=123451,mtim=1234,fst_flags=MTIM_NOW)
+<== errno=ESUCCESS
+`,
+		},
+	}
+
+	for _, tt := range tests {
+		tc := tt
+
+		t.Run(tc.name, func(t *testing.T) {
+			defer log.Reset()
+
+			if tc.flags == 0 && !platform.SupportsSymlinkNoFollow {
+				tc.expectedErrno = ErrnoNosys
+				tc.expectedLog = strings.ReplaceAll(tc.expectedLog, "ESUCCESS", "ENOSYS")
+			}
+
+			pathName := tc.pathName
+			if pathName == "" {
+				pathName = file
+			}
+			mod.Memory().Write(0, []byte(pathName))
+
+			fd := sys.FdPreopen
+			path := 0
+			pathLen := uint32(len(pathName))
+
+			sys := mod.(*wasm.CallContext).Sys
+			fsc := sys.FS()
+
+			var oldSt platform.Stat_t
+			if tc.expectedErrno == ErrnoSuccess {
+				require.NoError(t, fsc.RootFS().Stat(pathName, &oldSt))
+			}
+
+			requireErrnoResult(t, tc.expectedErrno, mod, PathFilestatSetTimesName, uint64(fd), uint64(tc.flags),
+				uint64(path), uint64(pathLen), uint64(tc.atime), uint64(tc.mtime), uint64(tc.fstFlags))
+			require.Equal(t, tc.expectedLog, "\n"+log.String())
+
+			if tc.expectedErrno != ErrnoSuccess {
+				return
+			}
+
+			var newSt platform.Stat_t
+			require.NoError(t, fsc.RootFS().Stat(pathName, &newSt))
+
+			if platform.CompilerSupported() {
+				if tc.fstFlags&FstflagsAtim != 0 {
+					require.Equal(t, tc.atime, newSt.Atim)
+				} else if tc.fstFlags&FstflagsAtimNow != 0 {
+					now := time.Now().UnixNano()
+					require.True(t, newSt.Atim <= now, "expected atim %d <= now %d", newSt.Atim, now)
+				} else { // omit
+					require.Equal(t, oldSt.Atim, newSt.Atim)
+				}
+			}
+
+			// When compiler isn't supported, we can still check mtim.
+			if tc.fstFlags&FstflagsMtim != 0 {
+				require.Equal(t, tc.mtime, newSt.Mtim)
+			} else if tc.fstFlags&FstflagsMtimNow != 0 {
+				now := time.Now().UnixNano()
+				require.True(t, newSt.Mtim <= now, "expected mtim %d <= now %d", newSt.Mtim, now)
+			} else { // omit
+				require.Equal(t, oldSt.Mtim, newSt.Mtim)
+			}
+		})
+	}
 }
 
 func Test_pathLink(t *testing.T) {
 	tmpDir := t.TempDir() // open before loop to ensure no locking problems.
 
-	const oldDirName = "my-old-dir"
+	oldDirName := "my-old-dir"
+	oldDirPath := joinPath(tmpDir, oldDirName)
 	mod, oldFd, log, r := requireOpenFile(t, tmpDir, oldDirName, nil, false)
 	defer r.Close(testCtx)
 
-	const newDirName = "my-new-dir/sub"
-	require.NoError(t, os.MkdirAll(path.Join(tmpDir, newDirName), 0o700))
+	newDirName := "my-new-dir/sub"
+	newDirPath := joinPath(tmpDir, newDirName)
+	require.NoError(t, os.MkdirAll(joinPath(tmpDir, newDirName), 0o700))
 	fsc := mod.(*wasm.CallContext).Sys.FS()
 	newFd, err := fsc.OpenFile(fsc.RootFS(), newDirName, 0o600, 0)
 	require.NoError(t, err)
 
 	mem := mod.Memory()
 
-	const filename = "file"
-	err = os.WriteFile(path.Join(tmpDir, oldDirName, filename), []byte{1, 2, 3, 4}, 0o700)
+	fileName := "file"
+	err = os.WriteFile(joinPath(oldDirPath, fileName), []byte{1, 2, 3, 4}, 0o700)
 	require.NoError(t, err)
 
-	const fileNamePtr = 0xff
-	ok := mem.Write(fileNamePtr, []byte(filename))
+	file := uint32(0xff)
+	ok := mem.Write(file, []byte(fileName))
 	require.True(t, ok)
 
-	const nonExistingFileNamePtr = 0xaa
-	const nonExistingFileName = "invalid-san"
-	ok = mem.Write(nonExistingFileNamePtr, []byte(nonExistingFileName))
+	notFoundFile := uint32(0xaa)
+	notFoundFileName := "nope"
+	ok = mem.Write(notFoundFile, []byte(notFoundFileName))
 	require.True(t, ok)
 
-	const destinationNamePtr = 0xcc
-	const destinationName = "hard-linked"
-	ok = mem.Write(destinationNamePtr, []byte(destinationName))
+	destination := uint32(0xcc)
+	destinationName := "hard-linked"
+	ok = mem.Write(destination, []byte(destinationName))
 	require.True(t, ok)
 
-	destinationRealPath := path.Join(tmpDir, newDirName, destinationName)
+	destinationRealPath := joinPath(newDirPath, destinationName)
 
 	t.Run("success", func(t *testing.T) {
 		requireErrnoResult(t, ErrnoSuccess, mod, PathLinkName,
-			uint64(oldFd), 0, fileNamePtr, uint64(len(filename)),
-			uint64(newFd), destinationNamePtr, uint64(len(destinationName)))
+			uint64(oldFd), 0, uint64(file), uint64(len(fileName)),
+			uint64(newFd), uint64(destination), uint64(len(destinationName)))
 		require.Contains(t, log.String(), ErrnoName(ErrnoSuccess))
 
 		f, err := os.Open(destinationRealPath)
@@ -3292,30 +3495,31 @@ func Test_pathLink(t *testing.T) {
 
 	t.Run("errors", func(t *testing.T) {
 		for _, tc := range []struct {
-			errno                                              Errno
-			oldDirFd, newDirFd, oldPtr, newPtr, oldLen, newLen uint64
+			errno                                      Errno
+			oldFd /* oldFlags, */, oldPath, oldPathLen uint32
+			newFd, newPath, newPathLen                 uint32
 		}{
-			{errno: ErrnoBadf, oldDirFd: 1000},
-			{errno: ErrnoBadf, oldDirFd: uint64(oldFd), newDirFd: 1000},
-			{errno: ErrnoNotdir, oldDirFd: uint64(oldFd), newDirFd: 1},
-			{errno: ErrnoNotdir, oldDirFd: 1, newDirFd: 1},
-			{errno: ErrnoNotdir, oldDirFd: 1, newDirFd: uint64(newFd)},
-			{errno: ErrnoFault, oldDirFd: uint64(oldFd), newDirFd: uint64(newFd), oldLen: math.MaxUint32},
-			{errno: ErrnoFault, oldDirFd: uint64(oldFd), newDirFd: uint64(newFd), newLen: math.MaxUint32},
+			{errno: ErrnoBadf, oldFd: 1000},
+			{errno: ErrnoBadf, oldFd: oldFd, newFd: 1000},
+			{errno: ErrnoNotdir, oldFd: oldFd, newFd: 1},
+			{errno: ErrnoNotdir, oldFd: 1, newFd: 1},
+			{errno: ErrnoNotdir, oldFd: 1, newFd: newFd},
+			{errno: ErrnoFault, oldFd: oldFd, newFd: newFd, oldPathLen: math.MaxUint32},
+			{errno: ErrnoFault, oldFd: oldFd, newFd: newFd, newPathLen: math.MaxUint32},
 			{
-				errno: ErrnoFault, oldDirFd: uint64(oldFd), newDirFd: uint64(newFd),
-				oldPtr: math.MaxUint32, oldLen: 100, newLen: 100,
+				errno: ErrnoFault, oldFd: oldFd, newFd: newFd,
+				oldPath: math.MaxUint32, oldPathLen: 100, newPathLen: 100,
 			},
 			{
-				errno: ErrnoFault, oldDirFd: uint64(oldFd), newDirFd: uint64(newFd),
-				oldPtr: 1, oldLen: 100, newPtr: math.MaxUint32, newLen: 100,
+				errno: ErrnoFault, oldFd: oldFd, newFd: newFd,
+				oldPath: 1, oldPathLen: 100, newPath: math.MaxUint32, newPathLen: 100,
 			},
 		} {
 			name := ErrnoName(tc.errno)
 			t.Run(name, func(t *testing.T) {
 				requireErrnoResult(t, tc.errno, mod, PathLinkName,
-					tc.oldDirFd, 0, tc.oldPtr, tc.oldLen,
-					tc.newDirFd, tc.newPtr, tc.newLen)
+					uint64(tc.oldFd), 0, uint64(tc.oldPath), uint64(tc.oldPathLen),
+					uint64(tc.newFd), uint64(tc.newPath), uint64(tc.newPathLen))
 				require.Contains(t, log.String(), name)
 			})
 		}
@@ -3342,7 +3546,7 @@ func Test_pathOpen(t *testing.T) {
 	dirName := "dir"
 	mkdir(t, dir, dirName)
 
-	dirFileName := path.Join(dirName, fileName)
+	dirFileName := joinPath(dirName, fileName)
 	dirFileContents := []byte("def")
 	writeFile(t, dir, dirFileName, dirFileContents)
 
@@ -3450,7 +3654,7 @@ func Test_pathOpen(t *testing.T) {
 			fs:            readFS,
 			oflags:        O_CREAT | O_TRUNC,
 			expectedErrno: ErrnoNosys,
-			path:          func(t *testing.T) (file string) { return path.Join(dirName, "O_CREAT-O_TRUNC") },
+			path:          func(t *testing.T) (file string) { return joinPath(dirName, "O_CREAT-O_TRUNC") },
 			expectedLog: `
 ==> wasi_snapshot_preview1.path_open(fd=3,dirflags=,path=dir/O_CREAT-O_TRUNC,oflags=CREAT|TRUNC,fs_rights_base=,fs_rights_inheriting=,fdflags=)
 <== (opened_fd=,errno=ENOSYS)
@@ -3459,7 +3663,7 @@ func Test_pathOpen(t *testing.T) {
 		{
 			name:   "sysfs.DirFS O_CREAT O_TRUNC",
 			fs:     writeFS,
-			path:   func(t *testing.T) (file string) { return path.Join(dirName, "O_CREAT-O_TRUNC") },
+			path:   func(t *testing.T) (file string) { return joinPath(dirName, "O_CREAT-O_TRUNC") },
 			oflags: O_CREAT | O_TRUNC,
 			expected: func(t *testing.T, fsc *sys.FSContext) {
 				// expect to create a new file
@@ -3469,7 +3673,7 @@ func Test_pathOpen(t *testing.T) {
 				require.NoError(t, fsc.CloseFile(expectedOpenedFd))
 
 				// verify the contents were written
-				b := readFile(t, dir, path.Join(dirName, "O_CREAT-O_TRUNC"))
+				b := readFile(t, dir, joinPath(dirName, "O_CREAT-O_TRUNC"))
 				require.Equal(t, contents, b)
 			},
 			expectedLog: `
@@ -3557,7 +3761,7 @@ func Test_pathOpen(t *testing.T) {
 			path := uint32(0)
 			pathLen := uint32(len(pathName))
 			resultOpenedFd := pathLen
-			dirfd := sys.FdPreopen
+			fd := sys.FdPreopen
 
 			// TODO: dirflags is a lookupflags and it only has one bit: symlink_follow
 			// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#lookupflags
@@ -3566,7 +3770,7 @@ func Test_pathOpen(t *testing.T) {
 			// rights aren't used
 			fsRightsBase, fsRightsInheriting := uint64(0), uint64(0)
 
-			requireErrnoResult(t, tc.expectedErrno, mod, PathOpenName, uint64(dirfd), uint64(dirflags), uint64(path),
+			requireErrnoResult(t, tc.expectedErrno, mod, PathOpenName, uint64(fd), uint64(dirflags), uint64(path),
 				uint64(pathLen), uint64(tc.oflags), fsRightsBase, fsRightsInheriting, uint64(tc.fdflags), uint64(resultOpenedFd))
 			require.Equal(t, tc.expectedLog, "\n"+log.String())
 
@@ -3603,18 +3807,18 @@ func requireContents(t *testing.T, fsc *sys.FSContext, expectedOpenedFd uint32,
 }
 
 func mkdir(t *testing.T, tmpDir, dir string) {
-	err := os.Mkdir(path.Join(tmpDir, dir), 0o700)
+	err := os.Mkdir(joinPath(tmpDir, dir), 0o700)
 	require.NoError(t, err)
 }
 
 func readFile(t *testing.T, tmpDir, file string) []byte {
-	contents, err := os.ReadFile(path.Join(tmpDir, file))
+	contents, err := os.ReadFile(joinPath(tmpDir, file))
 	require.NoError(t, err)
 	return contents
 }
 
 func writeFile(t *testing.T, tmpDir, file string, contents []byte) {
-	err := os.WriteFile(path.Join(tmpDir, file), contents, 0o600)
+	err := os.WriteFile(joinPath(tmpDir, file), contents, 0o600)
 	require.NoError(t, err)
 }
 
@@ -3624,15 +3828,13 @@ func Test_pathOpen_Errors(t *testing.T) {
 	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFSConfig(fsConfig))
 	defer r.Close(testCtx)
 
-	preopenedFD := sys.FdPreopen
-
 	file := "file"
-	err := os.WriteFile(path.Join(tmpDir, file), []byte{}, 0o700)
+	err := os.WriteFile(joinPath(tmpDir, file), []byte{}, 0o700)
 	require.NoError(t, err)
 	fileFD := requireOpenFD(t, mod, file)
 
 	dir := "dir"
-	err = os.Mkdir(path.Join(tmpDir, dir), 0o700)
+	err = os.Mkdir(joinPath(tmpDir, dir), 0o700)
 	require.NoError(t, err)
 
 	tests := []struct {
@@ -3651,7 +3853,7 @@ func Test_pathOpen_Errors(t *testing.T) {
 `,
 		},
 		{
-			name:          "FD not a directory",
+			name:          "Fd not a directory",
 			fd:            fileFD,
 			pathName:      file,
 			path:          0,
@@ -3698,7 +3900,7 @@ func Test_pathOpen_Errors(t *testing.T) {
 		},
 		{
 			name:           "out-of-memory writing resultOpenedFd",
-			fd:             preopenedFD,
+			fd:             sys.FdPreopen,
 			pathName:       dir,
 			path:           0,
 			pathLen:        uint32(len(dir)),
@@ -3754,120 +3956,119 @@ func Test_pathOpen_Errors(t *testing.T) {
 func Test_pathReadlink(t *testing.T) {
 	tmpDir := t.TempDir() // open before loop to ensure no locking problems.
 
-	const topDirName = "top"
-	mod, topFd, log, r := requireOpenFile(t, tmpDir, topDirName, nil, false)
+	dirName := "dir"
+	dirPath := joinPath(tmpDir, dirName)
+	mod, dirFD, log, r := requireOpenFile(t, tmpDir, dirName, nil, false)
 	defer r.Close(testCtx)
 
-	const subDirName = "sub-dir"
-	require.NoError(t, os.Mkdir(path.Join(tmpDir, topDirName, subDirName), 0o700))
+	subDirName := "sub-dir"
+	require.NoError(t, os.Mkdir(joinPath(dirPath, subDirName), 0o700))
 
 	mem := mod.Memory()
 
-	const originalFileName = "top-original-file"
-	const destinationPathNamePtr = 0x77
-	const destinationPathName = "top-symlinked"
-	ok := mem.Write(destinationPathNamePtr, []byte(destinationPathName))
+	originalFileName := "top-original-file"
+	destinationPath := uint32(0x77)
+	destinationPathName := "top-symlinked"
+	ok := mem.Write(destinationPath, []byte(destinationPathName))
 	require.True(t, ok)
 
-	originalSubDirFileName := path.Join(subDirName, "subdir-original-file")
-	destinationSubDirFileName := path.Join(subDirName, "subdir-symlinked")
-	const destinationSubDirPathNamePtr = 0xcc
+	originalSubDirFileName := joinPath(subDirName, "subdir-original-file")
+	destinationSubDirFileName := joinPath(subDirName, "subdir-symlinked")
+	destinationSubDirPathNamePtr := uint32(0xcc)
 	ok = mem.Write(destinationSubDirPathNamePtr, []byte(destinationSubDirFileName))
 	require.True(t, ok)
 
 	// Create original file and symlink to the destination.
-	originalRelativePath := path.Join(topDirName, originalFileName)
-	err := os.WriteFile(path.Join(tmpDir, originalRelativePath), []byte{4, 3, 2, 1}, 0o700)
+	originalRelativePath := joinPath(dirName, originalFileName)
+	err := os.WriteFile(joinPath(tmpDir, originalRelativePath), []byte{4, 3, 2, 1}, 0o700)
 	require.NoError(t, err)
-	err = os.Symlink(originalRelativePath, path.Join(tmpDir, topDirName, destinationPathName))
+	err = os.Symlink(originalRelativePath, joinPath(dirPath, destinationPathName))
 	require.NoError(t, err)
-	originalSubDirRelativePath := path.Join(topDirName, originalSubDirFileName)
-	err = os.WriteFile(path.Join(tmpDir, originalSubDirRelativePath), []byte{1, 2, 3, 4}, 0o700)
+	originalSubDirRelativePath := joinPath(dirName, originalSubDirFileName)
+	err = os.WriteFile(joinPath(tmpDir, originalSubDirRelativePath), []byte{1, 2, 3, 4}, 0o700)
 	require.NoError(t, err)
-	err = os.Symlink(originalSubDirRelativePath, path.Join(tmpDir, topDirName, destinationSubDirFileName))
+	err = os.Symlink(originalSubDirRelativePath, joinPath(dirPath, destinationSubDirFileName))
 	require.NoError(t, err)
 
 	t.Run("ok", func(t *testing.T) {
 		for _, tc := range []struct {
-			name    string
-			pathPtr uint64
-			pathLen uint64
-			exp     string
+			name          string
+			path, pathLen uint32
+			expectedBuf   string
 		}{
 			{
-				name:    "top",
-				pathPtr: destinationPathNamePtr,
-				pathLen: uint64(len(destinationPathName)),
-				exp:     originalRelativePath,
+				name:        "top",
+				path:        destinationPath,
+				pathLen:     uint32(len(destinationPathName)),
+				expectedBuf: originalRelativePath,
 			},
 			{
-				name:    "subdir",
-				pathPtr: destinationSubDirPathNamePtr,
-				pathLen: uint64(len(destinationSubDirFileName)),
-				exp:     originalSubDirRelativePath,
+				name:        "subdir",
+				path:        destinationSubDirPathNamePtr,
+				pathLen:     uint32(len(destinationSubDirFileName)),
+				expectedBuf: originalSubDirRelativePath,
 			},
 		} {
 			t.Run(tc.name, func(t *testing.T) {
-				const bufPtr, bufSize, resultBufUsedPtr = 0x100, 0xff, 0x200
+				const buf, bufLen, resultBufused = 0x100, 0xff, 0x200
 				requireErrnoResult(t, ErrnoSuccess, mod, PathReadlinkName,
-					uint64(topFd),
-					tc.pathPtr, tc.pathLen,
-					bufPtr, bufSize, resultBufUsedPtr)
+					uint64(dirFD), uint64(tc.path), uint64(tc.pathLen),
+					buf, bufLen, resultBufused)
 				require.Contains(t, log.String(), ErrnoName(ErrnoSuccess))
 
-				size, ok := mem.ReadUint32Le(resultBufUsedPtr)
+				size, ok := mem.ReadUint32Le(resultBufused)
 				require.True(t, ok)
-				actual, ok := mem.Read(bufPtr, size)
+				actual, ok := mem.Read(buf, size)
 				require.True(t, ok)
-				require.Equal(t, tc.exp, string(actual))
+				require.Equal(t, tc.expectedBuf, string(actual))
 			})
 		}
 	})
 
 	t.Run("errors", func(t *testing.T) {
 		for _, tc := range []struct {
-			name                                                      string
-			errno                                                     Errno
-			dirFd, pathPtr, pathLen, bufPtr, bufLen, resultBufUsedPtr uint64
+			name                                          string
+			fd, path, pathLen, buf, bufLen, resultBufused uint32
+			expectedErrno                                 Errno
 		}{
-			{errno: ErrnoInval},
-			{errno: ErrnoInval, pathLen: 100},
-			{errno: ErrnoInval, bufLen: 100},
+			{expectedErrno: ErrnoInval},
+			{expectedErrno: ErrnoInval, pathLen: 100},
+			{expectedErrno: ErrnoInval, bufLen: 100},
 			{
-				name:    "bufLen too short",
-				errno:   ErrnoFault,
-				dirFd:   uint64(topFd),
-				bufLen:  10,
-				pathPtr: destinationPathNamePtr,
-				pathLen: uint64(len(destinationPathName)),
-				bufPtr:  math.MaxUint32,
+				name:          "bufLen too short",
+				expectedErrno: ErrnoFault,
+				fd:            dirFD,
+				bufLen:        10,
+				path:          destinationPath,
+				pathLen:       uint32(len(destinationPathName)),
+				buf:           math.MaxUint32,
 			},
 			{
-				name:    "pathPtr past memory",
-				errno:   ErrnoFault,
-				bufLen:  100,
-				pathLen: 100,
-				bufPtr:  50,
-				pathPtr: math.MaxUint32,
+				name:          "path past memory",
+				expectedErrno: ErrnoFault,
+				bufLen:        100,
+				pathLen:       100,
+				buf:           50,
+				path:          math.MaxUint32,
 			},
-			{errno: ErrnoNotdir, bufLen: 100, pathLen: 100, bufPtr: 50, pathPtr: 50, dirFd: 1},
-			{errno: ErrnoBadf, bufLen: 100, pathLen: 100, bufPtr: 50, pathPtr: 50, dirFd: 1000},
+			{expectedErrno: ErrnoNotdir, bufLen: 100, pathLen: 100, buf: 50, path: 50, fd: 1},
+			{expectedErrno: ErrnoBadf, bufLen: 100, pathLen: 100, buf: 50, path: 50, fd: 1000},
 			{
-				errno:  ErrnoNoent,
-				bufLen: 100, bufPtr: 50,
-				pathPtr: destinationPathNamePtr, pathLen: uint64(len(destinationPathName)) - 1,
-				dirFd: uint64(topFd),
+				expectedErrno: ErrnoNoent,
+				bufLen:        100, buf: 50,
+				path: destinationPath, pathLen: uint32(len(destinationPathName)) - 1,
+				fd: dirFD,
 			},
 		} {
 			name := tc.name
 			if name == "" {
-				name = ErrnoName(tc.errno)
+				name = ErrnoName(tc.expectedErrno)
 			}
 			t.Run(name, func(t *testing.T) {
-				requireErrnoResult(t, tc.errno, mod, PathReadlinkName,
-					tc.dirFd, tc.pathPtr, tc.pathLen, tc.bufPtr,
-					tc.bufLen, tc.resultBufUsedPtr)
-				require.Contains(t, log.String(), ErrnoName(tc.errno))
+				requireErrnoResult(t, tc.expectedErrno, mod, PathReadlinkName,
+					uint64(tc.fd), uint64(tc.path), uint64(tc.pathLen), uint64(tc.buf),
+					uint64(tc.bufLen), uint64(tc.resultBufused))
+				require.Contains(t, log.String(), ErrnoName(tc.expectedErrno))
 			})
 		}
 	})
@@ -3881,7 +4082,7 @@ func Test_pathRemoveDirectory(t *testing.T) {
 
 	// set up the initial memory to include the path name starting at an offset.
 	pathName := "wazero"
-	realPath := path.Join(tmpDir, pathName)
+	realPath := joinPath(tmpDir, pathName)
 	ok := mod.Memory().Write(0, append([]byte{'?'}, pathName...))
 	require.True(t, ok)
 
@@ -3889,11 +4090,11 @@ func Test_pathRemoveDirectory(t *testing.T) {
 	err := os.Mkdir(realPath, 0o700)
 	require.NoError(t, err)
 
-	dirFD := sys.FdPreopen
+	fd := sys.FdPreopen
 	name := 1
 	nameLen := len(pathName)
 
-	requireErrnoResult(t, ErrnoSuccess, mod, PathRemoveDirectoryName, uint64(dirFD), uint64(name), uint64(nameLen))
+	requireErrnoResult(t, ErrnoSuccess, mod, PathRemoveDirectoryName, uint64(fd), uint64(name), uint64(nameLen))
 	require.Equal(t, `
 ==> wasi_snapshot_preview1.path_remove_directory(fd=3,path=wazero)
 <== errno=ESUCCESS
@@ -3911,16 +4112,17 @@ func Test_pathRemoveDirectory_Errors(t *testing.T) {
 	defer r.Close(testCtx)
 
 	file := "file"
-	err := os.WriteFile(path.Join(tmpDir, file), []byte{}, 0o700)
+	err := os.WriteFile(joinPath(tmpDir, file), []byte{}, 0o700)
 	require.NoError(t, err)
 	fileFD := requireOpenFD(t, mod, file)
 
 	dirNotEmpty := "notempty"
-	err = os.Mkdir(path.Join(tmpDir, dirNotEmpty), 0o700)
+	dirNotEmptyPath := joinPath(tmpDir, dirNotEmpty)
+	err = os.Mkdir(dirNotEmptyPath, 0o700)
 	require.NoError(t, err)
 
 	dir := "dir"
-	err = os.Mkdir(path.Join(tmpDir, dirNotEmpty, dir), 0o700)
+	err = os.Mkdir(joinPath(dirNotEmptyPath, dir), 0o700)
 	require.NoError(t, err)
 
 	tests := []struct {
@@ -3939,7 +4141,7 @@ func Test_pathRemoveDirectory_Errors(t *testing.T) {
 `,
 		},
 		{
-			name:          "FD not a directory",
+			name:          "Fd not a directory",
 			fd:            fileFD,
 			pathName:      file,
 			path:          0,
@@ -4026,69 +4228,70 @@ func Test_pathRemoveDirectory_Errors(t *testing.T) {
 func Test_pathSymlink_errors(t *testing.T) {
 	tmpDir := t.TempDir() // open before loop to ensure no locking problems.
 
-	const dirname = "my-dir"
-	mod, fd, log, r := requireOpenFile(t, tmpDir, dirname, nil, false)
+	dirName := "dir"
+	dirPath := joinPath(tmpDir, dirName)
+	mod, fd, log, r := requireOpenFile(t, tmpDir, dirName, nil, false)
 	defer r.Close(testCtx)
 
 	mem := mod.Memory()
 
-	const filename = "file"
-	err := os.WriteFile(path.Join(tmpDir, dirname, filename), []byte{1, 2, 3, 4}, 0o700)
+	fileName := "file"
+	err := os.WriteFile(joinPath(dirPath, fileName), []byte{1, 2, 3, 4}, 0o700)
 	require.NoError(t, err)
 
-	const fileNamePtr = 0xff
-	ok := mem.Write(fileNamePtr, []byte(filename))
+	file := uint32(0xff)
+	ok := mem.Write(file, []byte(fileName))
 	require.True(t, ok)
 
-	const nonExistingFileNamePtr = 0xaa
-	const nonExistingFileName = "invalid-san"
-	ok = mem.Write(nonExistingFileNamePtr, []byte(nonExistingFileName))
+	notFoundFile := uint32(0xaa)
+	notFoundFileName := "nope"
+	ok = mem.Write(notFoundFile, []byte(notFoundFileName))
 	require.True(t, ok)
 
-	const destinationNamePtr = 0xcc
-	const destinationName = "symlinked"
-	ok = mem.Write(destinationNamePtr, []byte(destinationName))
+	link := uint32(0xcc)
+	linkName := fileName + "-link"
+	ok = mem.Write(link, []byte(linkName))
 	require.True(t, ok)
 
 	t.Run("success", func(t *testing.T) {
 		requireErrnoResult(t, ErrnoSuccess, mod, PathSymlinkName,
-			fileNamePtr, uint64(len(filename)), uint64(fd), destinationNamePtr, uint64(len(destinationName)))
+			uint64(file), uint64(len(fileName)), uint64(fd), uint64(link), uint64(len(linkName)))
 		require.Contains(t, log.String(), ErrnoName(ErrnoSuccess))
-		st, err := os.Lstat(path.Join(tmpDir, dirname, destinationName))
+		st, err := os.Lstat(joinPath(dirPath, linkName))
 		require.NoError(t, err)
 		require.Equal(t, st.Mode()&os.ModeSymlink, os.ModeSymlink)
 	})
 
 	t.Run("errors", func(t *testing.T) {
 		for _, tc := range []struct {
-			errno                                 Errno
-			dirFd, oldPtr, newPtr, oldLen, newLen uint64
+			errno                                        Errno
+			oldPath, oldPathLen, fd, newPath, newPathLen uint32
 		}{
-			{errno: ErrnoBadf, dirFd: 1000},
-			{errno: ErrnoNotdir, dirFd: 2},
+			{errno: ErrnoBadf, fd: 1000},
+			{errno: ErrnoNotdir, fd: 2},
 			// Length zero buffer is not valid.
-			{errno: ErrnoInval, dirFd: uint64(fd)},
-			{errno: ErrnoInval, oldLen: 100, dirFd: uint64(fd)},
-			{errno: ErrnoInval, newLen: 100, dirFd: uint64(fd)},
+			{errno: ErrnoInval, fd: fd},
+			{errno: ErrnoInval, oldPathLen: 100, fd: fd},
+			{errno: ErrnoInval, newPathLen: 100, fd: fd},
 			// Invalid pointer to the names.
-			{errno: ErrnoFault, oldPtr: math.MaxUint64, oldLen: 100, newLen: 100, dirFd: uint64(fd)},
-			{errno: ErrnoFault, newPtr: math.MaxUint64, oldLen: 100, newLen: 100, dirFd: uint64(fd)},
-			{errno: ErrnoFault, oldPtr: math.MaxUint64, newPtr: math.MaxUint64, oldLen: 100, newLen: 100, dirFd: uint64(fd)},
+			{errno: ErrnoFault, oldPath: math.MaxUint32, oldPathLen: 100, newPathLen: 100, fd: fd},
+			{errno: ErrnoFault, newPath: math.MaxUint32, oldPathLen: 100, newPathLen: 100, fd: fd},
+			{errno: ErrnoFault, oldPath: math.MaxUint32, newPath: math.MaxUint32, oldPathLen: 100, newPathLen: 100, fd: fd},
 			// Non-existing path as source.
 			{
-				errno: ErrnoInval, oldPtr: nonExistingFileNamePtr, oldLen: uint64(len(nonExistingFileName)),
-				newPtr: 0, newLen: 5, dirFd: uint64(fd),
+				errno: ErrnoInval, oldPath: notFoundFile, oldPathLen: uint32(len(notFoundFileName)),
+				newPath: 0, newPathLen: 5, fd: fd,
 			},
 			// Linking to existing file.
 			{
-				errno: ErrnoExist, oldPtr: fileNamePtr, oldLen: uint64(len(filename)),
-				newPtr: fileNamePtr, newLen: uint64(len(filename)), dirFd: uint64(fd),
+				errno: ErrnoExist, oldPath: file, oldPathLen: uint32(len(fileName)),
+				newPath: file, newPathLen: uint32(len(fileName)), fd: fd,
 			},
 		} {
 			name := ErrnoName(tc.errno)
 			t.Run(name, func(t *testing.T) {
 				requireErrnoResult(t, tc.errno, mod, PathSymlinkName,
-					tc.oldPtr, tc.oldLen, tc.dirFd, tc.newPtr, tc.newLen)
+					uint64(tc.oldPath), uint64(tc.oldPathLen), uint64(tc.fd), uint64(tc.newPath), uint64(tc.newPathLen))
 				require.Contains(t, log.String(), name)
 			})
 		}
@@ -4102,9 +4305,9 @@ func Test_pathRename(t *testing.T) {
 	defer r.Close(testCtx)
 
 	// set up the initial memory to include the old path name starting at an offset.
-	oldDirFD := sys.FdPreopen
+	oldfd := sys.FdPreopen
 	oldPathName := "wazero"
-	realOldPath := path.Join(tmpDir, oldPathName)
+	realOldPath := joinPath(tmpDir, oldPathName)
 	oldPath := uint32(0)
 	oldPathLen := len(oldPathName)
 	ok := mod.Memory().Write(oldPath, []byte(oldPathName))
@@ -4114,17 +4317,17 @@ func Test_pathRename(t *testing.T) {
 	err := os.WriteFile(realOldPath, []byte{}, 0o600)
 	require.NoError(t, err)
 
-	newDirFD := sys.FdPreopen
+	newfd := sys.FdPreopen
 	newPathName := "wahzero"
-	realNewPath := path.Join(tmpDir, newPathName)
+	realNewPath := joinPath(tmpDir, newPathName)
 	newPath := uint32(16)
 	newPathLen := len(newPathName)
 	ok = mod.Memory().Write(newPath, []byte(newPathName))
 	require.True(t, ok)
 
 	requireErrnoResult(t, ErrnoSuccess, mod, PathRenameName,
-		uint64(oldDirFD), uint64(oldPath), uint64(oldPathLen),
-		uint64(newDirFD), uint64(newPath), uint64(newPathLen))
+		uint64(oldfd), uint64(oldPath), uint64(oldPathLen),
+		uint64(newfd), uint64(newPath), uint64(newPathLen))
 	require.Equal(t, `
 ==> wasi_snapshot_preview1.path_rename(fd=3,old_path=wazero,new_fd=3,new_path=wahzero)
 <== errno=ESUCCESS
@@ -4144,23 +4347,23 @@ func Test_pathRename_Errors(t *testing.T) {
 	defer r.Close(testCtx)
 
 	file := "file"
-	err := os.WriteFile(path.Join(tmpDir, file), []byte{}, 0o700)
+	err := os.WriteFile(joinPath(tmpDir, file), []byte{}, 0o700)
 	require.NoError(t, err)
 
 	// We have to test FD validation with a path not under test. Otherwise,
 	// Windows may fail for the wrong reason, like:
 	//	The process cannot access the file because it is being used by another process.
 	file1 := "file1"
-	err = os.WriteFile(path.Join(tmpDir, file1), []byte{}, 0o700)
+	err = os.WriteFile(joinPath(tmpDir, file1), []byte{}, 0o700)
 	require.NoError(t, err)
 	fileFD := requireOpenFD(t, mod, file1)
 
 	dirNotEmpty := "notempty"
-	err = os.Mkdir(path.Join(tmpDir, dirNotEmpty), 0o700)
+	err = os.Mkdir(joinPath(tmpDir, dirNotEmpty), 0o700)
 	require.NoError(t, err)
 
-	dir := path.Join(dirNotEmpty, "dir")
-	err = os.Mkdir(path.Join(tmpDir, dir), 0o700)
+	dir := joinPath(dirNotEmpty, "dir")
+	err = os.Mkdir(joinPath(tmpDir, dir), 0o700)
 	require.NoError(t, err)
 
 	tests := []struct {
@@ -4171,7 +4374,7 @@ func Test_pathRename_Errors(t *testing.T) {
 		expectedLog                    string
 	}{
 		{
-			name:          "unopened old fd",
+			name:          "unopened old FD",
 			oldFd:         42, // arbitrary invalid fd
 			newFd:         sys.FdPreopen,
 			expectedErrno: ErrnoBadf,
@@ -4191,7 +4394,7 @@ func Test_pathRename_Errors(t *testing.T) {
 `,
 		},
 		{
-			name:          "unopened new fd",
+			name:          "unopened new FD",
 			oldFd:         sys.FdPreopen,
 			newFd:         42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
@@ -4319,7 +4522,7 @@ func Test_pathUnlinkFile(t *testing.T) {
 
 	// set up the initial memory to include the path name starting at an offset.
 	pathName := "wazero"
-	realPath := path.Join(tmpDir, pathName)
+	realPath := joinPath(tmpDir, pathName)
 	ok := mod.Memory().Write(0, append([]byte{'?'}, pathName...))
 	require.True(t, ok)
 
@@ -4327,11 +4530,11 @@ func Test_pathUnlinkFile(t *testing.T) {
 	err := os.WriteFile(realPath, []byte{}, 0o600)
 	require.NoError(t, err)
 
-	dirFD := sys.FdPreopen
+	fd := sys.FdPreopen
 	name := 1
 	nameLen := len(pathName)
 
-	requireErrnoResult(t, ErrnoSuccess, mod, PathUnlinkFileName, uint64(dirFD), uint64(name), uint64(nameLen))
+	requireErrnoResult(t, ErrnoSuccess, mod, PathUnlinkFileName, uint64(fd), uint64(name), uint64(nameLen))
 	require.Equal(t, `
 ==> wasi_snapshot_preview1.path_unlink_file(fd=3,path=wazero)
 <== errno=ESUCCESS
@@ -4349,12 +4552,12 @@ func Test_pathUnlinkFile_Errors(t *testing.T) {
 	defer r.Close(testCtx)
 
 	file := "file"
-	err := os.WriteFile(path.Join(tmpDir, file), []byte{}, 0o700)
+	err := os.WriteFile(joinPath(tmpDir, file), []byte{}, 0o700)
 	require.NoError(t, err)
 	fileFD := requireOpenFD(t, mod, file)
 
 	dir := "dir"
-	err = os.Mkdir(path.Join(tmpDir, dir), 0o700)
+	err = os.Mkdir(joinPath(tmpDir, dir), 0o700)
 	require.NoError(t, err)
 
 	tests := []struct {
@@ -4373,7 +4576,7 @@ func Test_pathUnlinkFile_Errors(t *testing.T) {
 `,
 		},
 		{
-			name:          "FD not a directory",
+			name:          "Fd not a directory",
 			fd:            fileFD,
 			expectedErrno: ErrnoNotdir,
 			expectedLog: `
@@ -4445,7 +4648,7 @@ func Test_pathUnlinkFile_Errors(t *testing.T) {
 func requireOpenFile(t *testing.T, tmpDir string, pathName string, data []byte, readOnly bool) (api.Module, uint32, *bytes.Buffer, api.Closer) {
 	oflags := os.O_RDWR
 
-	realPath := path.Join(tmpDir, pathName)
+	realPath := joinPath(tmpDir, pathName)
 	if data == nil {
 		oflags = os.O_RDONLY
 		require.NoError(t, os.Mkdir(realPath, 0o700))
@@ -4489,13 +4692,13 @@ func Test_fdReaddir_dotEntriesHaveRealInodes(t *testing.T) {
 	fsc := mod.(*wasm.CallContext).Sys.FS()
 	preopen := fsc.RootFS()
 
-	const readDirTarget = "dir"
+	readDirTarget := "dir"
 	mem.Write(0, []byte(readDirTarget))
 	requireErrnoResult(t, ErrnoSuccess, mod, PathCreateDirectoryName,
 		uint64(sys.FdPreopen), uint64(0), uint64(len(readDirTarget)))
 
 	// Open the directory, before writing files!
-	dirFd, err := fsc.OpenFile(preopen, readDirTarget, os.O_RDONLY, 0)
+	fd, err := fsc.OpenFile(preopen, readDirTarget, os.O_RDONLY, 0)
 	require.NoError(t, err)
 
 	// get the real inode of the current directory
@@ -4519,7 +4722,7 @@ func Test_fdReaddir_dotEntriesHaveRealInodes(t *testing.T) {
 	resultBufused := uint32(0) // where to write the amount used out of bufLen
 	buf := uint32(8)           // where to start the dirents
 	requireErrnoResult(t, ErrnoSuccess, mod, FdReaddirName,
-		uint64(dirFd), uint64(buf), uint64(0x2000), 0, uint64(resultBufused))
+		uint64(fd), uint64(buf), uint64(0x2000), 0, uint64(resultBufused))
 
 	used, _ := mem.ReadUint32Le(resultBufused)
 
@@ -4535,9 +4738,9 @@ func Test_fdReaddir_opened_file_written(t *testing.T) {
 		t.Skip("windows before go 1.20 has trouble reading the inode information on directories.")
 	}
 
-	root := t.TempDir()
+	tmpDir := t.TempDir()
 	mod, r, _ := requireProxyModule(t, wazero.NewModuleConfig().
-		WithFSConfig(wazero.NewFSConfig().WithDirMount(root, "/")),
+		WithFSConfig(wazero.NewFSConfig().WithDirMount(tmpDir, "/")),
 	)
 	defer r.Close(testCtx)
 
@@ -4546,23 +4749,24 @@ func Test_fdReaddir_opened_file_written(t *testing.T) {
 	fsc := mod.(*wasm.CallContext).Sys.FS()
 	preopen := fsc.RootFS()
 
-	const readDirTarget = "dir"
-	mem.Write(0, []byte(readDirTarget))
+	dirName := "dir"
+	dirPath := joinPath(tmpDir, dirName)
+	mem.Write(0, []byte(dirName))
 	requireErrnoResult(t, ErrnoSuccess, mod, PathCreateDirectoryName,
-		uint64(sys.FdPreopen), uint64(0), uint64(len(readDirTarget)))
+		uint64(sys.FdPreopen), uint64(0), uint64(len(dirName)))
 
 	// Open the directory, before writing files!
-	dirFd, err := fsc.OpenFile(preopen, readDirTarget, os.O_RDONLY, 0)
+	dirFD, err := fsc.OpenFile(preopen, dirName, os.O_RDONLY, 0)
 	require.NoError(t, err)
 
 	// Then write a file to the directory.
-	f, err := os.Create(path.Join(root, readDirTarget, "afile"))
+	f, err := os.Create(joinPath(dirPath, "file"))
 	require.NoError(t, err)
 	defer f.Close()
 
 	// get the real inode of the current directory
 	var st platform.Stat_t
-	require.NoError(t, preopen.Stat(readDirTarget, &st))
+	require.NoError(t, preopen.Stat(dirName, &st))
 	dirents := []byte{1, 0, 0, 0, 0, 0, 0, 0}         // d_next = 1
 	dirents = append(dirents, u64.LeBytes(st.Ino)...) // d_ino
 	dirents = append(dirents, 1, 0, 0, 0)             // d_namlen = 1 character
@@ -4579,20 +4783,26 @@ func Test_fdReaddir_opened_file_written(t *testing.T) {
 
 	// get the real inode of the file
 	require.NoError(t, platform.StatFile(f, &st))
-	dirents = append(dirents, 3, 0, 0, 0, 0, 0, 0, 0)  // d_next = 3
-	dirents = append(dirents, u64.LeBytes(st.Ino)...)  // d_ino
-	dirents = append(dirents, 5, 0, 0, 0)              // d_namlen = 5 characters
-	dirents = append(dirents, 4, 0, 0, 0)              // d_type = regular_file
-	dirents = append(dirents, 'a', 'f', 'i', 'l', 'e') // name
+	dirents = append(dirents, 3, 0, 0, 0, 0, 0, 0, 0) // d_next = 3
+	dirents = append(dirents, u64.LeBytes(st.Ino)...) // d_ino
+	dirents = append(dirents, 4, 0, 0, 0)             // d_namlen = 4 characters
+	dirents = append(dirents, 4, 0, 0, 0)             // d_type = regular_file
+	dirents = append(dirents, 'f', 'i', 'l', 'e')     // name
 
 	// Try to list them!
 	resultBufused := uint32(0) // where to write the amount used out of bufLen
 	buf := uint32(8)           // where to start the dirents
 	requireErrnoResult(t, ErrnoSuccess, mod, FdReaddirName,
-		uint64(dirFd), uint64(buf), uint64(0x2000), 0, uint64(resultBufused))
+		uint64(dirFD), uint64(buf), uint64(0x2000), 0, uint64(resultBufused))
 
 	used, _ := mem.ReadUint32Le(resultBufused)
 
 	results, _ := mem.Read(buf, used)
 	require.Equal(t, dirents, results)
 }
+
+// joinPath avoids us having to rename fields just to avoid conflict with the
+// path package.
+func joinPath(dirName, baseName string) string {
+	return path.Join(dirName, baseName)
+}
diff --git a/imports/wasi_snapshot_preview1/wasi_test.go b/imports/wasi_snapshot_preview1/wasi_test.go
index bcc25cd5..977bb1bf 100644
--- a/imports/wasi_snapshot_preview1/wasi_test.go
+++ b/imports/wasi_snapshot_preview1/wasi_test.go
@@ -145,5 +145,5 @@ func requireErrnoResult(t *testing.T, expectedErrno Errno, mod api.Closer, funcN
 	results, err := mod.(api.Module).ExportedFunction(funcName).Call(testCtx, params...)
 	require.NoError(t, err)
 	errno := Errno(results[0])
-	require.Equal(t, expectedErrno, errno, "want %s but got %s", ErrnoName(expectedErrno), ErrnoName(errno))
+	require.Equal(t, expectedErrno, errno, "want %s but have %s", ErrnoName(expectedErrno), ErrnoName(errno))
 }
diff --git a/internal/platform/futimens_test.go b/internal/platform/futimens_test.go
index 4f91a37e..f082b0a2 100644
--- a/internal/platform/futimens_test.go
+++ b/internal/platform/futimens_test.go
@@ -79,6 +79,20 @@ func testFutimens(t *testing.T, usePath bool) {
 				{Sec: 123, Nsec: UTIME_NOW},
 			},
 		},
+		{
+			name: "a=set,m=omit",
+			times: &[2]syscall.Timespec{
+				{Sec: 123, Nsec: 4 * 1e3},
+				{Sec: 123, Nsec: UTIME_OMIT},
+			},
+		},
+		{
+			name: "a=omit,m=set",
+			times: &[2]syscall.Timespec{
+				{Sec: 123, Nsec: UTIME_OMIT},
+				{Sec: 123, Nsec: 4 * 1e3},
+			},
+		},
 		{
 			name: "a=set,m=set",
 			times: &[2]syscall.Timespec{
diff --git a/internal/platform/open_file_test.go b/internal/platform/open_file_test.go
index f1f98640..cc6f754a 100644
--- a/internal/platform/open_file_test.go
+++ b/internal/platform/open_file_test.go
@@ -2,7 +2,7 @@ package platform
 
 import (
 	"os"
-	pathutil "path/filepath"
+	path "path/filepath"
 	"syscall"
 	"testing"
 
@@ -13,13 +13,13 @@ func TestOpenFile_Errors(t *testing.T) {
 	tmpDir := t.TempDir()
 
 	t.Run("not found must be ENOENT", func(t *testing.T) {
-		_, err := OpenFile(pathutil.Join(tmpDir, "not-really-exist.txt"), os.O_RDONLY, 0o600)
+		_, err := OpenFile(path.Join(tmpDir, "not-really-exist.txt"), os.O_RDONLY, 0o600)
 		require.EqualErrno(t, syscall.ENOENT, err)
 	})
 
 	// This is the same as https://github.com/ziglang/zig/blob/d24ebf1d12cf66665b52136a2807f97ff021d78d/lib/std/os/test.zig#L105-L112
 	t.Run("try creating on existing file must be EEXIST", func(t *testing.T) {
-		filepath := pathutil.Join(tmpDir, "file.txt")
+		filepath := path.Join(tmpDir, "file.txt")
 		f, err := OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666)
 		defer require.NoError(t, f.Close())
 		require.NoError(t, err)
@@ -29,7 +29,7 @@ func TestOpenFile_Errors(t *testing.T) {
 	})
 
 	t.Run("writing to a read-only file is EBADF", func(t *testing.T) {
-		path := pathutil.Join(tmpDir, "file")
+		path := path.Join(tmpDir, "file")
 		require.NoError(t, os.WriteFile(path, nil, 0o600))
 
 		f, err := OpenFile(path, os.O_RDONLY, 0)
@@ -41,7 +41,7 @@ func TestOpenFile_Errors(t *testing.T) {
 	})
 
 	t.Run("writing to a directory is EBADF", func(t *testing.T) {
-		path := pathutil.Join(tmpDir, "diragain")
+		path := path.Join(tmpDir, "diragain")
 		require.NoError(t, os.Mkdir(path, 0o755))
 
 		f, err := OpenFile(path, os.O_RDONLY, 0)
@@ -54,8 +54,8 @@ func TestOpenFile_Errors(t *testing.T) {
 
 	// This is similar to https://github.com/WebAssembly/wasi-testsuite/blob/dc7f8d27be1030cd4788ebdf07d9b57e5d23441e/tests/rust/src/bin/dangling_symlink.rs
 	t.Run("dangling symlinks", func(t *testing.T) {
-		target := pathutil.Join(tmpDir, "target")
-		symlink := pathutil.Join(tmpDir, "dangling_symlink_symlink.cleanup")
+		target := path.Join(tmpDir, "target")
+		symlink := path.Join(tmpDir, "dangling_symlink_symlink.cleanup")
 
 		err := os.Symlink(target, symlink)
 		require.NoError(t, err)
diff --git a/internal/platform/stat_test.go b/internal/platform/stat_test.go
index 52cf4b4f..731985c8 100644
--- a/internal/platform/stat_test.go
+++ b/internal/platform/stat_test.go
@@ -3,7 +3,7 @@ package platform
 import (
 	"io/fs"
 	"os"
-	pathutil "path"
+	"path"
 	"runtime"
 	"syscall"
 	"testing"
@@ -16,8 +16,8 @@ func TestLstat(t *testing.T) {
 	tmpDir := t.TempDir()
 
 	var stat Stat_t
-	require.EqualErrno(t, syscall.ENOENT, Lstat(pathutil.Join(tmpDir, "cat"), &stat))
-	require.EqualErrno(t, syscall.ENOENT, Lstat(pathutil.Join(tmpDir, "sub/cat"), &stat))
+	require.EqualErrno(t, syscall.ENOENT, Lstat(path.Join(tmpDir, "cat"), &stat))
+	require.EqualErrno(t, syscall.ENOENT, Lstat(path.Join(tmpDir, "sub/cat"), &stat))
 
 	t.Run("dir", func(t *testing.T) {
 		err := Lstat(tmpDir, &stat)
@@ -26,7 +26,7 @@ func TestLstat(t *testing.T) {
 		require.NotEqual(t, uint64(0), stat.Ino)
 	})
 
-	file := pathutil.Join(tmpDir, "file")
+	file := path.Join(tmpDir, "file")
 	var statFile Stat_t
 
 	t.Run("file", func(t *testing.T) {
@@ -41,7 +41,7 @@ func TestLstat(t *testing.T) {
 		requireLinkStat(t, file, &statFile)
 	})
 
-	subdir := pathutil.Join(tmpDir, "sub")
+	subdir := path.Join(tmpDir, "sub")
 	var statSubdir Stat_t
 	t.Run("subdir", func(t *testing.T) {
 		require.NoError(t, os.Mkdir(subdir, 0o500))
@@ -87,8 +87,8 @@ func TestStat(t *testing.T) {
 	tmpDir := t.TempDir()
 
 	var stat Stat_t
-	require.EqualErrno(t, syscall.ENOENT, Stat(pathutil.Join(tmpDir, "cat"), &stat))
-	require.EqualErrno(t, syscall.ENOENT, Stat(pathutil.Join(tmpDir, "sub/cat"), &stat))
+	require.EqualErrno(t, syscall.ENOENT, Stat(path.Join(tmpDir, "cat"), &stat))
+	require.EqualErrno(t, syscall.ENOENT, Stat(path.Join(tmpDir, "sub/cat"), &stat))
 
 	t.Run("dir", func(t *testing.T) {
 		err := Stat(tmpDir, &stat)
@@ -97,7 +97,7 @@ func TestStat(t *testing.T) {
 		require.NotEqual(t, uint64(0), stat.Ino)
 	})
 
-	file := pathutil.Join(tmpDir, "file")
+	file := path.Join(tmpDir, "file")
 	var statFile Stat_t
 
 	t.Run("file", func(t *testing.T) {
@@ -108,14 +108,14 @@ func TestStat(t *testing.T) {
 	})
 
 	t.Run("link to file", func(t *testing.T) {
-		link := pathutil.Join(tmpDir, "file-link")
+		link := path.Join(tmpDir, "file-link")
 		require.NoError(t, os.Symlink(file, link))
 
 		require.NoError(t, Stat(link, &stat))
 		require.Equal(t, statFile, stat) // resolves to the file
 	})
 
-	subdir := pathutil.Join(tmpDir, "sub")
+	subdir := path.Join(tmpDir, "sub")
 	var statSubdir Stat_t
 	t.Run("subdir", func(t *testing.T) {
 		require.NoError(t, os.Mkdir(subdir, 0o500))
@@ -126,7 +126,7 @@ func TestStat(t *testing.T) {
 	})
 
 	t.Run("link to dir", func(t *testing.T) {
-		link := pathutil.Join(tmpDir, "dir-link")
+		link := path.Join(tmpDir, "dir-link")
 		require.NoError(t, os.Symlink(subdir, link))
 
 		require.NoError(t, Stat(link, &stat))
@@ -159,7 +159,7 @@ func TestStatFile(t *testing.T) {
 		})
 	}
 
-	file := pathutil.Join(tmpDir, "file")
+	file := path.Join(tmpDir, "file")
 	require.NoError(t, os.WriteFile(file, nil, 0o400))
 	fileF, err := OpenFile(file, syscall.O_RDONLY, 0)
 	require.NoError(t, err)
@@ -178,7 +178,7 @@ func TestStatFile(t *testing.T) {
 		require.NotEqual(t, uint64(0), stat.Ino)
 	})
 
-	subdir := pathutil.Join(tmpDir, "sub")
+	subdir := path.Join(tmpDir, "sub")
 	require.NoError(t, os.Mkdir(subdir, 0o500))
 	subdirF, err := OpenFile(subdir, syscall.O_RDONLY, 0)
 	require.NoError(t, err)
@@ -202,7 +202,7 @@ func TestStatFile(t *testing.T) {
 func Test_StatFile_times(t *testing.T) {
 	tmpDir := t.TempDir()
 
-	file := pathutil.Join(tmpDir, "file")
+	file := path.Join(tmpDir, "file")
 	err := os.WriteFile(file, []byte{}, 0o700)
 	require.NoError(t, err)
 
@@ -256,17 +256,17 @@ func TestStatFile_dev_inode(t *testing.T) {
 	require.NoError(t, err)
 	defer d.Close()
 
-	path1 := pathutil.Join(tmpDir, "1")
+	path1 := path.Join(tmpDir, "1")
 	f1, err := os.Create(path1)
 	require.NoError(t, err)
 	defer f1.Close()
 
-	path2 := pathutil.Join(tmpDir, "2")
+	path2 := path.Join(tmpDir, "2")
 	f2, err := os.Create(path2)
 	require.NoError(t, err)
 	defer f2.Close()
 
-	pathLink2 := pathutil.Join(tmpDir, "link2")
+	pathLink2 := path.Join(tmpDir, "link2")
 	err = os.Symlink(path2, pathLink2)
 	require.NoError(t, err)
 	l2, err := os.Open(pathLink2)
diff --git a/internal/sysfs/adapter_test.go b/internal/sysfs/adapter_test.go
index 06326494..6f9b7be3 100644
--- a/internal/sysfs/adapter_test.go
+++ b/internal/sysfs/adapter_test.go
@@ -4,7 +4,6 @@ import (
 	"errors"
 	"io/fs"
 	"os"
-	pathutil "path"
 	"runtime"
 	"syscall"
 	"testing"
@@ -44,13 +43,13 @@ func TestAdapt_Rename(t *testing.T) {
 	testFS := Adapt(os.DirFS(tmpDir))
 
 	file1 := "file1"
-	file1Path := pathutil.Join(tmpDir, file1)
+	file1Path := joinPath(tmpDir, file1)
 	file1Contents := []byte{1}
 	err := os.WriteFile(file1Path, file1Contents, 0o600)
 	require.NoError(t, err)
 
 	file2 := "file2"
-	file2Path := pathutil.Join(tmpDir, file2)
+	file2Path := joinPath(tmpDir, file2)
 	file2Contents := []byte{2}
 	err = os.WriteFile(file2Path, file2Contents, 0o600)
 	require.NoError(t, err)
@@ -64,7 +63,7 @@ func TestAdapt_Rmdir(t *testing.T) {
 	testFS := Adapt(os.DirFS(tmpDir))
 
 	path := "rmdir"
-	realPath := pathutil.Join(tmpDir, path)
+	realPath := joinPath(tmpDir, path)
 	require.NoError(t, os.Mkdir(realPath, 0o700))
 
 	err := testFS.Rmdir(path)
@@ -76,7 +75,7 @@ func TestAdapt_Unlink(t *testing.T) {
 	testFS := Adapt(os.DirFS(tmpDir))
 
 	path := "unlink"
-	realPath := pathutil.Join(tmpDir, path)
+	realPath := joinPath(tmpDir, path)
 	require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
 
 	err := testFS.Unlink(path)
@@ -88,7 +87,7 @@ func TestAdapt_UtimesNano(t *testing.T) {
 	testFS := Adapt(os.DirFS(tmpDir))
 
 	path := "utimes"
-	realPath := pathutil.Join(tmpDir, path)
+	realPath := joinPath(tmpDir, path)
 	require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
 
 	err := testFS.Utimens(path, nil, true)
@@ -98,7 +97,7 @@ func TestAdapt_UtimesNano(t *testing.T) {
 func TestAdapt_Open_Read(t *testing.T) {
 	// Create a subdirectory, so we can test reads outside the FS root.
 	tmpDir := t.TempDir()
-	tmpDir = pathutil.Join(tmpDir, t.Name())
+	tmpDir = joinPath(tmpDir, t.Name())
 	require.NoError(t, os.Mkdir(tmpDir, 0o700))
 	require.NoError(t, fstest.WriteTestFiles(tmpDir))
 	testFS := Adapt(os.DirFS(tmpDir))
@@ -125,8 +124,8 @@ func TestAdapt_Lstat(t *testing.T) {
 	testFS := Adapt(os.DirFS(tmpDir))
 
 	for _, path := range []string{"animals.txt", "sub", "sub-link"} {
-		fullPath := pathutil.Join(tmpDir, path)
-		linkPath := pathutil.Join(tmpDir, path+"-link")
+		fullPath := joinPath(tmpDir, path)
+		linkPath := joinPath(tmpDir, path+"-link")
 		require.NoError(t, os.Symlink(fullPath, linkPath))
 		var stat platform.Stat_t
 		require.EqualErrno(t, syscall.ENOSYS, testFS.Lstat(linkPath, &stat))
diff --git a/internal/sysfs/dirfs_test.go b/internal/sysfs/dirfs_test.go
index 6a68396e..74e07c12 100644
--- a/internal/sysfs/dirfs_test.go
+++ b/internal/sysfs/dirfs_test.go
@@ -4,7 +4,7 @@ import (
 	"errors"
 	"io/fs"
 	"os"
-	pathutil "path"
+	"path"
 	"runtime"
 	"syscall"
 	"testing"
@@ -63,7 +63,7 @@ func TestDirFS_MkDir(t *testing.T) {
 	testFS := NewDirFS(tmpDir)
 
 	name := "mkdir"
-	realPath := pathutil.Join(tmpDir, name)
+	realPath := path.Join(tmpDir, name)
 
 	t.Run("doesn't exist", func(t *testing.T) {
 		require.NoError(t, testFS.Mkdir(name, fs.ModeDir))
@@ -86,7 +86,7 @@ func TestDirFS_MkDir(t *testing.T) {
 		require.EqualErrno(t, syscall.EEXIST, err)
 	})
 	t.Run("try creating on file", func(t *testing.T) {
-		filePath := pathutil.Join("non-existing-dir", "foo.txt")
+		filePath := path.Join("non-existing-dir", "foo.txt")
 		err := testFS.Mkdir(filePath, fs.ModeDir)
 		require.EqualErrno(t, syscall.ENOENT, err)
 	})
@@ -137,7 +137,7 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		file1 := "file1"
-		file1Path := pathutil.Join(tmpDir, file1)
+		file1Path := path.Join(tmpDir, file1)
 		err := os.WriteFile(file1Path, []byte{1}, 0o600)
 		require.NoError(t, err)
 
@@ -149,13 +149,13 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		file1 := "file1"
-		file1Path := pathutil.Join(tmpDir, file1)
+		file1Path := path.Join(tmpDir, file1)
 		file1Contents := []byte{1}
 		err := os.WriteFile(file1Path, file1Contents, 0o600)
 		require.NoError(t, err)
 
 		file2 := "file2"
-		file2Path := pathutil.Join(tmpDir, file2)
+		file2Path := path.Join(tmpDir, file2)
 		err = testFS.Rename(file1, file2)
 		require.NoError(t, err)
 
@@ -172,11 +172,11 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		dir1 := "dir1"
-		dir1Path := pathutil.Join(tmpDir, dir1)
+		dir1Path := path.Join(tmpDir, dir1)
 		require.NoError(t, os.Mkdir(dir1Path, 0o700))
 
 		dir2 := "dir2"
-		dir2Path := pathutil.Join(tmpDir, dir2)
+		dir2Path := path.Join(tmpDir, dir2)
 		err := testFS.Rename(dir1, dir2)
 		require.NoError(t, err)
 
@@ -193,11 +193,11 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		dir1 := "dir1"
-		dir1Path := pathutil.Join(tmpDir, dir1)
+		dir1Path := path.Join(tmpDir, dir1)
 		require.NoError(t, os.Mkdir(dir1Path, 0o700))
 
 		dir2 := "dir2"
-		dir2Path := pathutil.Join(tmpDir, dir2)
+		dir2Path := path.Join(tmpDir, dir2)
 
 		// write a file to that path
 		f, err := os.OpenFile(dir2Path, os.O_RDWR|os.O_CREATE, 0o600)
@@ -212,13 +212,13 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		file1 := "file1"
-		file1Path := pathutil.Join(tmpDir, file1)
+		file1Path := path.Join(tmpDir, file1)
 		file1Contents := []byte{1}
 		err := os.WriteFile(file1Path, file1Contents, 0o600)
 		require.NoError(t, err)
 
 		dir1 := "dir1"
-		dir1Path := pathutil.Join(tmpDir, dir1)
+		dir1Path := path.Join(tmpDir, dir1)
 		require.NoError(t, os.Mkdir(dir1Path, 0o700))
 
 		err = testFS.Rename(file1, dir1)
@@ -231,18 +231,18 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		dir1 := "dir1"
-		dir1Path := pathutil.Join(tmpDir, dir1)
+		dir1Path := path.Join(tmpDir, dir1)
 		require.NoError(t, os.Mkdir(dir1Path, 0o700))
 
 		// add a file to that directory
 		file1 := "file1"
-		file1Path := pathutil.Join(dir1Path, file1)
+		file1Path := path.Join(dir1Path, file1)
 		file1Contents := []byte{1}
 		err := os.WriteFile(file1Path, file1Contents, 0o600)
 		require.NoError(t, err)
 
 		dir2 := "dir2"
-		dir2Path := pathutil.Join(tmpDir, dir2)
+		dir2Path := path.Join(tmpDir, dir2)
 		require.NoError(t, os.Mkdir(dir2Path, 0o700))
 
 		err = testFS.Rename(dir1, dir2)
@@ -253,7 +253,7 @@ func TestDirFS_Rename(t *testing.T) {
 		require.EqualErrno(t, syscall.ENOENT, platform.UnwrapOSError(err))
 
 		// Show the file inside that directory moved
-		s, err := os.Stat(pathutil.Join(dir2Path, file1))
+		s, err := os.Stat(path.Join(dir2Path, file1))
 		require.NoError(t, err)
 		require.False(t, s.IsDir())
 	})
@@ -264,22 +264,22 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		dir1 := "dir1"
-		dir1Path := pathutil.Join(tmpDir, dir1)
+		dir1Path := path.Join(tmpDir, dir1)
 		require.NoError(t, os.Mkdir(dir1Path, 0o700))
 
 		// add a file to that directory
 		file1 := "file1"
-		file1Path := pathutil.Join(dir1Path, file1)
+		file1Path := path.Join(dir1Path, file1)
 		file1Contents := []byte{1}
 		err := os.WriteFile(file1Path, file1Contents, 0o600)
 		require.NoError(t, err)
 
 		dir2 := "dir2"
-		dir2Path := pathutil.Join(tmpDir, dir2)
+		dir2Path := path.Join(tmpDir, dir2)
 		require.NoError(t, os.Mkdir(dir2Path, 0o700))
 
 		// Make the destination non-empty.
-		err = os.WriteFile(pathutil.Join(dir2Path, "existing.txt"), []byte("any thing"), 0o600)
+		err = os.WriteFile(path.Join(dir2Path, "existing.txt"), []byte("any thing"), 0o600)
 		require.NoError(t, err)
 
 		err = testFS.Rename(dir1, dir2)
@@ -291,13 +291,13 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		file1 := "file1"
-		file1Path := pathutil.Join(tmpDir, file1)
+		file1Path := path.Join(tmpDir, file1)
 		file1Contents := []byte{1}
 		err := os.WriteFile(file1Path, file1Contents, 0o600)
 		require.NoError(t, err)
 
 		file2 := "file2"
-		file2Path := pathutil.Join(tmpDir, file2)
+		file2Path := path.Join(tmpDir, file2)
 		file2Contents := []byte{2}
 		err = os.WriteFile(file2Path, file2Contents, 0o600)
 		require.NoError(t, err)
@@ -319,7 +319,7 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		dir1 := "dir1"
-		dir1Path := pathutil.Join(tmpDir, dir1)
+		dir1Path := path.Join(tmpDir, dir1)
 		require.NoError(t, os.Mkdir(dir1Path, 0o700))
 
 		err := testFS.Rename(dir1, dir1)
@@ -334,7 +334,7 @@ func TestDirFS_Rename(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		file1 := "file1"
-		file1Path := pathutil.Join(tmpDir, file1)
+		file1Path := path.Join(tmpDir, file1)
 		file1Contents := []byte{1}
 		err := os.WriteFile(file1Path, file1Contents, 0o600)
 		require.NoError(t, err)
@@ -364,10 +364,10 @@ func TestDirFS_Rmdir(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		name := "rmdir"
-		realPath := pathutil.Join(tmpDir, name)
+		realPath := path.Join(tmpDir, name)
 
 		require.NoError(t, os.Mkdir(realPath, 0o700))
-		fileInDir := pathutil.Join(realPath, "file")
+		fileInDir := path.Join(realPath, "file")
 		require.NoError(t, os.WriteFile(fileInDir, []byte{}, 0o600))
 
 		err := testFS.Rmdir(name)
@@ -381,11 +381,11 @@ func TestDirFS_Rmdir(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		name := "rmdir"
-		realPath := pathutil.Join(tmpDir, name)
+		realPath := path.Join(tmpDir, name)
 		require.NoError(t, os.Mkdir(realPath, 0o700))
 
 		// Create a file and then delete it.
-		fileInDir := pathutil.Join(realPath, "file")
+		fileInDir := path.Join(realPath, "file")
 		require.NoError(t, os.WriteFile(fileInDir, []byte{}, 0o600))
 		require.NoError(t, os.Remove(fileInDir))
 
@@ -399,7 +399,7 @@ func TestDirFS_Rmdir(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		name := "rmdir"
-		realPath := pathutil.Join(tmpDir, name)
+		realPath := path.Join(tmpDir, name)
 		require.NoError(t, os.Mkdir(realPath, 0o700))
 		require.NoError(t, testFS.Rmdir(name))
 		_, err := os.Stat(realPath)
@@ -411,7 +411,7 @@ func TestDirFS_Rmdir(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		name := "rmdir"
-		realPath := pathutil.Join(tmpDir, name)
+		realPath := path.Join(tmpDir, name)
 		require.NoError(t, os.Mkdir(realPath, 0o700))
 
 		f, err := testFS.OpenFile(name, platform.O_DIRECTORY, 0o700)
@@ -430,7 +430,7 @@ func TestDirFS_Rmdir(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		name := "rmdir"
-		realPath := pathutil.Join(tmpDir, name)
+		realPath := path.Join(tmpDir, name)
 
 		require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
 
@@ -456,7 +456,7 @@ func TestDirFS_Unlink(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		dir := "dir"
-		realPath := pathutil.Join(tmpDir, dir)
+		realPath := path.Join(tmpDir, dir)
 
 		require.NoError(t, os.Mkdir(realPath, 0o700))
 
@@ -472,7 +472,7 @@ func TestDirFS_Unlink(t *testing.T) {
 
 		// Create link target dir.
 		subDirName := "subdir"
-		subDirRealPath := pathutil.Join(tmpDir, subDirName)
+		subDirRealPath := path.Join(tmpDir, subDirName)
 		require.NoError(t, os.Mkdir(subDirRealPath, 0o700))
 
 		// Create a symlink to the subdirectory.
@@ -489,7 +489,7 @@ func TestDirFS_Unlink(t *testing.T) {
 		testFS := NewDirFS(tmpDir)
 
 		name := "unlink"
-		realPath := pathutil.Join(tmpDir, name)
+		realPath := path.Join(tmpDir, name)
 
 		require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
 
@@ -504,11 +504,11 @@ func TestDirFS_Utimesns(t *testing.T) {
 	testFS := NewDirFS(tmpDir)
 
 	file := "file"
-	err := os.WriteFile(pathutil.Join(tmpDir, file), []byte{}, 0o700)
+	err := os.WriteFile(path.Join(tmpDir, file), []byte{}, 0o700)
 	require.NoError(t, err)
 
 	dir := "dir"
-	err = os.Mkdir(pathutil.Join(tmpDir, dir), 0o700)
+	err = os.Mkdir(path.Join(tmpDir, dir), 0o700)
 	require.NoError(t, err)
 
 	t.Run("doesn't exist", func(t *testing.T) {
@@ -595,14 +595,14 @@ func TestDirFS_Utimesns(t *testing.T) {
 				tmpDir := t.TempDir()
 				testFS := NewDirFS(tmpDir)
 
-				file := pathutil.Join(tmpDir, "file")
+				file := path.Join(tmpDir, "file")
 				err := os.WriteFile(file, []byte{}, 0o700)
 				require.NoError(t, err)
 
 				link := file + "-link"
 				require.NoError(t, os.Symlink(file, link))
 
-				dir := pathutil.Join(tmpDir, "dir")
+				dir := path.Join(tmpDir, "dir")
 				err = os.Mkdir(dir, 0o700)
 				require.NoError(t, err)
 
@@ -666,7 +666,7 @@ func TestDirFS_OpenFile(t *testing.T) {
 	tmpDir := t.TempDir()
 
 	// Create a subdirectory, so we can test reads outside the FS root.
-	tmpDir = pathutil.Join(tmpDir, t.Name())
+	tmpDir = path.Join(tmpDir, t.Name())
 	require.NoError(t, os.Mkdir(tmpDir, 0o700))
 	require.NoError(t, fstest.WriteTestFiles(tmpDir))
 
@@ -730,7 +730,7 @@ func TestDirFS_Truncate(t *testing.T) {
 			testFS := NewDirFS(tmpDir)
 
 			name := "truncate"
-			realPath := pathutil.Join(tmpDir, name)
+			realPath := path.Join(tmpDir, name)
 			require.NoError(t, os.WriteFile(realPath, content, 0o0600))
 
 			err := testFS.Truncate(name, tc.size)
@@ -746,7 +746,7 @@ func TestDirFS_Truncate(t *testing.T) {
 	testFS := NewDirFS(tmpDir)
 
 	name := "truncate"
-	realPath := pathutil.Join(tmpDir, name)
+	realPath := path.Join(tmpDir, name)
 
 	if runtime.GOOS != "windows" {
 		// TODO: os.Truncate on windows can create the file even when it
@@ -805,7 +805,7 @@ func Test_fdReaddir_opened_file_written(t *testing.T) {
 	defer dirFile.Close()
 
 	// Then write a file to the directory.
-	f, err := os.Create(pathutil.Join(root, readDirTarget, "my-file"))
+	f, err := os.Create(path.Join(root, readDirTarget, "my-file"))
 	require.NoError(t, err)
 	defer f.Close()
 
@@ -850,12 +850,12 @@ func TestDirFS_Symlink(t *testing.T) {
 	require.NoError(t, testFS.Symlink("non-existing", "aa"))
 	require.NoError(t, testFS.Symlink("sub/", "symlinked-subdir"))
 
-	st, err := os.Lstat(pathutil.Join(tmpDir, "aa"))
+	st, err := os.Lstat(path.Join(tmpDir, "aa"))
 	require.NoError(t, err)
 	require.Equal(t, "aa", st.Name())
 	require.True(t, st.Mode()&fs.ModeSymlink > 0 && !st.IsDir())
 
-	st, err = os.Lstat(pathutil.Join(tmpDir, "symlinked-subdir"))
+	st, err = os.Lstat(path.Join(tmpDir, "symlinked-subdir"))
 	require.NoError(t, err)
 	require.Equal(t, "symlinked-subdir", st.Name())
 	require.True(t, st.Mode()&fs.ModeSymlink > 0)
diff --git a/internal/sysfs/readfs_test.go b/internal/sysfs/readfs_test.go
index 518b19d5..5bd29918 100644
--- a/internal/sysfs/readfs_test.go
+++ b/internal/sysfs/readfs_test.go
@@ -3,7 +3,6 @@ package sysfs
 import (
 	"io/fs"
 	"os"
-	pathutil "path"
 	"runtime"
 	"syscall"
 	"testing"
@@ -72,13 +71,13 @@ func TestReadFS_Rename(t *testing.T) {
 	testFS := NewReadFS(writeable)
 
 	file1 := "file1"
-	file1Path := pathutil.Join(tmpDir, file1)
+	file1Path := joinPath(tmpDir, file1)
 	file1Contents := []byte{1}
 	err := os.WriteFile(file1Path, file1Contents, 0o600)
 	require.NoError(t, err)
 
 	file2 := "file2"
-	file2Path := pathutil.Join(tmpDir, file2)
+	file2Path := joinPath(tmpDir, file2)
 	file2Contents := []byte{2}
 	err = os.WriteFile(file2Path, file2Contents, 0o600)
 	require.NoError(t, err)
@@ -93,7 +92,7 @@ func TestReadFS_Rmdir(t *testing.T) {
 	testFS := NewReadFS(writeable)
 
 	path := "rmdir"
-	realPath := pathutil.Join(tmpDir, path)
+	realPath := joinPath(tmpDir, path)
 	require.NoError(t, os.Mkdir(realPath, 0o700))
 
 	err := testFS.Rmdir(path)
@@ -106,7 +105,7 @@ func TestReadFS_Unlink(t *testing.T) {
 	testFS := NewReadFS(writeable)
 
 	path := "unlink"
-	realPath := pathutil.Join(tmpDir, path)
+	realPath := joinPath(tmpDir, path)
 	require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
 
 	err := testFS.Unlink(path)
@@ -119,7 +118,7 @@ func TestReadFS_UtimesNano(t *testing.T) {
 	testFS := NewReadFS(writeable)
 
 	path := "utimes"
-	realPath := pathutil.Join(tmpDir, path)
+	realPath := joinPath(tmpDir, path)
 	require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
 
 	err := testFS.Utimens(path, nil, true)
diff --git a/internal/sysfs/rootfs_test.go b/internal/sysfs/rootfs_test.go
index 1e6390ed..744d00b9 100644
--- a/internal/sysfs/rootfs_test.go
+++ b/internal/sysfs/rootfs_test.go
@@ -5,7 +5,7 @@ import (
 	"io"
 	"io/fs"
 	"os"
-	pathutil "path"
+	"path"
 	"sort"
 	"strings"
 	"syscall"
@@ -76,12 +76,12 @@ func TestNewRootFS(t *testing.T) {
 	t.Run("multiple matches", func(t *testing.T) {
 		tmpDir1 := t.TempDir()
 		testFS1 := NewDirFS(tmpDir1)
-		require.NoError(t, os.Mkdir(pathutil.Join(tmpDir1, "tmp"), 0o700))
-		require.NoError(t, os.WriteFile(pathutil.Join(tmpDir1, "a"), []byte{1}, 0o600))
+		require.NoError(t, os.Mkdir(path.Join(tmpDir1, "tmp"), 0o700))
+		require.NoError(t, os.WriteFile(path.Join(tmpDir1, "a"), []byte{1}, 0o600))
 
 		tmpDir2 := t.TempDir()
 		testFS2 := NewDirFS(tmpDir2)
-		require.NoError(t, os.WriteFile(pathutil.Join(tmpDir2, "a"), []byte{2}, 0o600))
+		require.NoError(t, os.WriteFile(path.Join(tmpDir2, "a"), []byte{2}, 0o600))
 
 		rootFS, err := NewRootFS([]FS{testFS2, testFS1}, []string{"/tmp", "/"})
 		require.NoError(t, err)
@@ -135,7 +135,7 @@ func TestRootFS_Open(t *testing.T) {
 	tmpDir := t.TempDir()
 
 	// Create a subdirectory, so we can test reads outside the FS root.
-	tmpDir = pathutil.Join(tmpDir, t.Name())
+	tmpDir = path.Join(tmpDir, t.Name())
 	require.NoError(t, os.Mkdir(tmpDir, 0o700))
 	require.NoError(t, fstest.WriteTestFiles(tmpDir))
 
@@ -175,13 +175,13 @@ func TestRootFS_TestFS(t *testing.T) {
 
 	// move one directory outside the other
 	tmpDir2 := t.TempDir()
-	require.NoError(t, os.Rename(pathutil.Join(tmpDir1, "dir"), pathutil.Join(tmpDir2, "dir")))
+	require.NoError(t, os.Rename(path.Join(tmpDir1, "dir"), path.Join(tmpDir2, "dir")))
 
 	// Create a root mount
 	testFS1 := NewDirFS(tmpDir1)
 
 	// Create a dir mount
-	testFS2 := NewDirFS(pathutil.Join(tmpDir2, "dir"))
+	testFS2 := NewDirFS(path.Join(tmpDir2, "dir"))
 
 	testFS, err := NewRootFS([]FS{testFS1, testFS2}, []string{"/", "/dir"})
 	require.NoError(t, err)
diff --git a/internal/sysfs/sysfs_test.go b/internal/sysfs/sysfs_test.go
index 0f7ed744..279f5fba 100644
--- a/internal/sysfs/sysfs_test.go
+++ b/internal/sysfs/sysfs_test.go
@@ -713,3 +713,9 @@ func requireIno(t *testing.T, dirents []*platform.Dirent, expectIno bool) {
 		}
 	}
 }
+
+// joinPath avoids us having to rename fields just to avoid conflict with the
+// path package.
+func joinPath(dirName, baseName string) string {
+	return path.Join(dirName, baseName)
+}