diff --git a/cmd/wazero/wazero.go b/cmd/wazero/wazero.go index 2c66d85534..7866a01372 100644 --- a/cmd/wazero/wazero.go +++ b/cmd/wazero/wazero.go @@ -21,6 +21,7 @@ import ( "github.com/tetratelabs/wazero/experimental/gojs" "github.com/tetratelabs/wazero/experimental/logging" "github.com/tetratelabs/wazero/experimental/sock" + "github.com/tetratelabs/wazero/experimental/sysfs" "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" "github.com/tetratelabs/wazero/internal/platform" internalsys "github.com/tetratelabs/wazero/internal/sys" @@ -394,7 +395,7 @@ func validateMounts(mounts sliceFlag, stdErr logging.Writer) (rc int, rootPath s readOnly = true } - // TODO(anuraaga): Support wasm paths with colon in them. + // TODO: Support wasm paths with colon in them. var dir, guestPath string if clnIdx := strings.LastIndexByte(mount, ':'); clnIdx != -1 { dir, guestPath = mount[:clnIdx], mount[clnIdx+1:] @@ -418,12 +419,13 @@ func validateMounts(mounts sliceFlag, stdErr logging.Writer) (rc int, rootPath s fmt.Fprintf(stdErr, "invalid mount: path %q is not a directory\n", dir) } + root := sysfs.NewDirFS(dir) if readOnly { - config = config.WithReadOnlyDirMount(dir, guestPath) - } else { - config = config.WithDirMount(dir, guestPath) + root = sysfs.NewReadFS(root) } + config = config.(sysfs.FSConfig).WithSysFSMount(root, guestPath) + if internalsys.StripPrefixesAndTrailingSlash(guestPath) == "" { rootPath = dir } diff --git a/config.go b/config.go index 8fcfb5fa2b..70219b055f 100644 --- a/config.go +++ b/config.go @@ -11,10 +11,10 @@ import ( "time" "github.com/tetratelabs/wazero/api" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/internal/engine/compiler" "github.com/tetratelabs/wazero/internal/engine/interpreter" "github.com/tetratelabs/wazero/internal/filecache" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/internalapi" "github.com/tetratelabs/wazero/internal/platform" internalsock "github.com/tetratelabs/wazero/internal/sock" @@ -846,7 +846,7 @@ func (c *moduleConfig) toSysContext() (sysCtx *internalsys.Context, err error) { environ = append(environ, result) } - var fs []fsapi.FS + var fs []experimentalsys.FS var guestPaths []string if f, ok := c.fsConfig.(*fsConfig); ok { fs, guestPaths = f.preopens() diff --git a/internal/fsapi/dir.go b/experimental/sys/dir.go similarity index 68% rename from internal/fsapi/dir.go rename to experimental/sys/dir.go index 32cfc56f4b..047e5daab4 100644 --- a/internal/fsapi/dir.go +++ b/experimental/sys/dir.go @@ -1,10 +1,9 @@ -package fsapi +package sys import ( "fmt" "io/fs" - experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/sys" ) @@ -21,7 +20,7 @@ type FileType = fs.FileMode // - This extends `dirent` defined in POSIX with some fields defined by // Linux. See https://man7.org/linux/man-pages/man3/readdir.3.html and // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/dirent.h.html -// - This has a subset of fields defined in Stat_t. Notably, there is no +// - This has a subset of fields defined in sys.Stat_t. Notably, there is no // field corresponding to Stat_t.Dev because that value will be constant // for all files in a directory. To get the Dev value, call File.Stat on // the directory File.Readdir was called on. @@ -58,8 +57,8 @@ func (DirFile) IsAppend() bool { } // SetAppend implements File.SetAppend -func (DirFile) SetAppend(bool) experimentalsys.Errno { - return experimentalsys.EISDIR +func (DirFile) SetAppend(bool) Errno { + return EISDIR } // IsNonblock implements File.IsNonblock @@ -68,41 +67,41 @@ func (DirFile) IsNonblock() bool { } // SetNonblock implements File.SetNonblock -func (DirFile) SetNonblock(bool) experimentalsys.Errno { - return experimentalsys.EISDIR +func (DirFile) SetNonblock(bool) Errno { + return EISDIR } // IsDir implements File.IsDir -func (DirFile) IsDir() (bool, experimentalsys.Errno) { +func (DirFile) IsDir() (bool, Errno) { return true, 0 } // Read implements File.Read -func (DirFile) Read([]byte) (int, experimentalsys.Errno) { - return 0, experimentalsys.EISDIR +func (DirFile) Read([]byte) (int, Errno) { + return 0, EISDIR } // Pread implements File.Pread -func (DirFile) Pread([]byte, int64) (int, experimentalsys.Errno) { - return 0, experimentalsys.EISDIR +func (DirFile) Pread([]byte, int64) (int, Errno) { + return 0, EISDIR } // Poll implements File.Poll -func (DirFile) Poll(Pflag, int32) (ready bool, errno experimentalsys.Errno) { - return false, experimentalsys.ENOSYS +func (DirFile) Poll(Pflag, int32) (ready bool, errno Errno) { + return false, ENOSYS } // Write implements File.Write -func (DirFile) Write([]byte) (int, experimentalsys.Errno) { - return 0, experimentalsys.EISDIR +func (DirFile) Write([]byte) (int, Errno) { + return 0, EISDIR } // Pwrite implements File.Pwrite -func (DirFile) Pwrite([]byte, int64) (int, experimentalsys.Errno) { - return 0, experimentalsys.EISDIR +func (DirFile) Pwrite([]byte, int64) (int, Errno) { + return 0, EISDIR } // Truncate implements File.Truncate -func (DirFile) Truncate(int64) experimentalsys.Errno { - return experimentalsys.EISDIR +func (DirFile) Truncate(int64) Errno { + return EISDIR } diff --git a/internal/fsapi/file.go b/experimental/sys/file.go similarity index 68% rename from internal/fsapi/file.go rename to experimental/sys/file.go index 0c50175d45..d1abfc6a46 100644 --- a/internal/fsapi/file.go +++ b/experimental/sys/file.go @@ -1,9 +1,6 @@ -package fsapi +package sys -import ( - experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/sys" -) +import "github.com/tetratelabs/wazero/sys" // File is a writeable fs.File bridge backed by syscall functions needed for ABI // including WASI and runtime.GOOS=js. @@ -13,10 +10,10 @@ import ( // // # Errors // -// All methods that can return an error return a sys.Errno, which is zero +// All methods that can return an error return a Errno, which is zero // on success. // -// Restricting to sys.Errno matches current WebAssembly host functions, +// Restricting to Errno matches current WebAssembly host functions, // which are constrained to well-known error codes. For example, `GOOS=js` maps // hard coded values and panics otherwise. More commonly, WASI maps syscall // errors to u32 numeric values. @@ -41,7 +38,7 @@ type File interface { // // - Implementations should cache this result. // - This combined with Ino can implement os.SameFile. - Dev() (uint64, experimentalsys.Errno) + Dev() (uint64, Errno) // Ino returns the serial number (Stat_t.Ino) of this file, zero if unknown // or an error retrieving it. @@ -55,7 +52,7 @@ type File interface { // // - Implementations should cache this result. // - This combined with Dev can implement os.SameFile. - Ino() (sys.Inode, experimentalsys.Errno) + Ino() (sys.Inode, Errno) // IsDir returns true if this file is a directory or an error there was an // error retrieving this information. @@ -68,7 +65,7 @@ type File interface { // # Notes // // - Implementations should cache this result. - IsDir() (bool, experimentalsys.Errno) + IsDir() (bool, Errno) // IsNonblock returns true if the file was opened with O_NONBLOCK, or // SetNonblock was successfully enabled on this file. @@ -83,17 +80,17 @@ type File interface { // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. // // # Notes // // - This is like syscall.SetNonblock and `fcntl` with O_NONBLOCK in // POSIX. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html - SetNonblock(enable bool) experimentalsys.Errno + SetNonblock(enable bool) Errno - // IsAppend returns true if the file was opened with fsapi.O_APPEND, or + // IsAppend returns true if the file was opened with O_APPEND, or // SetAppend was successfully enabled on this file. // // # Notes @@ -102,28 +99,28 @@ type File interface { // the file was not opened via OpenFile. IsAppend() bool - // SetAppend toggles the append mode (fsapi.O_APPEND) of this file. + // SetAppend toggles the append mode (O_APPEND) of this file. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. // // # Notes // // - There is no `O_APPEND` for `fcntl` in POSIX, so implementations may // have to re-open the underlying file to apply this. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html - SetAppend(enable bool) experimentalsys.Errno + SetAppend(enable bool) Errno // Stat is similar to syscall.Fstat. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. // // # Notes // @@ -132,17 +129,17 @@ type File interface { // - A fs.FileInfo backed implementation sets atim, mtim and ctim to the // same value. // - Windows allows you to stat a closed directory. - Stat() (sys.Stat_t, experimentalsys.Errno) + Stat() (sys.Stat_t, Errno) // Read attempts to read all bytes in the file into `buf`, and returns the // count read even on error. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed or not readable. - // - sys.EISDIR: the file was a directory. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed or not readable. + // - EISDIR: the file was a directory. // // # Notes // @@ -150,18 +147,18 @@ type File interface { // io.Reader. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html // - Unlike io.Reader, there is no io.EOF returned on end-of-file. To // read the file completely, the caller must repeat until `n` is zero. - Read(buf []byte) (n int, errno experimentalsys.Errno) + Read(buf []byte) (n int, errno Errno) // Pread attempts to read all bytes in the file into `p`, starting at the // offset `off`, and returns the count read even on error. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed or not readable. - // - sys.EINVAL: the offset was negative. - // - sys.EISDIR: the file was a directory. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed or not readable. + // - EINVAL: the offset was negative. + // - EISDIR: the file was a directory. // // # Notes // @@ -169,7 +166,7 @@ type File interface { // of io.ReaderAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html // - Unlike io.ReaderAt, there is no io.EOF returned on end-of-file. To // read the file completely, the caller must repeat until `n` is zero. - Pread(buf []byte, off int64) (n int, errno experimentalsys.Errno) + Pread(buf []byte, off int64) (n int, errno Errno) // Seek attempts to set the next offset for Read or Write and returns the // resulting absolute offset or an error. @@ -192,16 +189,16 @@ type File interface { // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed or not readable. - // - sys.EINVAL: the offset was negative. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed or not readable. + // - EINVAL: the offset was negative. // // # Notes // // - This is like io.Seeker and `fseek` in POSIX, preferring semantics // of io.Seeker. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fseek.html - Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) + Seek(offset int64, whence int) (newOffset int64, errno Errno) // Poll returns if the file has data ready to be read or written. // @@ -221,9 +218,9 @@ type File interface { // event was ready or `errno` is not zero. // // A zero `errno` is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.ENOTSUP: the implementation does not the flag combination. - // - sys.EINTR: the call was interrupted prior to an event. + // - ENOSYS: the implementation does not support this function. + // - ENOTSUP: the implementation does not the flag combination. + // - EINTR: the call was interrupted prior to an event. // // # Notes // @@ -232,7 +229,7 @@ type File interface { // - No-op files, such as those which read from /dev/null, should return // immediately true, as data will never become available. // - See /RATIONALE.md for detailed notes including impact of blocking. - Poll(flag Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) + Poll(flag Pflag, timeoutMillis int32) (ready bool, errno Errno) // Readdir reads the contents of the directory associated with file and // returns a slice of up to n Dirent values in an arbitrary order. This is @@ -243,10 +240,10 @@ type File interface { // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file was closed or not a directory. - // - sys.ENOENT: the directory could not be read (e.g. deleted). + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file was closed or not a directory. + // - ENOENT: the directory could not be read (e.g. deleted). // // # Notes // @@ -256,63 +253,63 @@ type File interface { // read the directory completely, the caller must repeat until the // count read (`len(dirents)`) is less than `n`. // - See /RATIONALE.md for design notes. - Readdir(n int) (dirents []Dirent, errno experimentalsys.Errno) + Readdir(n int) (dirents []Dirent, errno Errno) // Write attempts to write all bytes in `p` to the file, and returns the // count written even on error. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file was closed, not writeable, or a directory. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file was closed, not writeable, or a directory. // // # Notes // // - This is like io.Writer and `write` in POSIX, preferring semantics of // io.Writer. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html - Write(buf []byte) (n int, errno experimentalsys.Errno) + Write(buf []byte) (n int, errno Errno) // Pwrite attempts to write all bytes in `p` to the file at the given // offset `off`, and returns the count written even on error. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed or not writeable. - // - sys.EINVAL: the offset was negative. - // - sys.EISDIR: the file was a directory. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed or not writeable. + // - EINVAL: the offset was negative. + // - EISDIR: the file was a directory. // // # Notes // // - This is like io.WriterAt and `pwrite` in POSIX, preferring semantics // of io.WriterAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html - Pwrite(buf []byte, off int64) (n int, errno experimentalsys.Errno) + Pwrite(buf []byte, off int64) (n int, errno Errno) // Truncate truncates a file to a specified length. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed. - // - sys.EINVAL: the `size` is negative. - // - sys.EISDIR: the file was a directory. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. + // - EINVAL: the `size` is negative. + // - EISDIR: the file was a directory. // // # Notes // // - This is like syscall.Ftruncate and `ftruncate` in POSIX. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html // - Windows does not error when calling Truncate on a closed file. - Truncate(size int64) experimentalsys.Errno + Truncate(size int64) Errno // Sync synchronizes changes to the file. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.EBADF: the file or directory was closed. + // A zero Errno is success. The below are expected otherwise: + // - EBADF: the file or directory was closed. // // # Notes // @@ -321,14 +318,14 @@ type File interface { // - This returns with no error instead of ENOSYS when // unimplemented. This prevents fake filesystems from erring. // - Windows does not error when calling Sync on a closed file. - Sync() experimentalsys.Errno + Sync() Errno // Datasync synchronizes the data of a file. // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.EBADF: the file or directory was closed. + // A zero Errno is success. The below are expected otherwise: + // - EBADF: the file or directory was closed. // // # Notes // @@ -337,7 +334,7 @@ type File interface { // - This returns with no error instead of ENOSYS when // unimplemented. This prevents fake filesystems from erring. // - As this is commonly missing, some implementations dispatch to Sync. - Datasync() experimentalsys.Errno + Datasync() Errno // Utimens set file access and modification times of this file, at // nanosecond precision. @@ -350,25 +347,25 @@ type File interface { // // # Errors // - // A zero sys.Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EBADF: the file or directory was closed. + // A zero Errno is success. The below are expected otherwise: + // - ENOSYS: the implementation does not support this function. + // - EBADF: the file or directory was closed. // // # Notes // // - This is like syscall.UtimesNano and `futimens` in POSIX. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html - // - Windows requires files to be open with fsapi.O_RDWR, which means you + // - Windows requires files to be open with O_RDWR, which means you // cannot use this to update timestamps on a directory (EPERM). - Utimens(atim, mtim int64) experimentalsys.Errno + Utimens(atim, mtim int64) Errno // Close closes the underlying file. // - // A zero sys.Errno is returned if unimplemented or success. + // A zero Errno is returned if unimplemented or success. // // # Notes // // - This is like syscall.Close and `close` in POSIX. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html - Close() experimentalsys.Errno + Close() Errno } diff --git a/internal/fsapi/fs.go b/experimental/sys/fs.go similarity index 71% rename from internal/fsapi/fs.go rename to experimental/sys/fs.go index 0b0d6790b2..1ce99cef18 100644 --- a/internal/fsapi/fs.go +++ b/experimental/sys/fs.go @@ -1,9 +1,8 @@ -package fsapi +package sys import ( "io/fs" - experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/sys" ) @@ -33,11 +32,11 @@ type FS interface { // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EINVAL: `path` or `flag` is invalid. - // - sys.EISDIR: the path was a directory, but flag included O_RDWR or + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` or `flag` is invalid. + // - EISDIR: the path was a directory, but flag included O_RDWR or // O_WRONLY - // - sys.ENOENT: `path` doesn't exist and `flag` doesn't contain O_CREAT. + // - ENOENT: `path` doesn't exist and `flag` doesn't contain O_CREAT. // // # Constraints on the returned file // @@ -58,15 +57,15 @@ type FS interface { // - Implications of permissions when O_CREAT are described in Chmod notes. // - This is like `open` in POSIX. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html - OpenFile(path string, flag Oflag, perm fs.FileMode) (File, experimentalsys.Errno) + OpenFile(path string, flag Oflag, perm fs.FileMode) (File, Errno) // Lstat gets file status without following symbolic links. // // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.ENOENT: `path` doesn't exist. + // - ENOSYS: the implementation does not support this function. + // - ENOENT: `path` doesn't exist. // // # Notes // @@ -78,15 +77,15 @@ type FS interface { // same value. // - When the path is a symbolic link, the stat returned is for the link, // not the file it refers to. - Lstat(path string) (sys.Stat_t, experimentalsys.Errno) + Lstat(path string) (sys.Stat_t, Errno) // Stat gets file status. // // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.ENOENT: `path` doesn't exist. + // - ENOSYS: the implementation does not support this function. + // - ENOENT: `path` doesn't exist. // // # Notes // @@ -98,17 +97,17 @@ type FS interface { // same value. // - When the path is a symbolic link, the stat returned is for the file // it refers to. - Stat(path string) (sys.Stat_t, experimentalsys.Errno) + Stat(path string) (sys.Stat_t, Errno) // Mkdir makes a directory. // // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EINVAL: `path` is invalid. - // - sys.EEXIST: `path` exists and is a directory. - // - sys.ENOTDIR: `path` exists and is a file. + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - EEXIST: `path` exists and is a directory. + // - ENOTDIR: `path` exists and is a file. // // # Notes // @@ -117,16 +116,16 @@ type FS interface { // - This is like `mkdir` in POSIX. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html // - Implications of permissions are described in Chmod notes. - Mkdir(path string, perm fs.FileMode) experimentalsys.Errno + Mkdir(path string, perm fs.FileMode) Errno // Chmod changes the mode of the file. // // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EINVAL: `path` is invalid. - // - sys.ENOENT: `path` does not exist. + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - ENOENT: `path` does not exist. // // # Notes // @@ -137,19 +136,19 @@ type FS interface { // - Windows ignores the execute bit, and any permissions come back as // group and world. For example, chmod of 0400 reads back as 0444, and // 0700 0666. Also, permissions on directories aren't supported at all. - Chmod(path string, perm fs.FileMode) experimentalsys.Errno + Chmod(path string, perm fs.FileMode) Errno // Rename renames file or directory. // // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EINVAL: `from` or `to` is invalid. - // - sys.ENOENT: `from` or `to` don't exist. - // - sys.ENOTDIR: `from` is a directory and `to` exists as a file. - // - sys.EISDIR: `from` is a file and `to` exists as a directory. - // - sys.ENOTEMPTY: `both from` and `to` are existing directory, but + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `from` or `to` is invalid. + // - ENOENT: `from` or `to` don't exist. + // - ENOTDIR: `from` is a directory and `to` exists as a file. + // - EISDIR: `from` is a file and `to` exists as a directory. + // - ENOTEMPTY: `both from` and `to` are existing directory, but // `to` is not empty. // // # Notes @@ -159,18 +158,18 @@ type FS interface { // - This is like `rename` in POSIX. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html // - Windows doesn't let you overwrite an existing directory. - Rename(from, to string) experimentalsys.Errno + Rename(from, to string) Errno // Rmdir removes a directory. // // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EINVAL: `path` is invalid. - // - sys.ENOENT: `path` doesn't exist. - // - sys.ENOTDIR: `path` exists, but isn't a directory. - // - sys.ENOTEMPTY: `path` exists, but isn't empty. + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - ENOENT: `path` doesn't exist. + // - ENOTDIR: `path` exists, but isn't a directory. + // - ENOTEMPTY: `path` exists, but isn't empty. // // # Notes // @@ -178,18 +177,18 @@ type FS interface { // file system. // - This is like `rmdir` in POSIX. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html - // - As of Go 1.19, Windows maps sys.ENOTDIR to sys.ENOENT. - Rmdir(path string) experimentalsys.Errno + // - As of Go 1.19, Windows maps ENOTDIR to ENOENT. + Rmdir(path string) Errno // Unlink removes a directory entry. // // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EINVAL: `path` is invalid. - // - sys.ENOENT: `path` doesn't exist. - // - sys.EISDIR: `path` exists, but is a directory. + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - ENOENT: `path` doesn't exist. + // - EISDIR: `path` exists, but is a directory. // // # Notes // @@ -200,7 +199,7 @@ type FS interface { // - On Windows, syscall.Unlink doesn't delete symlink to directory unlike other platforms. Implementations might // want to combine syscall.RemoveDirectory with syscall.Unlink in order to delete such links on Windows. // See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya - Unlink(path string) experimentalsys.Errno + Unlink(path string) Errno // Link creates a "hard" link from oldPath to newPath, in contrast to a // soft link (via Symlink). @@ -208,10 +207,10 @@ type FS interface { // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EPERM: `oldPath` is invalid. - // - sys.ENOENT: `oldPath` doesn't exist. - // - sys.EISDIR: `newPath` exists, but is a directory. + // - ENOSYS: the implementation does not support this function. + // - EPERM: `oldPath` is invalid. + // - ENOENT: `oldPath` doesn't exist. + // - EISDIR: `newPath` exists, but is a directory. // // # Notes // @@ -219,7 +218,7 @@ type FS interface { // file system. // - This is like `link` in POSIX. See // https://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html - Link(oldPath, newPath string) experimentalsys.Errno + Link(oldPath, newPath string) Errno // Symlink creates a "soft" link from oldPath to newPath, in contrast to a // hard link (via Link). @@ -227,9 +226,9 @@ type FS interface { // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EPERM: `oldPath` or `newPath` is invalid. - // - sys.EEXIST: `newPath` exists. + // - ENOSYS: the implementation does not support this function. + // - EPERM: `oldPath` or `newPath` is invalid. + // - EEXIST: `newPath` exists. // // # Notes // @@ -243,17 +242,17 @@ type FS interface { // See https://github.com/bytecodealliance/cap-std/blob/v1.0.4/cap-std/src/fs/dir.rs#L404-L409 // for how others implement this. // - Symlinks in Windows requires `SeCreateSymbolicLinkPrivilege`. - // Otherwise, sys.EPERM results. + // Otherwise, EPERM results. // See https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links - Symlink(oldPath, linkName string) experimentalsys.Errno + Symlink(oldPath, linkName string) Errno // Readlink reads the contents of a symbolic link. // // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EINVAL: `path` is invalid. + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. // // # Notes // @@ -264,7 +263,7 @@ type FS interface { // - On Windows, the path separator is different from other platforms, // but to provide consistent results to Wasm, this normalizes to a "/" // separator. - Readlink(path string) (string, experimentalsys.Errno) + Readlink(path string) (string, Errno) // Utimens set file access and modification times on a path relative to // this file system, at nanosecond precision. @@ -281,14 +280,14 @@ type FS interface { // # Errors // // A zero Errno is success. The below are expected otherwise: - // - sys.ENOSYS: the implementation does not support this function. - // - sys.EINVAL: `path` is invalid. - // - sys.EEXIST: `path` exists and is a directory. - // - sys.ENOTDIR: `path` exists and is a file. + // - ENOSYS: the implementation does not support this function. + // - EINVAL: `path` is invalid. + // - EEXIST: `path` exists and is a directory. + // - ENOTDIR: `path` exists and is a file. // // # Notes // // - This is like syscall.UtimesNano and `utimensat` with `AT_FDCWD` in // POSIX. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html - Utimens(path string, atim, mtim int64) experimentalsys.Errno + Utimens(path string, atim, mtim int64) Errno } diff --git a/internal/fsapi/oflag.go b/experimental/sys/oflag.go similarity index 99% rename from internal/fsapi/oflag.go rename to experimental/sys/oflag.go index eac4fc9874..39ebd378f6 100644 --- a/internal/fsapi/oflag.go +++ b/experimental/sys/oflag.go @@ -1,4 +1,4 @@ -package fsapi +package sys // Oflag are flags used for FS.OpenFile. Values, including zero, should not be // interpreted numerically. Instead, use by constants prefixed with 'O_' with diff --git a/internal/fsapi/poll.go b/experimental/sys/poll.go similarity index 97% rename from internal/fsapi/poll.go rename to experimental/sys/poll.go index 25f7c5711b..c63e55b958 100644 --- a/internal/fsapi/poll.go +++ b/experimental/sys/poll.go @@ -1,4 +1,4 @@ -package fsapi +package sys // Pflag are bit flags used for File.Poll. Values, including zero, should not // be interpreted numerically. Instead, use by constants prefixed with 'POLL'. diff --git a/internal/fsapi/time.go b/experimental/sys/time.go similarity index 95% rename from internal/fsapi/time.go rename to experimental/sys/time.go index 1cfcea5d95..4f3e01fefb 100644 --- a/internal/fsapi/time.go +++ b/experimental/sys/time.go @@ -1,4 +1,4 @@ -package fsapi +package sys import "math" diff --git a/experimental/sys/unimplemented.go b/experimental/sys/unimplemented.go new file mode 100644 index 0000000000..1099eb12eb --- /dev/null +++ b/experimental/sys/unimplemented.go @@ -0,0 +1,190 @@ +package sys + +import ( + "io/fs" + + "github.com/tetratelabs/wazero/sys" +) + +// UnimplementedFS is an FS that returns ENOSYS for all functions, +// This should be embedded to have forward compatible implementations. +type UnimplementedFS struct{} + +// String implements fmt.Stringer +func (UnimplementedFS) String() string { + return "Unimplemented:/" +} + +// Open implements the same method as documented on fs.FS +func (UnimplementedFS) Open(name string) (fs.File, error) { + return nil, &fs.PathError{Op: "open", Path: name, Err: ENOSYS} +} + +// OpenFile implements FS.OpenFile +func (UnimplementedFS) OpenFile(path string, flag Oflag, perm fs.FileMode) (File, Errno) { + return nil, ENOSYS +} + +// Lstat implements FS.Lstat +func (UnimplementedFS) Lstat(path string) (sys.Stat_t, Errno) { + return sys.Stat_t{}, ENOSYS +} + +// Stat implements FS.Stat +func (UnimplementedFS) Stat(path string) (sys.Stat_t, Errno) { + return sys.Stat_t{}, ENOSYS +} + +// Readlink implements FS.Readlink +func (UnimplementedFS) Readlink(path string) (string, Errno) { + return "", ENOSYS +} + +// Mkdir implements FS.Mkdir +func (UnimplementedFS) Mkdir(path string, perm fs.FileMode) Errno { + return ENOSYS +} + +// Chmod implements FS.Chmod +func (UnimplementedFS) Chmod(path string, perm fs.FileMode) Errno { + return ENOSYS +} + +// Rename implements FS.Rename +func (UnimplementedFS) Rename(from, to string) Errno { + return ENOSYS +} + +// Rmdir implements FS.Rmdir +func (UnimplementedFS) Rmdir(path string) Errno { + return ENOSYS +} + +// Link implements FS.Link +func (UnimplementedFS) Link(_, _ string) Errno { + return ENOSYS +} + +// Symlink implements FS.Symlink +func (UnimplementedFS) Symlink(_, _ string) Errno { + return ENOSYS +} + +// Unlink implements FS.Unlink +func (UnimplementedFS) Unlink(path string) Errno { + return ENOSYS +} + +// Utimens implements FS.Utimens +func (UnimplementedFS) Utimens(path string, atim, mtim int64) Errno { + return ENOSYS +} + +// Truncate implements FS.Truncate +func (UnimplementedFS) Truncate(string, int64) Errno { + return ENOSYS +} + +// UnimplementedFile is a File that returns ENOSYS for all functions, +// except where no-op are otherwise documented. +// +// This should be embedded to have forward compatible implementations. +type UnimplementedFile struct{} + +// Dev implements File.Dev +func (UnimplementedFile) Dev() (uint64, Errno) { + return 0, 0 +} + +// Ino implements File.Ino +func (UnimplementedFile) Ino() (sys.Inode, Errno) { + return 0, 0 +} + +// IsDir implements File.IsDir +func (UnimplementedFile) IsDir() (bool, Errno) { + return false, 0 +} + +// IsAppend implements File.IsAppend +func (UnimplementedFile) IsAppend() bool { + return false +} + +// SetAppend implements File.SetAppend +func (UnimplementedFile) SetAppend(bool) Errno { + return ENOSYS +} + +// IsNonblock implements File.IsNonblock +func (UnimplementedFile) IsNonblock() bool { + return false +} + +// SetNonblock implements File.SetNonblock +func (UnimplementedFile) SetNonblock(bool) Errno { + return ENOSYS +} + +// Stat implements File.Stat +func (UnimplementedFile) Stat() (sys.Stat_t, Errno) { + return sys.Stat_t{}, ENOSYS +} + +// Read implements File.Read +func (UnimplementedFile) Read([]byte) (int, Errno) { + return 0, ENOSYS +} + +// Pread implements File.Pread +func (UnimplementedFile) Pread([]byte, int64) (int, Errno) { + return 0, ENOSYS +} + +// Seek implements File.Seek +func (UnimplementedFile) Seek(int64, int) (int64, Errno) { + return 0, ENOSYS +} + +// Readdir implements File.Readdir +func (UnimplementedFile) Readdir(int) (dirents []Dirent, errno Errno) { + return nil, ENOSYS +} + +// Poll implements File.Poll +func (UnimplementedFile) Poll(Pflag, int32) (ready bool, errno Errno) { + return false, ENOSYS +} + +// Write implements File.Write +func (UnimplementedFile) Write([]byte) (int, Errno) { + return 0, ENOSYS +} + +// Pwrite implements File.Pwrite +func (UnimplementedFile) Pwrite([]byte, int64) (int, Errno) { + return 0, ENOSYS +} + +// Truncate implements File.Truncate +func (UnimplementedFile) Truncate(int64) Errno { + return ENOSYS +} + +// Sync implements File.Sync +func (UnimplementedFile) Sync() Errno { + return 0 // not ENOSYS +} + +// Datasync implements File.Datasync +func (UnimplementedFile) Datasync() Errno { + return 0 // not ENOSYS +} + +// Utimens implements File.Utimens +func (UnimplementedFile) Utimens(int64, int64) Errno { + return ENOSYS +} + +// Close implements File.Close +func (UnimplementedFile) Close() (errno Errno) { return } diff --git a/experimental/sysfs/config.go b/experimental/sysfs/config.go new file mode 100644 index 0000000000..a160911986 --- /dev/null +++ b/experimental/sysfs/config.go @@ -0,0 +1,16 @@ +package sysfs + +import ( + "github.com/tetratelabs/wazero" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" +) + +// FSConfig extends wazero.FSConfig, allowing access to the experimental +// sys.FS until it is moved to the "sys" package. +type FSConfig interface { + // WithSysFSMount assigns a sys.FS file system for any paths beginning at + // `guestPath`. + // + // This is an alternative to WithFSMount, allowing more features. + WithSysFSMount(fs experimentalsys.FS, guestPath string) wazero.FSConfig +} diff --git a/experimental/sysfs/config_example_test.go b/experimental/sysfs/config_example_test.go new file mode 100644 index 0000000000..91ce29a42a --- /dev/null +++ b/experimental/sysfs/config_example_test.go @@ -0,0 +1,40 @@ +package sysfs_test + +import ( + "io/fs" + "testing/fstest" + + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/experimental/sysfs" +) + +var moduleConfig wazero.ModuleConfig + +// This example shows how to configure a sysfs.NewDirFS +func ExampleNewDirFS() { + root := sysfs.NewDirFS(".") + + moduleConfig = wazero.NewModuleConfig(). + WithFSConfig(wazero.NewFSConfig().(sysfs.FSConfig).WithSysFSMount(root, "/")) +} + +// This example shows how to configure a sysfs.NewReadFS +func ExampleNewReadFS() { + root := sysfs.NewDirFS(".") + readOnly := sysfs.NewReadFS(root) + + moduleConfig = wazero.NewModuleConfig(). + WithFSConfig(wazero.NewFSConfig().(sysfs.FSConfig).WithSysFSMount(readOnly, "/")) +} + +// This example shows how to adapt a fs.FS as a sys.FS +func ExampleAdapt() { + m := fstest.MapFS{ + "a/b.txt": &fstest.MapFile{Mode: 0o666}, + ".": &fstest.MapFile{Mode: 0o777 | fs.ModeDir}, + } + root := sysfs.Adapt(m) + + moduleConfig = wazero.NewModuleConfig(). + WithFSConfig(wazero.NewFSConfig().(sysfs.FSConfig).WithSysFSMount(root, "/")) +} diff --git a/experimental/sysfs/sysfs.go b/experimental/sysfs/sysfs.go new file mode 100644 index 0000000000..c2a18fd5ee --- /dev/null +++ b/experimental/sysfs/sysfs.go @@ -0,0 +1,39 @@ +// Package sysfs includes a low-level filesystem interface and utilities needed +// for WebAssembly host functions (ABI) such as WASI and runtime.GOOS=js. +// +// The name sysfs was chosen because wazero's public API has a "sys" package, +// which was named after https://github.com/golang/sys. +// +// This tracked in https://github.com/tetratelabs/wazero/issues/1013 +package sysfs + +import ( + "io/fs" + + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" + "github.com/tetratelabs/wazero/internal/sysfs" +) + +// Adapt adapts the input to sys.FS unless it is already one. Use NewDirFS +// instead of os.DirFS as it handles interop issues such as windows support. +// +// Note: This performs no flag verification on OpenFile. fs.FS cannot read +// flags as there is no parameter to pass them through with. Moreover, fs.FS +// documentation does not require the file to be present. In summary, we can't +// enforce flag behavior. +func Adapt(fs fs.FS) experimentalsys.FS { + return sysfs.Adapt(fs) +} + +// NewReadFS is used to mask an existing sys.FS for reads. Notably, this allows +// the CLI to do read-only mounts of directories the host user can write, but +// doesn't want the guest wasm to. For example, Python libraries shouldn't be +// written to at runtime by the python wasm file. +func NewReadFS(fs experimentalsys.FS) experimentalsys.FS { + return sysfs.NewReadFS(fs) +} + +// NewDirFS is like os.DirFS except it returns sys.FS, which has more features. +func NewDirFS(dir string) experimentalsys.FS { + return sysfs.NewDirFS(dir) +} diff --git a/fsconfig.go b/fsconfig.go index 560da0b37d..5576e7cc0e 100644 --- a/fsconfig.go +++ b/fsconfig.go @@ -3,7 +3,7 @@ package wazero import ( "io/fs" - "github.com/tetratelabs/wazero/internal/fsapi" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/sysfs" ) @@ -135,7 +135,7 @@ type FSConfig interface { type fsConfig struct { // fs are the currently configured filesystems. - fs []fsapi.FS + fs []experimentalsys.FS // guestPaths are the user-supplied names of the filesystems, retained for // error messages and fmt.Stringer. guestPaths []string @@ -152,7 +152,7 @@ func NewFSConfig() FSConfig { // clone makes a deep copy of this module config. func (c *fsConfig) clone() *fsConfig { ret := *c // copy except slice and maps which share a ref - ret.fs = make([]fsapi.FS, 0, len(c.fs)) + ret.fs = make([]experimentalsys.FS, 0, len(c.fs)) ret.fs = append(ret.fs, c.fs...) ret.guestPaths = make([]string, 0, len(c.guestPaths)) ret.guestPaths = append(ret.guestPaths, c.guestPaths...) @@ -165,21 +165,22 @@ func (c *fsConfig) clone() *fsConfig { // WithDirMount implements FSConfig.WithDirMount func (c *fsConfig) WithDirMount(dir, guestPath string) FSConfig { - return c.withMount(sysfs.NewDirFS(dir), guestPath) + return c.WithSysFSMount(sysfs.NewDirFS(dir), guestPath) } // WithReadOnlyDirMount implements FSConfig.WithReadOnlyDirMount func (c *fsConfig) WithReadOnlyDirMount(dir, guestPath string) FSConfig { - return c.withMount(sysfs.NewReadFS(sysfs.NewDirFS(dir)), guestPath) + return c.WithSysFSMount(sysfs.NewReadFS(sysfs.NewDirFS(dir)), guestPath) } // WithFSMount implements FSConfig.WithFSMount func (c *fsConfig) WithFSMount(fs fs.FS, guestPath string) FSConfig { - return c.withMount(sysfs.Adapt(fs), guestPath) + return c.WithSysFSMount(sysfs.Adapt(fs), guestPath) } -func (c *fsConfig) withMount(fs fsapi.FS, guestPath string) FSConfig { - if _, ok := fs.(fsapi.UnimplementedFS); ok { +// WithSysFSMount implements sysfs.FSConfig +func (c *fsConfig) WithSysFSMount(fs experimentalsys.FS, guestPath string) FSConfig { + if _, ok := fs.(experimentalsys.UnimplementedFS); ok { return c // don't add fake paths. } cleaned := sys.StripPrefixesAndTrailingSlash(guestPath) @@ -197,12 +198,12 @@ func (c *fsConfig) withMount(fs fsapi.FS, guestPath string) FSConfig { // preopens returns the possible nil index-correlated preopened filesystems // with guest paths. -func (c *fsConfig) preopens() ([]fsapi.FS, []string) { +func (c *fsConfig) preopens() ([]experimentalsys.FS, []string) { preopenCount := len(c.fs) if preopenCount == 0 { return nil, nil } - fs := make([]fsapi.FS, len(c.fs)) + fs := make([]experimentalsys.FS, len(c.fs)) copy(fs, c.fs) guestPaths := make([]string, len(c.guestPaths)) copy(guestPaths, c.guestPaths) diff --git a/fsconfig_test.go b/fsconfig_test.go index 2ea3aded4f..716120098e 100644 --- a/fsconfig_test.go +++ b/fsconfig_test.go @@ -3,7 +3,7 @@ package wazero import ( "testing" - "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/internal/sysfs" testfs "github.com/tetratelabs/wazero/internal/testing/fs" "github.com/tetratelabs/wazero/internal/testing/require" @@ -19,7 +19,7 @@ func TestFSConfig(t *testing.T) { tests := []struct { name string input FSConfig - expectedFS []fsapi.FS + expectedFS []sys.FS expectedGuestPaths []string }{ { @@ -29,13 +29,13 @@ func TestFSConfig(t *testing.T) { { name: "WithFSMount", input: base.WithFSMount(testFS, "/"), - expectedFS: []fsapi.FS{sysfs.Adapt(testFS)}, + expectedFS: []sys.FS{sysfs.Adapt(testFS)}, expectedGuestPaths: []string{"/"}, }, { name: "WithFSMount overwrites", input: base.WithFSMount(testFS, "/").WithFSMount(testFS2, "/"), - expectedFS: []fsapi.FS{sysfs.Adapt(testFS2)}, + expectedFS: []sys.FS{sysfs.Adapt(testFS2)}, expectedGuestPaths: []string{"/"}, }, { @@ -45,13 +45,13 @@ func TestFSConfig(t *testing.T) { { name: "WithDirMount overwrites", input: base.WithFSMount(testFS, "/").WithDirMount(".", "/"), - expectedFS: []fsapi.FS{sysfs.NewDirFS(".")}, + expectedFS: []sys.FS{sysfs.NewDirFS(".")}, expectedGuestPaths: []string{"/"}, }, { name: "multiple", input: base.WithReadOnlyDirMount(".", "/").WithDirMount("/tmp", "/tmp"), - expectedFS: []fsapi.FS{sysfs.NewReadFS(sysfs.NewDirFS(".")), sysfs.NewDirFS("/tmp")}, + expectedFS: []sys.FS{sysfs.NewReadFS(sysfs.NewDirFS(".")), sysfs.NewDirFS("/tmp")}, expectedGuestPaths: []string{"/", "/tmp"}, }, } diff --git a/imports/assemblyscript/assemblyscript.go b/imports/assemblyscript/assemblyscript.go index 4cb1b3db7a..5cbe605bbd 100644 --- a/imports/assemblyscript/assemblyscript.go +++ b/imports/assemblyscript/assemblyscript.go @@ -35,8 +35,8 @@ import ( "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/api" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" . "github.com/tetratelabs/wazero/internal/assemblyscript" - "github.com/tetratelabs/wazero/internal/fsapi" internalsys "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/sys" @@ -225,7 +225,7 @@ var traceStderr = traceStdout.WithGoModuleFunc(func(_ context.Context, mod api.M // (import "env" "trace" (func $~lib/builtins/trace (param i32 i32 f64 f64 f64 f64 f64))) // // See https://github.com/AssemblyScript/assemblyscript/blob/fa14b3b03bd4607efa52aaff3132bea0c03a7989/std/assembly/wasi/index.ts#L61 -func traceTo(mod api.Module, params []uint64, file fsapi.File) { +func traceTo(mod api.Module, params []uint64, file experimentalsys.File) { message := uint32(params[0]) nArgs := uint32(params[1]) arg0 := api.DecodeF64(params[2]) diff --git a/imports/wasi_snapshot_preview1/fs.go b/imports/wasi_snapshot_preview1/fs.go index 3a451711e1..b80c14d7d5 100644 --- a/imports/wasi_snapshot_preview1/fs.go +++ b/imports/wasi_snapshot_preview1/fs.go @@ -12,7 +12,6 @@ import ( "github.com/tetratelabs/wazero/api" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" socketapi "github.com/tetratelabs/wazero/internal/sock" "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/wasip1" @@ -414,7 +413,7 @@ func fdFilestatGetFunc(mod api.Module, fd int32, resultBuf uint32) experimentals return writeFilestat(buf, &st, filetype) } -func getExtendedWasiFiletype(file fsapi.File, fm fs.FileMode) (ftype uint8) { +func getExtendedWasiFiletype(file experimentalsys.File, fm fs.FileMode) (ftype uint8) { ftype = getWasiFiletype(fm) if ftype == wasip1.FILETYPE_UNKNOWN { if _, ok := file.(socketapi.TCPSock); ok { @@ -533,7 +532,7 @@ func toTimes(walltime func() int64, atim, mtim int64, fstFlags uint16) (int64, i nowTim = walltime() atim = nowTim } else { - atim = fsapi.UTIME_OMIT + atim = experimentalsys.UTIME_OMIT } // coerce mtim into a timespec @@ -548,7 +547,7 @@ func toTimes(walltime func() int64, atim, mtim int64, fstFlags uint16) (int64, i mtim = walltime() } } else { - mtim = fsapi.UTIME_OMIT + mtim = experimentalsys.UTIME_OMIT } return atim, mtim, 0 } @@ -749,11 +748,11 @@ var fdRead = newHostFunc( // preader tracks an offset across multiple reads. type preader struct { - f fsapi.File + f experimentalsys.File offset int64 } -// Read implements the same function as documented on fsapi.File. +// Read implements the same function as documented on sys.File. func (w *preader) Read(buf []byte) (n int, errno experimentalsys.Errno) { if len(buf) == 0 { return 0, 0 // less overhead on zero-length reads. @@ -946,7 +945,7 @@ const largestDirent = int64(math.MaxUint32 - wasip1.DirentSize) // // `bufToWrite` is the amount of memory needed to write direntCount, which // includes up to wasip1.DirentSize of a last truncated entry. -func maxDirents(dirents []fsapi.Dirent, bufLen uint32) (bufToWrite uint32, direntCount int, truncatedLen uint32) { +func maxDirents(dirents []experimentalsys.Dirent, bufLen uint32) (bufToWrite uint32, direntCount int, truncatedLen uint32) { lenRemaining := bufLen for i := range dirents { if lenRemaining == 0 { @@ -995,7 +994,7 @@ func maxDirents(dirents []fsapi.Dirent, bufLen uint32) (bufToWrite uint32, diren // writeDirents writes the directory entries to the buffer, which is pre-sized // based on maxDirents. truncatedEntryLen means the last is written without its // name. -func writeDirents(buf []byte, dirents []fsapi.Dirent, d_next uint64, direntCount int, truncatedLen uint32) { +func writeDirents(buf []byte, dirents []experimentalsys.Dirent, d_next uint64, direntCount int, truncatedLen uint32) { pos := uint32(0) skipNameI := -1 @@ -1237,11 +1236,11 @@ func fdWriteFn(_ context.Context, mod api.Module, params []uint64) experimentals // pwriter tracks an offset across multiple writes. type pwriter struct { - f fsapi.File + f experimentalsys.File offset int64 } -// Write implements the same function as documented on fsapi.File. +// Write implements the same function as documented on sys.File. func (w *pwriter) Write(buf []byte) (n int, errno experimentalsys.Errno) { if len(buf) == 0 { return 0, 0 // less overhead on zero-length writes. @@ -1599,7 +1598,7 @@ func pathOpenFn(_ context.Context, mod api.Module, params []uint64) experimental } fileOpenFlags := openFlags(dirflags, oflags, fdflags, rights) - isDir := fileOpenFlags&fsapi.O_DIRECTORY != 0 + isDir := fileOpenFlags&experimentalsys.O_DIRECTORY != 0 if isDir && oflags&wasip1.O_CREAT != 0 { return experimentalsys.EINVAL // use pathCreateDirectory! @@ -1646,7 +1645,7 @@ func pathOpenFn(_ context.Context, mod api.Module, params []uint64) experimental // // 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, fd int32, p, pathLen uint32) (fsapi.FS, string, experimentalsys.Errno) { +func atPath(fsc *sys.FSContext, mem api.Memory, fd int32, p, pathLen uint32) (experimentalsys.FS, string, experimentalsys.Errno) { b, ok := mem.Read(p, pathLen) if !ok { return nil, "", experimentalsys.EFAULT @@ -1700,15 +1699,15 @@ func preopenPath(fsc *sys.FSContext, fd int32) (string, experimentalsys.Errno) { } } -func openFlags(dirflags, oflags, fdflags uint16, rights uint32) (openFlags fsapi.Oflag) { +func openFlags(dirflags, oflags, fdflags uint16, rights uint32) (openFlags experimentalsys.Oflag) { if dirflags&wasip1.LOOKUP_SYMLINK_FOLLOW == 0 { - openFlags |= fsapi.O_NOFOLLOW + openFlags |= experimentalsys.O_NOFOLLOW } if oflags&wasip1.O_DIRECTORY != 0 { - openFlags |= fsapi.O_DIRECTORY + openFlags |= experimentalsys.O_DIRECTORY return // Early return for directories as the rest of flags doesn't make sense for it. } else if oflags&wasip1.O_EXCL != 0 { - openFlags |= fsapi.O_EXCL + openFlags |= experimentalsys.O_EXCL } // Because we don't implement rights, we partially rely on the open flags // to determine the mode in which the file will be opened. This will create @@ -1717,30 +1716,30 @@ func openFlags(dirflags, oflags, fdflags uint16, rights uint32) (openFlags fsapi // which sets O_CREAT but does not give read or write permissions will // successfully create a file when running with wazero, but might get a // permission denied error on other runtimes. - defaultMode := fsapi.O_RDONLY + defaultMode := experimentalsys.O_RDONLY if oflags&wasip1.O_TRUNC != 0 { - openFlags |= fsapi.O_TRUNC - defaultMode = fsapi.O_RDWR + openFlags |= experimentalsys.O_TRUNC + defaultMode = experimentalsys.O_RDWR } if oflags&wasip1.O_CREAT != 0 { - openFlags |= fsapi.O_CREAT - defaultMode = fsapi.O_RDWR + openFlags |= experimentalsys.O_CREAT + defaultMode = experimentalsys.O_RDWR } if fdflags&wasip1.FD_NONBLOCK != 0 { - openFlags |= fsapi.O_NONBLOCK + openFlags |= experimentalsys.O_NONBLOCK } if fdflags&wasip1.FD_APPEND != 0 { - openFlags |= fsapi.O_APPEND - defaultMode = fsapi.O_RDWR + openFlags |= experimentalsys.O_APPEND + defaultMode = experimentalsys.O_RDWR } if fdflags&wasip1.FD_DSYNC != 0 { - openFlags |= fsapi.O_DSYNC + openFlags |= experimentalsys.O_DSYNC } if fdflags&wasip1.FD_RSYNC != 0 { - openFlags |= fsapi.O_RSYNC + openFlags |= experimentalsys.O_RSYNC } if fdflags&wasip1.FD_SYNC != 0 { - openFlags |= fsapi.O_SYNC + openFlags |= experimentalsys.O_SYNC } // Since rights were discontinued in wasi, we only interpret RIGHT_FD_WRITE @@ -1752,11 +1751,11 @@ func openFlags(dirflags, oflags, fdflags uint16, rights uint32) (openFlags fsapi const rw = r | w switch { case (rights & rw) == rw: - openFlags |= fsapi.O_RDWR + openFlags |= experimentalsys.O_RDWR case (rights & w) == w: - openFlags |= fsapi.O_WRONLY + openFlags |= experimentalsys.O_WRONLY case (rights & r) == r: - openFlags |= fsapi.O_RDONLY + openFlags |= experimentalsys.O_RDONLY default: openFlags |= defaultMode } diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go index fc8e504c48..ee5ad2d740 100644 --- a/imports/wasi_snapshot_preview1/fs_test.go +++ b/imports/wasi_snapshot_preview1/fs_test.go @@ -17,7 +17,6 @@ import ( "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/api" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/platform" "github.com/tetratelabs/wazero/internal/sys" @@ -58,7 +57,7 @@ func Test_fdAllocate(t *testing.T) { preopen := fsc.RootFS() defer r.Close(testCtx) - fd, errno := fsc.OpenFile(preopen, fileName, fsapi.O_RDWR, 0) + fd, errno := fsc.OpenFile(preopen, fileName, experimentalsys.O_RDWR, 0) require.EqualErrno(t, 0, errno) f, ok := fsc.LookupFile(fd) @@ -136,10 +135,10 @@ func Test_fdClose(t *testing.T) { fsc := mod.(*wasm.ModuleInstance).Sys.FS() preopen := fsc.RootFS() - fdToClose, errno := fsc.OpenFile(preopen, path1, fsapi.O_RDONLY, 0) + fdToClose, errno := fsc.OpenFile(preopen, path1, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) - fdToKeep, errno := fsc.OpenFile(preopen, path2, fsapi.O_RDONLY, 0) + fdToKeep, errno := fsc.OpenFile(preopen, path2, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) // Close @@ -241,7 +240,7 @@ func Test_fdFdstatGet(t *testing.T) { preopen := fsc.RootFS() // replace stdin with a fake TTY file. - // TODO: Make this easier once we have in-memory fsapi.File + // TODO: Make this easier once we have in-memory sys.File stdin, _ := fsc.LookupFile(sys.FdStdin) stdinFile, errno := sysfs.Adapt(&gofstest.MapFS{"stdin": &gofstest.MapFile{ Mode: fs.ModeDevice | fs.ModeCharDevice | 0o600, @@ -251,10 +250,10 @@ func Test_fdFdstatGet(t *testing.T) { stdin.File = stdinFile // Make this file writeable, to ensure flags read-back correctly. - fileFD, errno := fsc.OpenFile(preopen, file, fsapi.O_RDWR, 0) + fileFD, errno := fsc.OpenFile(preopen, file, experimentalsys.O_RDWR, 0) require.EqualErrno(t, 0, errno) - dirFD, errno := fsc.OpenFile(preopen, dir, fsapi.O_RDONLY, 0) + dirFD, errno := fsc.OpenFile(preopen, dir, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) tests := []struct { @@ -506,7 +505,7 @@ func Test_fdFdstatSetFlags(t *testing.T) { // logic should clear O_CREAT preventing this. const fileName = "file.txt" // Create the target file. - fd, errno := fsc.OpenFile(preopen, fileName, fsapi.O_RDWR|fsapi.O_APPEND|fsapi.O_CREAT|fsapi.O_EXCL, 0o600) + fd, errno := fsc.OpenFile(preopen, fileName, experimentalsys.O_RDWR|experimentalsys.O_APPEND|experimentalsys.O_CREAT|experimentalsys.O_EXCL, 0o600) require.EqualErrno(t, 0, errno) // Write the initial text to the file. @@ -613,10 +612,10 @@ func Test_fdFilestatGet(t *testing.T) { fsc := mod.(*wasm.ModuleInstance).Sys.FS() preopen := fsc.RootFS() - fileFD, errno := fsc.OpenFile(preopen, file, fsapi.O_RDONLY, 0) + fileFD, errno := fsc.OpenFile(preopen, file, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) - dirFD, errno := fsc.OpenFile(preopen, dir, fsapi.O_RDONLY, 0) + dirFD, errno := fsc.OpenFile(preopen, dir, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) tests := []struct { @@ -2155,7 +2154,7 @@ func Test_fdReaddir(t *testing.T) { t.Run(tc.name, func(t *testing.T) { defer log.Reset() - fd, errno := fsc.OpenFile(preopen, tc.initialDir, fsapi.O_RDONLY, 0) + fd, errno := fsc.OpenFile(preopen, tc.initialDir, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer fsc.CloseFile(fd) // nolint @@ -2197,7 +2196,7 @@ func Test_fdReaddir_Rewind(t *testing.T) { fsc := mod.(*wasm.ModuleInstance).Sys.FS() - fd, errno := fsc.OpenFile(fsc.RootFS(), ".", fsapi.O_RDONLY, 0) + fd, errno := fsc.OpenFile(fsc.RootFS(), ".", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) mem := mod.Memory() @@ -2246,7 +2245,7 @@ func Test_fdReaddir_Errors(t *testing.T) { fsc := mod.(*wasm.ModuleInstance).Sys.FS() preopen := fsc.RootFS() - fileFD, errno := fsc.OpenFile(preopen, "animals.txt", fsapi.O_RDONLY, 0) + fileFD, errno := fsc.OpenFile(preopen, "animals.txt", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) // Directories are stateful, so we open them during the test. @@ -2350,7 +2349,7 @@ func Test_fdReaddir_Errors(t *testing.T) { // Reset the directory so that tests don't taint each other. if tc.fd == dirFD { - dirFD, errno = fsc.OpenFile(preopen, "dir", fsapi.O_RDONLY, 0) + dirFD, errno = fsc.OpenFile(preopen, "dir", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer fsc.CloseFile(dirFD) // nolint } @@ -2463,11 +2462,11 @@ func Test_fdRenumber(t *testing.T) { preopen := fsc.RootFS() // Sanity check of the file descriptor assignment. - fileFDAssigned, errno := fsc.OpenFile(preopen, "animals.txt", fsapi.O_RDONLY, 0) + fileFDAssigned, errno := fsc.OpenFile(preopen, "animals.txt", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) require.Equal(t, int32(fileFD), fileFDAssigned) - dirFDAssigned, errno := fsc.OpenFile(preopen, "dir", fsapi.O_RDONLY, 0) + dirFDAssigned, errno := fsc.OpenFile(preopen, "dir", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) require.Equal(t, int32(dirFD), dirFDAssigned) @@ -3603,7 +3602,7 @@ func Test_pathLink(t *testing.T) { uint64(newFd), uint64(destination), uint64(len(destinationName))) require.Contains(t, log.String(), wasip1.ErrnoName(wasip1.ErrnoSuccess)) - f := openFile(t, destinationRealPath, fsapi.O_RDONLY, 0) + f := openFile(t, destinationRealPath, experimentalsys.O_RDONLY, 0) defer f.Close() st, errno := f.Stat() @@ -3675,7 +3674,7 @@ func Test_pathOpen(t *testing.T) { tests := []struct { name string - fs fsapi.FS + fs experimentalsys.FS path func(t *testing.T) string oflags uint16 fdflags uint16 @@ -3925,7 +3924,7 @@ func requireOpenFD(t *testing.T, mod api.Module, path string) int32 { fsc := mod.(*wasm.ModuleInstance).Sys.FS() preopen := fsc.RootFS() - fd, errno := fsc.OpenFile(preopen, path, fsapi.O_RDONLY, 0) + fd, errno := fsc.OpenFile(preopen, path, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) return fd } @@ -3941,7 +3940,7 @@ func requireContents(t *testing.T, fsc *sys.FSContext, expectedOpenedFd int32, f require.Equal(t, fileContents, buf) } -func readAll(t *testing.T, f fsapi.File) []byte { +func readAll(t *testing.T, f experimentalsys.File) []byte { st, errno := f.Stat() require.EqualErrno(t, 0, errno) buf := make([]byte, st.Size) @@ -4854,14 +4853,14 @@ func Test_pathUnlinkFile_Errors(t *testing.T) { } func requireOpenFile(t *testing.T, tmpDir string, pathName string, data []byte, readOnly bool) (api.Module, int32, *bytes.Buffer, api.Closer) { - oflags := fsapi.O_RDWR + oflags := experimentalsys.O_RDWR if readOnly { - oflags = fsapi.O_RDONLY + oflags = experimentalsys.O_RDONLY } realPath := joinPath(tmpDir, pathName) if data == nil { - oflags = fsapi.O_RDONLY + oflags = experimentalsys.O_RDONLY require.NoError(t, os.Mkdir(realPath, 0o700)) } else { require.NoError(t, os.WriteFile(realPath, data, 0o600)) @@ -4908,7 +4907,7 @@ func Test_fdReaddir_dotEntryHasARealInode(t *testing.T) { uint64(sys.FdPreopen), uint64(0), uint64(len(readDirTarget))) // Open the directory, before writing files! - fd, errno := fsc.OpenFile(preopen, readDirTarget, fsapi.O_RDONLY, 0) + fd, errno := fsc.OpenFile(preopen, readDirTarget, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) // get the real inode of the current directory @@ -4966,11 +4965,11 @@ func Test_fdReaddir_opened_file_written(t *testing.T) { uint64(sys.FdPreopen), uint64(0), uint64(len(dirName))) // Open the directory, before writing files! - dirFD, errno := fsc.OpenFile(preopen, dirName, fsapi.O_RDONLY, 0) + dirFD, errno := fsc.OpenFile(preopen, dirName, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) // Then write a file to the directory. - f := openFile(t, joinPath(dirPath, "file"), fsapi.O_CREAT, 0) + f := openFile(t, joinPath(dirPath, "file"), experimentalsys.O_CREAT, 0) defer f.Close() // get the real inode of the current directory @@ -5019,7 +5018,7 @@ func joinPath(dirName, baseName string) string { return path.Join(dirName, baseName) } -func openFile(t *testing.T, path string, flag fsapi.Oflag, perm fs.FileMode) fsapi.File { +func openFile(t *testing.T, path string, flag experimentalsys.Oflag, perm fs.FileMode) experimentalsys.File { f, errno := sysfs.OpenOSFile(path, flag, perm) require.EqualErrno(t, 0, errno) return f diff --git a/imports/wasi_snapshot_preview1/fs_unit_test.go b/imports/wasi_snapshot_preview1/fs_unit_test.go index a65506087e..cea9e729f0 100644 --- a/imports/wasi_snapshot_preview1/fs_unit_test.go +++ b/imports/wasi_snapshot_preview1/fs_unit_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - "github.com/tetratelabs/wazero/internal/fsapi" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/sysfs" @@ -15,7 +15,7 @@ import ( func Test_maxDirents(t *testing.T) { tests := []struct { name string - dirents []fsapi.Dirent + dirents []experimentalsys.Dirent bufLen uint32 expectedBufToWrite uint32 expectedDirentCount int @@ -107,9 +107,9 @@ func Test_maxDirents(t *testing.T) { } var ( - testDirents = func() []fsapi.Dirent { + testDirents = func() []experimentalsys.Dirent { dPath := "dir" - d, errno := sysfs.OpenFSFile(fstest.FS, dPath, fsapi.O_RDONLY, 0) + d, errno := sysfs.OpenFSFile(fstest.FS, dPath, experimentalsys.O_RDONLY, 0) if errno != 0 { panic(errno) } @@ -147,7 +147,7 @@ var ( func Test_writeDirents(t *testing.T) { tests := []struct { name string - dirents []fsapi.Dirent + dirents []experimentalsys.Dirent entryCount int truncatedLen uint32 expected []byte @@ -207,61 +207,61 @@ func Test_openFlags(t *testing.T) { name string dirflags, oflags, fdflags uint16 rights uint32 - expectedOpenFlags fsapi.Oflag + expectedOpenFlags experimentalsys.Oflag }{ { name: "oflags=0", - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDONLY, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_RDONLY, }, { name: "oflags=O_CREAT", oflags: wasip1.O_CREAT, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR | fsapi.O_CREAT, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_RDWR | experimentalsys.O_CREAT, }, { name: "oflags=O_DIRECTORY", oflags: wasip1.O_DIRECTORY, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_DIRECTORY, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_DIRECTORY, }, { name: "oflags=O_EXCL", oflags: wasip1.O_EXCL, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDONLY | fsapi.O_EXCL, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_RDONLY | experimentalsys.O_EXCL, }, { name: "oflags=O_TRUNC", oflags: wasip1.O_TRUNC, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR | fsapi.O_TRUNC, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_RDWR | experimentalsys.O_TRUNC, }, { name: "fdflags=FD_APPEND", fdflags: wasip1.FD_APPEND, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR | fsapi.O_APPEND, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_RDWR | experimentalsys.O_APPEND, }, { name: "oflags=O_TRUNC|O_CREAT", oflags: wasip1.O_TRUNC | wasip1.O_CREAT, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR | fsapi.O_TRUNC | fsapi.O_CREAT, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_RDWR | experimentalsys.O_TRUNC | experimentalsys.O_CREAT, }, { name: "dirflags=LOOKUP_SYMLINK_FOLLOW", dirflags: wasip1.LOOKUP_SYMLINK_FOLLOW, - expectedOpenFlags: fsapi.O_RDONLY, + expectedOpenFlags: experimentalsys.O_RDONLY, }, { name: "rights=FD_READ", rights: wasip1.RIGHT_FD_READ, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDONLY, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_RDONLY, }, { name: "rights=FD_WRITE", rights: wasip1.RIGHT_FD_WRITE, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_WRONLY, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_WRONLY, }, { name: "rights=FD_READ|FD_WRITE", rights: wasip1.RIGHT_FD_READ | wasip1.RIGHT_FD_WRITE, - expectedOpenFlags: fsapi.O_NOFOLLOW | fsapi.O_RDWR, + expectedOpenFlags: experimentalsys.O_NOFOLLOW | experimentalsys.O_RDWR, }, } diff --git a/imports/wasi_snapshot_preview1/poll.go b/imports/wasi_snapshot_preview1/poll.go index 3249809dfc..0119b5410f 100644 --- a/imports/wasi_snapshot_preview1/poll.go +++ b/imports/wasi_snapshot_preview1/poll.go @@ -6,7 +6,6 @@ import ( "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" internalsys "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/wasip1" "github.com/tetratelabs/wazero/internal/wasm" @@ -175,7 +174,7 @@ func pollOneoffFn(_ context.Context, mod api.Module, params []uint64) sys.Errno return sys.EBADF } // Wait for the timeout to expire, or for some data to become available on Stdin. - stdinReady, errno := stdin.File.Poll(fsapi.POLLIN, int32(timeout.Milliseconds())) + stdinReady, errno := stdin.File.Poll(sys.POLLIN, int32(timeout.Milliseconds())) if errno != 0 { return errno } diff --git a/imports/wasi_snapshot_preview1/poll_test.go b/imports/wasi_snapshot_preview1/poll_test.go index 07fa6d1147..6db7d6926d 100644 --- a/imports/wasi_snapshot_preview1/poll_test.go +++ b/imports/wasi_snapshot_preview1/poll_test.go @@ -9,7 +9,6 @@ import ( "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/api" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/testing/require" "github.com/tetratelabs/wazero/internal/wasip1" @@ -155,7 +154,7 @@ func Test_pollOneoff_Stdin(t *testing.T) { name string in, out, nsubscriptions, resultNevents uint32 mem []byte // at offset in - stdin fsapi.File + stdin experimentalsys.File expectedErrno wasip1.Errno expectedMem []byte // at offset out expectedLog string @@ -395,7 +394,7 @@ func Test_pollOneoff_Stdin(t *testing.T) { } } -func setStdin(t *testing.T, mod api.Module, stdin fsapi.File) { +func setStdin(t *testing.T, mod api.Module, stdin experimentalsys.File) { fsc := mod.(*wasm.ModuleInstance).Sys.FS() f, ok := fsc.LookupFile(sys.FdStdin) require.True(t, ok) @@ -536,7 +535,7 @@ var fdReadSub = fdReadSubFd(byte(sys.FdStdin)) // https://github.com/mattn/go-isatty/blob/v0.0.18/isatty_tcgets.go#LL11C1-L12C1 type ttyStat struct{} -// Stat implements the same method as documented on fsapi.File +// Stat implements the same method as documented on sys.File func (ttyStat) Stat() (sysapi.Stat_t, experimentalsys.Errno) { return sysapi.Stat_t{ Mode: fs.ModeDevice | fs.ModeCharDevice, @@ -554,9 +553,9 @@ type neverReadyTtyStdinFile struct { ttyStat } -// Poll implements the same method as documented on fsapi.File -func (neverReadyTtyStdinFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { - if flag != fsapi.POLLIN { +// Poll implements the same method as documented on sys.File +func (neverReadyTtyStdinFile) Poll(flag experimentalsys.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { + if flag != experimentalsys.POLLIN { return false, experimentalsys.ENOTSUP } switch { @@ -573,9 +572,9 @@ type pollStdinFile struct { ready bool } -// Poll implements the same method as documented on fsapi.File -func (p *pollStdinFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { - if flag != fsapi.POLLIN { +// Poll implements the same method as documented on sys.File +func (p *pollStdinFile) Poll(flag experimentalsys.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { + if flag != experimentalsys.POLLIN { return false, experimentalsys.ENOTSUP } return p.ready, 0 diff --git a/imports/wasi_snapshot_preview1/sock_unit_test.go b/imports/wasi_snapshot_preview1/sock_unit_test.go index 5f12c45a52..12f14bf543 100644 --- a/imports/wasi_snapshot_preview1/sock_unit_test.go +++ b/imports/wasi_snapshot_preview1/sock_unit_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/sock" "github.com/tetratelabs/wazero/internal/testing/require" "github.com/tetratelabs/wazero/internal/wasip1" @@ -22,7 +21,7 @@ func Test_getExtendedWasiFiletype(t *testing.T) { } type testSock struct { - fsapi.UnimplementedFile + sys.UnimplementedFile } func (t testSock) Accept() (sock.TCPConn, sys.Errno) { @@ -30,7 +29,7 @@ func (t testSock) Accept() (sock.TCPConn, sys.Errno) { } type testConn struct { - fsapi.UnimplementedFile + sys.UnimplementedFile } func (t testConn) Recvfrom([]byte, int) (n int, errno sys.Errno) { diff --git a/imports/wasi_snapshot_preview1/wasi_bench_test.go b/imports/wasi_snapshot_preview1/wasi_bench_test.go index 41dd396729..ac8ce748fc 100644 --- a/imports/wasi_snapshot_preview1/wasi_bench_test.go +++ b/imports/wasi_snapshot_preview1/wasi_bench_test.go @@ -8,8 +8,8 @@ import ( "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/api" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/testing/proxy" "github.com/tetratelabs/wazero/internal/wasip1" @@ -132,7 +132,7 @@ func Benchmark_fdReaddir(b *testing.B) { benches := []struct { name string fs fs.FS - // dirMount ensures direct use of fsapi.FS + // dirMount ensures direct use of sys.FS dirMount string // twoCalls tests performance of reading a directory in two calls. twoCalls bool @@ -199,7 +199,7 @@ func Benchmark_fdReaddir(b *testing.B) { // Open the root directory as a file-descriptor. fsc := mod.(*wasm.ModuleInstance).Sys.FS() - fd, errno := fsc.OpenFile(fsc.RootFS(), ".", fsapi.O_RDONLY, 0) + fd, errno := fsc.OpenFile(fsc.RootFS(), ".", experimentalsys.O_RDONLY, 0) if errno != 0 { b.Fatal(errno) } @@ -244,7 +244,7 @@ func Benchmark_pathFilestat(b *testing.B) { benches := []struct { name string fs fs.FS - // dirMount ensures direct use of fsapi.FS + // dirMount ensures direct use of sys.FS dirMount string path string fd int32 @@ -308,7 +308,7 @@ func Benchmark_pathFilestat(b *testing.B) { fd := sys.FdPreopen if bc.fd != sys.FdPreopen { fsc := mod.(*wasm.ModuleInstance).Sys.FS() - fd, errno := fsc.OpenFile(fsc.RootFS(), "zig", fsapi.O_RDONLY, 0) + fd, errno := fsc.OpenFile(fsc.RootFS(), "zig", experimentalsys.O_RDONLY, 0) if errno != 0 { b.Fatal(errno) } diff --git a/imports/wasi_snapshot_preview1/wasi_stdlib_test.go b/imports/wasi_snapshot_preview1/wasi_stdlib_test.go index 93ac1a5670..3e4933ff37 100644 --- a/imports/wasi_snapshot_preview1/wasi_stdlib_test.go +++ b/imports/wasi_snapshot_preview1/wasi_stdlib_test.go @@ -20,8 +20,8 @@ import ( "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/api" experimentalsock "github.com/tetratelabs/wazero/experimental/sock" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/fstest" internalsys "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/testing/require" @@ -329,7 +329,7 @@ func Test_Poll(t *testing.T) { tests := []struct { name string args []string - stdin fsapi.File + stdin experimentalsys.File expectedOutput string expectedTimeout time.Duration }{ diff --git a/internal/fsapi/unimplemented.go b/internal/fsapi/unimplemented.go deleted file mode 100644 index b1284bc8dc..0000000000 --- a/internal/fsapi/unimplemented.go +++ /dev/null @@ -1,191 +0,0 @@ -package fsapi - -import ( - "io/fs" - - experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/sys" -) - -// UnimplementedFS is an FS that returns ENOSYS for all functions, -// This should be embedded to have forward compatible implementations. -type UnimplementedFS struct{} - -// String implements fmt.Stringer -func (UnimplementedFS) String() string { - return "Unimplemented:/" -} - -// Open implements the same method as documented on fs.FS -func (UnimplementedFS) Open(name string) (fs.File, error) { - return nil, &fs.PathError{Op: "open", Path: name, Err: experimentalsys.ENOSYS} -} - -// OpenFile implements FS.OpenFile -func (UnimplementedFS) OpenFile(path string, flag Oflag, perm fs.FileMode) (File, experimentalsys.Errno) { - return nil, experimentalsys.ENOSYS -} - -// Lstat implements FS.Lstat -func (UnimplementedFS) Lstat(path string) (sys.Stat_t, experimentalsys.Errno) { - return sys.Stat_t{}, experimentalsys.ENOSYS -} - -// Stat implements FS.Stat -func (UnimplementedFS) Stat(path string) (sys.Stat_t, experimentalsys.Errno) { - return sys.Stat_t{}, experimentalsys.ENOSYS -} - -// Readlink implements FS.Readlink -func (UnimplementedFS) Readlink(path string) (string, experimentalsys.Errno) { - return "", experimentalsys.ENOSYS -} - -// Mkdir implements FS.Mkdir -func (UnimplementedFS) Mkdir(path string, perm fs.FileMode) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Chmod implements FS.Chmod -func (UnimplementedFS) Chmod(path string, perm fs.FileMode) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Rename implements FS.Rename -func (UnimplementedFS) Rename(from, to string) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Rmdir implements FS.Rmdir -func (UnimplementedFS) Rmdir(path string) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Link implements FS.Link -func (UnimplementedFS) Link(_, _ string) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Symlink implements FS.Symlink -func (UnimplementedFS) Symlink(_, _ string) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Unlink implements FS.Unlink -func (UnimplementedFS) Unlink(path string) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Utimens implements FS.Utimens -func (UnimplementedFS) Utimens(path string, atim, mtim int64) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Truncate implements FS.Truncate -func (UnimplementedFS) Truncate(string, int64) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// UnimplementedFile is a File that returns ENOSYS for all functions, -// except where no-op are otherwise documented. -// -// This should be embedded to have forward compatible implementations. -type UnimplementedFile struct{} - -// Dev implements File.Dev -func (UnimplementedFile) Dev() (uint64, experimentalsys.Errno) { - return 0, 0 -} - -// Ino implements File.Ino -func (UnimplementedFile) Ino() (sys.Inode, experimentalsys.Errno) { - return 0, 0 -} - -// IsDir implements File.IsDir -func (UnimplementedFile) IsDir() (bool, experimentalsys.Errno) { - return false, 0 -} - -// IsAppend implements File.IsAppend -func (UnimplementedFile) IsAppend() bool { - return false -} - -// SetAppend implements File.SetAppend -func (UnimplementedFile) SetAppend(bool) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// IsNonblock implements File.IsNonblock -func (UnimplementedFile) IsNonblock() bool { - return false -} - -// SetNonblock implements File.SetNonblock -func (UnimplementedFile) SetNonblock(bool) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Stat implements File.Stat -func (UnimplementedFile) Stat() (sys.Stat_t, experimentalsys.Errno) { - return sys.Stat_t{}, experimentalsys.ENOSYS -} - -// Read implements File.Read -func (UnimplementedFile) Read([]byte) (int, experimentalsys.Errno) { - return 0, experimentalsys.ENOSYS -} - -// Pread implements File.Pread -func (UnimplementedFile) Pread([]byte, int64) (int, experimentalsys.Errno) { - return 0, experimentalsys.ENOSYS -} - -// Seek implements File.Seek -func (UnimplementedFile) Seek(int64, int) (int64, experimentalsys.Errno) { - return 0, experimentalsys.ENOSYS -} - -// Readdir implements File.Readdir -func (UnimplementedFile) Readdir(int) (dirents []Dirent, errno experimentalsys.Errno) { - return nil, experimentalsys.ENOSYS -} - -// Poll implements File.Poll -func (UnimplementedFile) Poll(Pflag, int32) (ready bool, errno experimentalsys.Errno) { - return false, experimentalsys.ENOSYS -} - -// Write implements File.Write -func (UnimplementedFile) Write([]byte) (int, experimentalsys.Errno) { - return 0, experimentalsys.ENOSYS -} - -// Pwrite implements File.Pwrite -func (UnimplementedFile) Pwrite([]byte, int64) (int, experimentalsys.Errno) { - return 0, experimentalsys.ENOSYS -} - -// Truncate implements File.Truncate -func (UnimplementedFile) Truncate(int64) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Sync implements File.Sync -func (UnimplementedFile) Sync() experimentalsys.Errno { - return 0 // not ENOSYS -} - -// Datasync implements File.Datasync -func (UnimplementedFile) Datasync() experimentalsys.Errno { - return 0 // not ENOSYS -} - -// Utimens implements File.Utimens -func (UnimplementedFile) Utimens(int64, int64) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Close implements File.Close -func (UnimplementedFile) Close() (errno experimentalsys.Errno) { return } diff --git a/internal/gojs/fs.go b/internal/gojs/fs.go index d0cd422ef3..ca15655791 100644 --- a/internal/gojs/fs.go +++ b/internal/gojs/fs.go @@ -6,7 +6,6 @@ import ( "github.com/tetratelabs/wazero/api" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/gojs/custom" "github.com/tetratelabs/wazero/internal/gojs/goos" "github.com/tetratelabs/wazero/internal/gojs/util" @@ -28,22 +27,22 @@ var ( }) // oWRONLY = jsfsConstants Get("O_WRONLY").Int() // fs_js.go init - oWRONLY = float64(fsapi.O_WRONLY) + oWRONLY = float64(experimentalsys.O_WRONLY) // oRDWR = jsfsConstants Get("O_RDWR").Int() // fs_js.go init - oRDWR = float64(fsapi.O_RDWR) + oRDWR = float64(experimentalsys.O_RDWR) // o CREAT = jsfsConstants Get("O_CREAT").Int() // fs_js.go init - oCREAT = float64(fsapi.O_CREAT) + oCREAT = float64(experimentalsys.O_CREAT) // oTRUNC = jsfsConstants Get("O_TRUNC").Int() // fs_js.go init - oTRUNC = float64(fsapi.O_TRUNC) + oTRUNC = float64(experimentalsys.O_TRUNC) // oAPPEND = jsfsConstants Get("O_APPEND").Int() // fs_js.go init - oAPPEND = float64(fsapi.O_APPEND) + oAPPEND = float64(experimentalsys.O_APPEND) // oEXCL = jsfsConstants Get("O_EXCL").Int() // fs_js.go init - oEXCL = float64(fsapi.O_EXCL) + oEXCL = float64(experimentalsys.O_EXCL) ) // jsfs = js.Global().Get("fs") // fs_js.go init @@ -91,9 +90,9 @@ type jsfsOpen struct { func (o *jsfsOpen) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) { path := util.ResolvePath(o.proc.cwd, args[0].(string)) - // Note: these are already fsapi.Flag because Go uses constants we define: + // Note: these are already sys.Flag because Go uses constants we define: // https://github.com/golang/go/blob/go1.20/src/syscall/fs_js.go#L24-L31 - flags := fsapi.Oflag(toUint64(args[1])) + flags := experimentalsys.Oflag(toUint64(args[1])) perm := custom.FromJsMode(goos.ValueToUint32(args[2]), o.proc.umask) callback := args[3].(funcWrapper) @@ -319,7 +318,7 @@ func syscallReaddir(_ context.Context, mod api.Module, name string) (*objectArra fsc := mod.(*wasm.ModuleInstance).Sys.FS() // don't allocate a file descriptor - f, errno := fsc.RootFS().OpenFile(name, fsapi.O_RDONLY, 0) + f, errno := fsc.RootFS().OpenFile(name, experimentalsys.O_RDONLY, 0) if errno != 0 { return nil, errno } @@ -358,7 +357,7 @@ func (m *jsfsMkdir) invoke(ctx context.Context, mod api.Module, args ...interfac perm = 0o0500 } if errno = root.Mkdir(path, perm); errno == 0 { - fd, errno = fsc.OpenFile(root, path, fsapi.O_RDONLY, 0) + fd, errno = fsc.OpenFile(root, path, experimentalsys.O_RDONLY, 0) } return callback.invoke(ctx, mod, goos.RefJsfs, maybeError(errno), fd) // note: error first diff --git a/internal/sock/sock.go b/internal/sock/sock.go index c49d1fbb22..ca17aa39ee 100644 --- a/internal/sock/sock.go +++ b/internal/sock/sock.go @@ -5,25 +5,24 @@ import ( "net" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) // TCPSock is a pseudo-file representing a TCP socket. type TCPSock interface { - fsapi.File + sys.File Accept() (TCPConn, sys.Errno) } // TCPConn is a pseudo-file representing a TCP connection. type TCPConn interface { - fsapi.File + sys.File // Recvfrom only supports the flag sysfs.MSG_PEEK - // TODO: document this like fsapi.File with known sys.Errno + // TODO: document this like sys.File with known sys.Errno Recvfrom(p []byte, flags int) (n int, errno sys.Errno) - // TODO: document this like fsapi.File with known sys.Errno + // TODO: document this like sys.File with known sys.Errno Shutdown(how int) sys.Errno } diff --git a/internal/sys/fs.go b/internal/sys/fs.go index 26d993b75f..2d1ce51941 100644 --- a/internal/sys/fs.go +++ b/internal/sys/fs.go @@ -7,7 +7,6 @@ import ( "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/internal/descriptor" - "github.com/tetratelabs/wazero/internal/fsapi" socketapi "github.com/tetratelabs/wazero/internal/sock" "github.com/tetratelabs/wazero/internal/sysfs" ) @@ -48,10 +47,10 @@ type FileEntry struct { IsPreopen bool // FS is the filesystem associated with the pre-open. - FS fsapi.FS + FS sys.FS // File is always non-nil. - File fsapi.File + File sys.File // direntCache is nil until DirentCache was called. direntCache *DirentCache @@ -91,7 +90,7 @@ func (f *FileEntry) DirentCache() (*DirentCache, sys.Errno) { return f.direntCache, 0 } -// DirentCache is a caching abstraction of fsapi.File Readdir. +// DirentCache is a caching abstraction of sys.File Readdir. // // This is special-cased for "wasi_snapshot_preview1.fd_readdir", and may be // unneeded, or require changes, to support preview1 or preview2. @@ -99,7 +98,7 @@ func (f *FileEntry) DirentCache() (*DirentCache, sys.Errno) { // described below, any may need to be re-read. This accepts any positions // in the cache, rather than track the position of the last dirent. // - dot entries ("." and "..") must be returned. See /RATIONALE.md for why. -// - An fsapi.Dirent Name is variable length, it could exceed memory size and +// - An sys.Dirent Name is variable length, it could exceed memory size and // need to be re-read. // - Multiple dirents may be returned. It is more efficient to read from the // underlying file in bulk vs one-at-a-time. @@ -110,17 +109,17 @@ func (f *FileEntry) DirentCache() (*DirentCache, sys.Errno) { // approach is sometimes called a sliding window. type DirentCache struct { // f is the underlying file - f fsapi.File + f sys.File // dotEntries are the "." and ".." entries added when the directory is // initialized. - dotEntries []fsapi.Dirent + dotEntries []sys.Dirent // dirents are the potentially unread directory entries. // // Internal detail: nil is different from zero length. Zero length is an // exhausted directory (eof). nil means the re-read. - dirents []fsapi.Dirent + dirents []sys.Dirent // countRead is the total count of dirents read since last rewind. countRead uint64 @@ -132,28 +131,28 @@ type DirentCache struct { } // synthesizeDotEntries generates a slice of the two elements "." and "..". -func synthesizeDotEntries(f *FileEntry) ([]fsapi.Dirent, sys.Errno) { +func synthesizeDotEntries(f *FileEntry) ([]sys.Dirent, sys.Errno) { dotIno, errno := f.File.Ino() if errno != 0 { return nil, errno } - result := [2]fsapi.Dirent{} - result[0] = fsapi.Dirent{Name: ".", Ino: dotIno, Type: fs.ModeDir} + result := [2]sys.Dirent{} + result[0] = sys.Dirent{Name: ".", Ino: dotIno, Type: fs.ModeDir} // See /RATIONALE.md for why we don't attempt to get an inode for ".." and // why in wasi-libc this won't fan-out either. - result[1] = fsapi.Dirent{Name: "..", Ino: 0, Type: fs.ModeDir} + result[1] = sys.Dirent{Name: "..", Ino: 0, Type: fs.ModeDir} return result[:], 0 } // exhaustedDirents avoids allocating empty slices. -var exhaustedDirents = [0]fsapi.Dirent{} +var exhaustedDirents = [0]sys.Dirent{} -// Read is similar to and returns the same errors as `Readdir` on fsapi.File. +// Read is similar to and returns the same errors as `Readdir` on sys.File. // The main difference is this caches entries returned, resulting in multiple // valid positions to read from. // // When zero, `pos` means rewind to the beginning of this directory. This -// implies a rewind (Seek to zero on the underlying fsapi.File), unless the +// implies a rewind (Seek to zero on the underlying sys.File), unless the // initial entries are still cached. // // When non-zero, `pos` is the zero based index of all dirents returned since @@ -162,9 +161,9 @@ var exhaustedDirents = [0]fsapi.Dirent{} // described on DirentCache documentation. // // Up to `n` entries are cached and returned. When `n` exceeds the cache, the -// difference are read from the underlying fsapi.File via `Readdir`. EOF is +// difference are read from the underlying sys.File via `Readdir`. EOF is // when `len(dirents)` returned are less than `n`. -func (d *DirentCache) Read(pos uint64, n uint32) (dirents []fsapi.Dirent, errno sys.Errno) { +func (d *DirentCache) Read(pos uint64, n uint32) (dirents []sys.Dirent, errno sys.Errno) { switch { case pos > d.countRead: // farther than read or negative coerced to uint64. return nil, sys.ENOENT @@ -239,7 +238,7 @@ func (d *DirentCache) Read(pos uint64, n uint32) (dirents []fsapi.Dirent, errno } // cachedDirents returns up to `n` dirents from the cache. -func (d *DirentCache) cachedDirents(n uint32) []fsapi.Dirent { +func (d *DirentCache) cachedDirents(n uint32) []sys.Dirent { direntCount := uint32(len(d.dirents)) switch { case direntCount == 0: @@ -252,7 +251,7 @@ func (d *DirentCache) cachedDirents(n uint32) []fsapi.Dirent { type FSContext struct { // rootFS is the root ("/") mount. - rootFS fsapi.FS + rootFS sys.FS // openedFiles is a map of file descriptor numbers (>=FdPreopen) to open files // (or directories) and defaults to empty. @@ -269,9 +268,9 @@ type FileTable = descriptor.Table[int32, *FileEntry] // // TODO: This is only used by GOOS=js and tests: Remove when we remove GOOS=js // (after Go 1.22 is released). -func (c *FSContext) RootFS() fsapi.FS { +func (c *FSContext) RootFS() sys.FS { if rootFS := c.rootFS; rootFS == nil { - return fsapi.UnimplementedFS{} + return sys.UnimplementedFS{} } else { return rootFS } @@ -284,7 +283,7 @@ func (c *FSContext) LookupFile(fd int32) (*FileEntry, bool) { // OpenFile opens the file into the table and returns its file descriptor. // The result must be closed by CloseFile or Close. -func (c *FSContext) OpenFile(fs fsapi.FS, path string, flag fsapi.Oflag, perm fs.FileMode) (int32, sys.Errno) { +func (c *FSContext) OpenFile(fs sys.FS, path string, flag sys.Oflag, perm fs.FileMode) (int32, sys.Errno) { if f, errno := fs.OpenFile(path, flag, perm); errno != 0 { return 0, errno } else { @@ -391,7 +390,7 @@ func (c *FSContext) Close() (err error) { func (c *Context) InitFSContext( stdin io.Reader, stdout, stderr io.Writer, - fs []fsapi.FS, guestPaths []string, + fs []sys.FS, guestPaths []string, tcpListeners []*net.TCPListener, ) (err error) { inFile, err := stdinFileEntry(stdin) diff --git a/internal/sys/fs_test.go b/internal/sys/fs_test.go index b3e581405b..33031b9018 100644 --- a/internal/sys/fs_test.go +++ b/internal/sys/fs_test.go @@ -11,7 +11,6 @@ import ( gofstest "testing/fstest" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/sysfs" testfs "github.com/tetratelabs/wazero/internal/testing/fs" @@ -30,7 +29,7 @@ func TestNewFSContext(t *testing.T) { // Test various usual configuration for the file system. tests := []struct { name string - fs fsapi.FS + fs sys.FS }{ { name: "embed.FS", @@ -59,7 +58,7 @@ func TestNewFSContext(t *testing.T) { for _, root := range []string{"/", ""} { t.Run(fmt.Sprintf("root = '%s'", root), func(t *testing.T) { c := Context{} - err := c.InitFSContext(nil, nil, nil, []fsapi.FS{tc.fs}, []string{root}, nil) + err := c.InitFSContext(nil, nil, nil, []sys.FS{tc.fs}, []string{root}, nil) require.NoError(t, err) fsc := c.fsc defer fsc.Close() @@ -100,15 +99,15 @@ func TestFSContext_CloseFile(t *testing.T) { testFS := sysfs.Adapt(embedFS) c := Context{} - err = c.InitFSContext(nil, nil, nil, []fsapi.FS{testFS}, []string{"/"}, nil) + err = c.InitFSContext(nil, nil, nil, []sys.FS{testFS}, []string{"/"}, nil) require.NoError(t, err) fsc := c.fsc defer fsc.Close() - fdToClose, errno := fsc.OpenFile(testFS, "empty.txt", fsapi.O_RDONLY, 0) + fdToClose, errno := fsc.OpenFile(testFS, "empty.txt", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) - fdToKeep, errno := fsc.OpenFile(testFS, "test.txt", fsapi.O_RDONLY, 0) + fdToKeep, errno := fsc.OpenFile(testFS, "test.txt", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) // Close @@ -158,14 +157,14 @@ func TestContext_Close(t *testing.T) { testFS := sysfs.Adapt(testfs.FS{"foo": &testfs.File{}}) c := Context{} - err := c.InitFSContext(nil, nil, nil, []fsapi.FS{testFS}, []string{"/"}, nil) + err := c.InitFSContext(nil, nil, nil, []sys.FS{testFS}, []string{"/"}, nil) require.NoError(t, err) fsc := c.fsc // Verify base case require.Equal(t, 1+FdPreopen, int32(fsc.openedFiles.Len())) - _, errno := fsc.OpenFile(testFS, "foo", fsapi.O_RDONLY, 0) + _, errno := fsc.OpenFile(testFS, "foo", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) require.Equal(t, 2+FdPreopen, int32(fsc.openedFiles.Len())) @@ -185,12 +184,12 @@ func TestContext_Close_Error(t *testing.T) { testFS := sysfs.Adapt(testfs.FS{"foo": file}) c := Context{} - err := c.InitFSContext(nil, nil, nil, []fsapi.FS{testFS}, []string{"/"}, nil) + err := c.InitFSContext(nil, nil, nil, []sys.FS{testFS}, []string{"/"}, nil) require.NoError(t, err) fsc := c.fsc // open another file - _, errno := fsc.OpenFile(testFS, "foo", fsapi.O_RDONLY, 0) + _, errno := fsc.OpenFile(testFS, "foo", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) // arbitrary errors coerce to EIO @@ -209,14 +208,14 @@ func TestFSContext_Renumber(t *testing.T) { require.EqualErrno(t, 0, errno) c := Context{} - err := c.InitFSContext(nil, nil, nil, []fsapi.FS{dirFS}, []string{"/"}, nil) + err := c.InitFSContext(nil, nil, nil, []sys.FS{dirFS}, []string{"/"}, nil) require.NoError(t, err) fsc := c.fsc defer fsc.Close() for _, toFd := range []int32{10, 100, 100} { - fromFd, errno := fsc.OpenFile(dirFS, dirName, fsapi.O_RDONLY, 0) + fromFd, errno := fsc.OpenFile(dirFS, dirName, sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) prevDirFile, ok := fsc.LookupFile(fromFd) @@ -253,7 +252,7 @@ func TestFSContext_Renumber(t *testing.T) { func TestDirentCache_Read(t *testing.T) { c := Context{} - err := c.InitFSContext(nil, nil, nil, []fsapi.FS{sysfs.Adapt(fstest.FS)}, []string{"/"}, nil) + err := c.InitFSContext(nil, nil, nil, []sys.FS{sysfs.Adapt(fstest.FS)}, []string{"/"}, nil) require.NoError(t, err) fsc := c.fsc defer fsc.Close() @@ -266,7 +265,7 @@ func TestDirentCache_Read(t *testing.T) { if errno != 0 { panic(errno) } - testDirents = append([]fsapi.Dirent{ + testDirents = append([]sys.Dirent{ {Name: ".", Type: fs.ModeDir}, {Name: "..", Type: fs.ModeDir}, }, testDirents...) @@ -278,7 +277,7 @@ func TestDirentCache_Read(t *testing.T) { fd int32 pos uint64 n uint32 - expectedDirents []fsapi.Dirent + expectedDirents []sys.Dirent expectedErrno sys.Errno }{ { @@ -405,7 +404,7 @@ func TestDirentCache_Read(t *testing.T) { for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { - fd, errno := fsc.OpenFile(fsc.RootFS(), tc.initialDir, fsapi.O_RDONLY, 0) + fd, errno := fsc.OpenFile(fsc.RootFS(), tc.initialDir, sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer fsc.CloseFile(fd) // nolint f, _ := fsc.LookupFile(fd) @@ -431,12 +430,12 @@ func TestDirentCache_ReadNewFile(t *testing.T) { tmpDir := t.TempDir() c := Context{} - err := c.InitFSContext(nil, nil, nil, []fsapi.FS{sysfs.NewDirFS(tmpDir)}, []string{"/"}, nil) + err := c.InitFSContext(nil, nil, nil, []sys.FS{sysfs.NewDirFS(tmpDir)}, []string{"/"}, nil) require.NoError(t, err) fsc := c.fsc defer fsc.Close() - fd, errno := fsc.OpenFile(fsc.RootFS(), ".", fsapi.O_RDONLY, 0) + fd, errno := fsc.OpenFile(fsc.RootFS(), ".", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer fsc.CloseFile(fd) // nolint f, _ := fsc.LookupFile(fd) diff --git a/internal/sys/lazy.go b/internal/sys/lazy.go index 1cb01a192e..0deb79c589 100644 --- a/internal/sys/lazy.go +++ b/internal/sys/lazy.go @@ -2,21 +2,20 @@ package sys import ( experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/sys" ) -// compile-time check to ensure lazyDir implements fsapi.File. -var _ fsapi.File = (*lazyDir)(nil) +// compile-time check to ensure lazyDir implements sys.File. +var _ experimentalsys.File = (*lazyDir)(nil) type lazyDir struct { - fsapi.DirFile + experimentalsys.DirFile - fs fsapi.FS - f fsapi.File + fs experimentalsys.FS + f experimentalsys.File } -// Dev implements the same method as documented on fsapi.File +// Dev implements the same method as documented on sys.File func (r *lazyDir) Dev() (uint64, experimentalsys.Errno) { if f, ok := r.file(); !ok { return 0, experimentalsys.EBADF @@ -25,7 +24,7 @@ func (r *lazyDir) Dev() (uint64, experimentalsys.Errno) { } } -// Ino implements the same method as documented on fsapi.File +// Ino implements the same method as documented on sys.File func (r *lazyDir) Ino() (sys.Inode, experimentalsys.Errno) { if f, ok := r.file(); !ok { return 0, experimentalsys.EBADF @@ -34,7 +33,7 @@ func (r *lazyDir) Ino() (sys.Inode, experimentalsys.Errno) { } } -// IsDir implements the same method as documented on fsapi.File +// IsDir implements the same method as documented on sys.File func (r *lazyDir) IsDir() (bool, experimentalsys.Errno) { // Note: we don't return a constant because we don't know if this is really // backed by a dir, until the first call. @@ -45,17 +44,17 @@ func (r *lazyDir) IsDir() (bool, experimentalsys.Errno) { } } -// IsAppend implements the same method as documented on fsapi.File +// IsAppend implements the same method as documented on sys.File func (r *lazyDir) IsAppend() bool { return false } -// SetAppend implements the same method as documented on fsapi.File +// SetAppend implements the same method as documented on sys.File func (r *lazyDir) SetAppend(bool) experimentalsys.Errno { return experimentalsys.EISDIR } -// Seek implements the same method as documented on fsapi.File +// Seek implements the same method as documented on sys.File func (r *lazyDir) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) { if f, ok := r.file(); !ok { return 0, experimentalsys.EBADF @@ -64,7 +63,7 @@ func (r *lazyDir) Seek(offset int64, whence int) (newOffset int64, errno experim } } -// Stat implements the same method as documented on fsapi.File +// Stat implements the same method as documented on sys.File func (r *lazyDir) Stat() (sys.Stat_t, experimentalsys.Errno) { if f, ok := r.file(); !ok { return sys.Stat_t{}, experimentalsys.EBADF @@ -73,8 +72,8 @@ func (r *lazyDir) Stat() (sys.Stat_t, experimentalsys.Errno) { } } -// Readdir implements the same method as documented on fsapi.File -func (r *lazyDir) Readdir(n int) (dirents []fsapi.Dirent, errno experimentalsys.Errno) { +// Readdir implements the same method as documented on sys.File +func (r *lazyDir) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { if f, ok := r.file(); !ok { return nil, experimentalsys.EBADF } else { @@ -82,7 +81,7 @@ func (r *lazyDir) Readdir(n int) (dirents []fsapi.Dirent, errno experimentalsys. } } -// Sync implements the same method as documented on fsapi.File +// Sync implements the same method as documented on sys.File func (r *lazyDir) Sync() experimentalsys.Errno { if f, ok := r.file(); !ok { return experimentalsys.EBADF @@ -91,7 +90,7 @@ func (r *lazyDir) Sync() experimentalsys.Errno { } } -// Datasync implements the same method as documented on fsapi.File +// Datasync implements the same method as documented on sys.File func (r *lazyDir) Datasync() experimentalsys.Errno { if f, ok := r.file(); !ok { return experimentalsys.EBADF @@ -100,7 +99,7 @@ func (r *lazyDir) Datasync() experimentalsys.Errno { } } -// Utimens implements the same method as documented on fsapi.File +// Utimens implements the same method as documented on sys.File func (r *lazyDir) Utimens(atim, mtim int64) experimentalsys.Errno { if f, ok := r.file(); !ok { return experimentalsys.EBADF @@ -110,12 +109,12 @@ func (r *lazyDir) Utimens(atim, mtim int64) experimentalsys.Errno { } // file returns the underlying file or false if it doesn't exist. -func (r *lazyDir) file() (fsapi.File, bool) { +func (r *lazyDir) file() (experimentalsys.File, bool) { if f := r.f; r.f != nil { return f, true } var errno experimentalsys.Errno - r.f, errno = r.fs.OpenFile(".", fsapi.O_RDONLY, 0) + r.f, errno = r.fs.OpenFile(".", experimentalsys.O_RDONLY, 0) switch errno { case 0: return r.f, true diff --git a/internal/sys/stdio.go b/internal/sys/stdio.go index 84ebb06cb3..6a249c3804 100644 --- a/internal/sys/stdio.go +++ b/internal/sys/stdio.go @@ -5,7 +5,6 @@ import ( "os" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/sysfs" "github.com/tetratelabs/wazero/sys" ) @@ -18,7 +17,7 @@ type StdinFile struct { io.Reader } -// Read implements the same method as documented on fsapi.File +// Read implements the same method as documented on sys.File func (f *StdinFile) Read(buf []byte) (int, experimentalsys.Errno) { n, err := f.Reader.Read(buf) return n, experimentalsys.UnwrapOSError(err) @@ -30,7 +29,7 @@ type writerFile struct { w io.Writer } -// Write implements the same method as documented on fsapi.File +// Write implements the same method as documented on sys.File func (f *writerFile) Write(buf []byte) (int, experimentalsys.Errno) { n, err := f.w.Write(buf) return n, experimentalsys.UnwrapOSError(err) @@ -43,14 +42,14 @@ type noopStdinFile struct { noopStdioFile } -// Read implements the same method as documented on fsapi.File +// Read implements the same method as documented on sys.File func (noopStdinFile) Read([]byte) (int, experimentalsys.Errno) { return 0, 0 // Always EOF } -// Poll implements the same method as documented on fsapi.File -func (noopStdinFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { - if flag != fsapi.POLLIN { +// Poll implements the same method as documented on sys.File +func (noopStdinFile) Poll(flag experimentalsys.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { + if flag != experimentalsys.POLLIN { return false, experimentalsys.ENOTSUP } return true, 0 // always ready to read nothing @@ -62,26 +61,26 @@ type noopStdoutFile struct { noopStdioFile } -// Write implements the same method as documented on fsapi.File +// Write implements the same method as documented on sys.File func (noopStdoutFile) Write(buf []byte) (int, experimentalsys.Errno) { return len(buf), 0 // same as io.Discard } type noopStdioFile struct { - fsapi.UnimplementedFile + experimentalsys.UnimplementedFile } -// Stat implements the same method as documented on fsapi.File +// Stat implements the same method as documented on sys.File func (noopStdioFile) Stat() (sys.Stat_t, experimentalsys.Errno) { return sys.Stat_t{Mode: modeDevice, Nlink: 1}, 0 } -// IsDir implements the same method as documented on fsapi.File +// IsDir implements the same method as documented on sys.File func (noopStdioFile) IsDir() (bool, experimentalsys.Errno) { return false, 0 } -// Close implements the same method as documented on fsapi.File +// Close implements the same method as documented on sys.File func (noopStdioFile) Close() (errno experimentalsys.Errno) { return } func stdinFileEntry(r io.Reader) (*FileEntry, error) { diff --git a/internal/sys/sys.go b/internal/sys/sys.go index aedd7c7035..12279ee495 100644 --- a/internal/sys/sys.go +++ b/internal/sys/sys.go @@ -7,7 +7,7 @@ import ( "net" "time" - "github.com/tetratelabs/wazero/internal/fsapi" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/internal/platform" "github.com/tetratelabs/wazero/sys" ) @@ -110,11 +110,11 @@ func (c *Context) RandSource() io.Reader { } // DefaultContext returns Context with no values set except a possible nil -// fsapi.FS. +// sys.FS. // // Note: This is only used for testing. -func DefaultContext(fs fsapi.FS) *Context { - if sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, nil, []fsapi.FS{fs}, []string{""}, nil); err != nil { +func DefaultContext(fs experimentalsys.FS) *Context { + if sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, nil, []experimentalsys.FS{fs}, []string{""}, nil); err != nil { panic(fmt.Errorf("BUG: DefaultContext should never error: %w", err)) } else { return sysCtx @@ -135,7 +135,7 @@ func NewContext( nanotimeResolution sys.ClockResolution, nanosleep sys.Nanosleep, osyield sys.Osyield, - fs []fsapi.FS, guestPaths []string, + fs []experimentalsys.FS, guestPaths []string, tcpListeners []*net.TCPListener, ) (sysCtx *Context, err error) { sysCtx = &Context{args: args, environ: environ} diff --git a/internal/sys/sys_test.go b/internal/sys/sys_test.go index f8d8dfc5b9..ae6270a181 100644 --- a/internal/sys/sys_test.go +++ b/internal/sys/sys_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/tetratelabs/wazero/internal/fsapi" + experimentalsys "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/platform" "github.com/tetratelabs/wazero/internal/sysfs" @@ -22,7 +22,7 @@ func TestContext_WalltimeNanos(t *testing.T) { func TestDefaultSysContext(t *testing.T) { testFS := sysfs.Adapt(fstest.FS) - sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, nil, []fsapi.FS{testFS}, []string{"/"}, nil) + sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, nil, []experimentalsys.FS{testFS}, []string{"/"}, nil) require.NoError(t, err) require.Nil(t, sysCtx.Args()) diff --git a/internal/sysfs/adapter.go b/internal/sysfs/adapter.go index 75d70888c8..bacc0b18f6 100644 --- a/internal/sysfs/adapter.go +++ b/internal/sysfs/adapter.go @@ -6,29 +6,28 @@ import ( "path" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/sys" ) -// Adapt adapts the input to fsapi.FS unless it is already one. Use NewDirFS instead +// Adapt adapts the input to sys.FS unless it is already one. Use NewDirFS instead // of os.DirFS as it handles interop issues such as windows support. // -// Note: This performs no flag verification on OpenFile. fsapi.FS cannot read -// flags as there is no parameter to pass them through with. Moreover, fsapi.FS +// Note: This performs no flag verification on OpenFile. sys.FS cannot read +// flags as there is no parameter to pass them through with. Moreover, sys.FS // documentation does not require the file to be present. In summary, we can't // enforce flag behavior. -func Adapt(fs fs.FS) fsapi.FS { +func Adapt(fs fs.FS) experimentalsys.FS { if fs == nil { - return fsapi.UnimplementedFS{} + return experimentalsys.UnimplementedFS{} } - if sys, ok := fs.(fsapi.FS); ok { + if sys, ok := fs.(experimentalsys.FS); ok { return sys } return &adapter{fs: fs} } type adapter struct { - fsapi.UnimplementedFS + experimentalsys.UnimplementedFS fs fs.FS } @@ -37,14 +36,14 @@ func (a *adapter) String() string { return fmt.Sprintf("%v", a.fs) } -// OpenFile implements the same method as documented on fsapi.FS -func (a *adapter) OpenFile(path string, flag fsapi.Oflag, perm fs.FileMode) (fsapi.File, experimentalsys.Errno) { +// OpenFile implements the same method as documented on sys.FS +func (a *adapter) OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { return OpenFSFile(a.fs, cleanPath(path), flag, perm) } -// Stat implements the same method as documented on fsapi.FS +// Stat implements the same method as documented on sys.FS func (a *adapter) Stat(path string) (sys.Stat_t, experimentalsys.Errno) { - f, errno := a.OpenFile(path, fsapi.O_RDONLY, 0) + f, errno := a.OpenFile(path, experimentalsys.O_RDONLY, 0) if errno != 0 { return sys.Stat_t{}, errno } @@ -52,11 +51,11 @@ func (a *adapter) Stat(path string) (sys.Stat_t, experimentalsys.Errno) { return f.Stat() } -// Lstat implements the same method as documented on fsapi.FS +// Lstat implements the same method as documented on sys.FS func (a *adapter) Lstat(path string) (sys.Stat_t, experimentalsys.Errno) { - // At this time, we make the assumption that fsapi.FS instances do not support + // At this time, we make the assumption that sys.FS instances do not support // symbolic links, therefore Lstat is the same as Stat. This is obviously - // not true but until fsapi.FS has a solid story for how to handle symlinks we + // not true but until sys.FS has a solid story for how to handle symlinks we // are better off not making a decision that would be difficult to revert // later on. // diff --git a/internal/sysfs/adapter_test.go b/internal/sysfs/adapter_test.go index 265d386ca9..fe3d491663 100644 --- a/internal/sysfs/adapter_test.go +++ b/internal/sysfs/adapter_test.go @@ -12,7 +12,6 @@ import ( "testing" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/testing/require" "github.com/tetratelabs/wazero/sys" @@ -20,7 +19,7 @@ import ( func TestAdapt_nil(t *testing.T) { testFS := Adapt(nil) - _, ok := testFS.(fsapi.UnimplementedFS) + _, ok := testFS.(experimentalsys.UnimplementedFS) require.True(t, ok) } @@ -90,12 +89,12 @@ func TestAdapt_UtimesNano(t *testing.T) { realPath := joinPath(tmpDir, path) require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600)) - err := testFS.Utimens(path, fsapi.UTIME_OMIT, fsapi.UTIME_OMIT) + err := testFS.Utimens(path, experimentalsys.UTIME_OMIT, experimentalsys.UTIME_OMIT) require.EqualErrno(t, experimentalsys.ENOSYS, err) } func TestAdapt_Open_Read(t *testing.T) { - // Create a subdirectory, so we can test reads outside the fsapi.FS root. + // Create a subdirectory, so we can test reads outside the sys.FS root. tmpDir := t.TempDir() tmpDir = joinPath(tmpDir, t.Name()) require.NoError(t, os.Mkdir(tmpDir, 0o700)) @@ -107,9 +106,9 @@ func TestAdapt_Open_Read(t *testing.T) { testOpen_Read(t, testFS, statSetsIno(), runtime.GOOS != "windows") t.Run("path outside root invalid", func(t *testing.T) { - _, err := testFS.OpenFile("../foo", fsapi.O_RDONLY, 0) + _, err := testFS.OpenFile("../foo", experimentalsys.O_RDONLY, 0) - // fsapi.FS doesn't allow relative path lookups + // sys.FS doesn't allow relative path lookups require.EqualErrno(t, experimentalsys.EINVAL, err) }) } @@ -137,7 +136,7 @@ func TestAdapt_Stat(t *testing.T) { testStat(t, testFS) } -// hackFS cheats the api.FS contract by opening for write (fsapi.O_RDWR). +// hackFS cheats the api.FS contract by opening for write (sys.O_RDWR). // // Until we have an alternate public interface for filesystems, some users will // rely on this. Via testing, we ensure we don't accidentally break them. @@ -242,7 +241,7 @@ func (i *sysFileInfo) Sys() any { // Windows. // // For example, on Windows, we cannot reliably read the inode for a -// fsapi.Dirent with any of these functions. +// sys.Dirent with any of these functions. type methodsUsedByFsAdapter interface { // fs.File is used to implement `stat`, `read` and `close`. fs.File diff --git a/internal/sysfs/bench_test.go b/internal/sysfs/bench_test.go index b31a7cb815..34620972b6 100644 --- a/internal/sysfs/bench_test.go +++ b/internal/sysfs/bench_test.go @@ -9,11 +9,10 @@ import ( "time" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) func BenchmarkFsFileUtimesNs(b *testing.B) { - f, errno := OpenOSFile(path.Join(b.TempDir(), "file"), fsapi.O_CREAT, 0) + f, errno := OpenOSFile(path.Join(b.TempDir(), "file"), sys.O_CREAT, 0) if errno != 0 { b.Fatal(errno) } @@ -55,7 +54,7 @@ func BenchmarkFsFileRead(b *testing.B) { b.Run(bc.name, func(b *testing.B) { name := "wazero.txt" - f, errno := OpenFSFile(bc.fs, name, fsapi.O_RDONLY, 0) + f, errno := OpenFSFile(bc.fs, name, sys.O_RDONLY, 0) if errno != 0 { b.Fatal(errno) } diff --git a/internal/sysfs/dir.go b/internal/sysfs/dir.go index 5a217394b3..f9823287cf 100644 --- a/internal/sysfs/dir.go +++ b/internal/sysfs/dir.go @@ -4,15 +4,14 @@ import ( "io" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) -func adjustReaddirErr(f fsapi.File, isClosed bool, err error) sys.Errno { +func adjustReaddirErr(f sys.File, isClosed bool, err error) sys.Errno { if err == io.EOF { return 0 // e.g. Readdir on darwin returns io.EOF, but linux doesn't. } else if errno := sys.UnwrapOSError(err); errno != 0 { errno = dirError(f, isClosed, errno) - // Comply with errors allowed on fsapi.File Readdir + // Comply with errors allowed on sys.File Readdir switch errno { case sys.EINVAL: // os.File Readdir can return this return sys.EBADF diff --git a/internal/sysfs/dir_test.go b/internal/sysfs/dir_test.go index ed0cd20f68..8229bdcb9c 100644 --- a/internal/sysfs/dir_test.go +++ b/internal/sysfs/dir_test.go @@ -9,7 +9,6 @@ import ( "testing" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/sysfs" "github.com/tetratelabs/wazero/internal/testing/require" @@ -41,7 +40,7 @@ func TestFSFileReaddir(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { - dotF, errno := sysfs.OpenFSFile(tc.fs, ".", fsapi.O_RDONLY, 0) + dotF, errno := sysfs.OpenFSFile(tc.fs, ".", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer dotF.Close() @@ -75,7 +74,7 @@ func TestFSFileReaddir(t *testing.T) { require.EqualErrno(t, sys.EBADF, errno) }) - fileF, errno := sysfs.OpenFSFile(tc.fs, "empty.txt", fsapi.O_RDONLY, 0) + fileF, errno := sysfs.OpenFSFile(tc.fs, "empty.txt", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer fileF.Close() @@ -84,7 +83,7 @@ func TestFSFileReaddir(t *testing.T) { require.EqualErrno(t, sys.EBADF, errno) }) - dirF, errno := sysfs.OpenFSFile(tc.fs, "dir", fsapi.O_RDONLY, 0) + dirF, errno := sysfs.OpenFSFile(tc.fs, "dir", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer dirF.Close() @@ -102,7 +101,7 @@ func TestFSFileReaddir(t *testing.T) { require.EqualErrno(t, 0, errno) require.Equal(t, 1, len(dirents3)) - dirents := []fsapi.Dirent{dirents1[0], dirents2[0], dirents3[0]} + dirents := []sys.Dirent{dirents1[0], dirents2[0], dirents3[0]} sort.Slice(dirents, func(i, j int) bool { return dirents[i].Name < dirents[j].Name }) requireIno(t, dirents, tc.expectIno) @@ -112,7 +111,7 @@ func TestFSFileReaddir(t *testing.T) { dirents[i].Ino = 0 } - require.Equal(t, []fsapi.Dirent{ + require.Equal(t, []sys.Dirent{ {Name: "-", Type: 0}, {Name: "a-", Type: fs.ModeDir}, {Name: "ab-", Type: 0}, @@ -123,7 +122,7 @@ func TestFSFileReaddir(t *testing.T) { require.EqualErrno(t, 0, errno) }) - subdirF, errno := sysfs.OpenFSFile(tc.fs, "sub", fsapi.O_RDONLY, 0) + subdirF, errno := sysfs.OpenFSFile(tc.fs, "sub", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer subdirF.Close() @@ -140,7 +139,7 @@ func TestFSFileReaddir(t *testing.T) { } } -func testReaddirAll(t *testing.T, dotF fsapi.File, expectDirIno bool) { +func testReaddirAll(t *testing.T, dotF sys.File, expectDirIno bool) { dirents, errno := dotF.Readdir(-1) require.EqualErrno(t, 0, errno) // no io.EOF when -1 is used sort.Slice(dirents, func(i, j int) bool { return dirents[i].Name < dirents[j].Name }) @@ -152,7 +151,7 @@ func testReaddirAll(t *testing.T, dotF fsapi.File, expectDirIno bool) { dirents[i].Ino = 0 } - require.Equal(t, []fsapi.Dirent{ + require.Equal(t, []sys.Dirent{ {Name: "animals.txt", Type: 0}, {Name: "dir", Type: fs.ModeDir}, {Name: "empty.txt", Type: 0}, @@ -161,7 +160,7 @@ func testReaddirAll(t *testing.T, dotF fsapi.File, expectDirIno bool) { }, dirents) } -func requireIno(t *testing.T, dirents []fsapi.Dirent, expectDirIno bool) { +func requireIno(t *testing.T, dirents []sys.Dirent, expectDirIno bool) { for _, e := range dirents { if expectDirIno { require.NotEqual(t, uint64(0), e.Ino, "%+v", e) diff --git a/internal/sysfs/dirfs.go b/internal/sysfs/dirfs.go index 714610a403..3fc13d8e2e 100644 --- a/internal/sysfs/dirfs.go +++ b/internal/sysfs/dirfs.go @@ -5,12 +5,11 @@ import ( "os" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/platform" "github.com/tetratelabs/wazero/sys" ) -func NewDirFS(dir string) fsapi.FS { +func NewDirFS(dir string) experimentalsys.FS { return &dirFS{ dir: dir, cleanedDir: ensureTrailingPathSeparator(dir), @@ -25,7 +24,7 @@ func ensureTrailingPathSeparator(dir string) string { } type dirFS struct { - fsapi.UnimplementedFS + experimentalsys.UnimplementedFS dir string // cleanedDir is for easier OS-specific concatenation, as it always has // a trailing path separator. @@ -37,22 +36,22 @@ func (d *dirFS) String() string { return d.dir } -// OpenFile implements the same method as documented on fsapi.FS -func (d *dirFS) OpenFile(path string, flag fsapi.Oflag, perm fs.FileMode) (fsapi.File, experimentalsys.Errno) { +// OpenFile implements the same method as documented on sys.FS +func (d *dirFS) OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { return OpenOSFile(d.join(path), flag, perm) } -// Lstat implements the same method as documented on fsapi.FS +// Lstat implements the same method as documented on sys.FS func (d *dirFS) Lstat(path string) (sys.Stat_t, experimentalsys.Errno) { return lstat(d.join(path)) } -// Stat implements the same method as documented on fsapi.FS +// Stat implements the same method as documented on sys.FS func (d *dirFS) Stat(path string) (sys.Stat_t, experimentalsys.Errno) { return stat(d.join(path)) } -// Mkdir implements the same method as documented on fsapi.FS +// Mkdir implements the same method as documented on sys.FS func (d *dirFS) Mkdir(path string, perm fs.FileMode) (errno experimentalsys.Errno) { err := os.Mkdir(d.join(path), perm) if errno = experimentalsys.UnwrapOSError(err); errno == experimentalsys.ENOTDIR { @@ -61,19 +60,19 @@ func (d *dirFS) Mkdir(path string, perm fs.FileMode) (errno experimentalsys.Errn return } -// Chmod implements the same method as documented on fsapi.FS +// Chmod implements the same method as documented on sys.FS func (d *dirFS) Chmod(path string, perm fs.FileMode) experimentalsys.Errno { err := os.Chmod(d.join(path), perm) return experimentalsys.UnwrapOSError(err) } -// Rename implements the same method as documented on fsapi.FS +// Rename implements the same method as documented on sys.FS func (d *dirFS) Rename(from, to string) experimentalsys.Errno { from, to = d.join(from), d.join(to) return rename(from, to) } -// Readlink implements the same method as documented on fsapi.FS +// Readlink implements the same method as documented on sys.FS func (d *dirFS) Readlink(path string) (string, experimentalsys.Errno) { // Note: do not use syscall.Readlink as that causes race on Windows. // In any case, syscall.Readlink does almost the same logic as os.Readlink. @@ -84,23 +83,23 @@ func (d *dirFS) Readlink(path string) (string, experimentalsys.Errno) { return platform.ToPosixPath(dst), 0 } -// Link implements the same method as documented on fsapi.FS +// Link implements the same method as documented on sys.FS func (d *dirFS) Link(oldName, newName string) experimentalsys.Errno { err := os.Link(d.join(oldName), d.join(newName)) return experimentalsys.UnwrapOSError(err) } -// Rmdir implements the same method as documented on fsapi.FS +// Rmdir implements the same method as documented on sys.FS func (d *dirFS) Rmdir(path string) experimentalsys.Errno { return rmdir(d.join(path)) } -// Unlink implements the same method as documented on fsapi.FS +// Unlink implements the same method as documented on sys.FS func (d *dirFS) Unlink(path string) (err experimentalsys.Errno) { return unlink(d.join(path)) } -// Symlink implements the same method as documented on fsapi.FS +// Symlink implements the same method as documented on sys.FS func (d *dirFS) Symlink(oldName, link string) experimentalsys.Errno { // Note: do not resolve `oldName` relative to this dirFS. The link result is always resolved // when dereference the `link` on its usage (e.g. readlink, read, etc). @@ -109,7 +108,7 @@ func (d *dirFS) Symlink(oldName, link string) experimentalsys.Errno { return experimentalsys.UnwrapOSError(err) } -// Utimens implements the same method as documented on fsapi.FS +// Utimens implements the same method as documented on sys.FS func (d *dirFS) Utimens(path string, atim, mtim int64) experimentalsys.Errno { return utimens(d.join(path), atim, mtim) } diff --git a/internal/sysfs/dirfs_test.go b/internal/sysfs/dirfs_test.go index b13146a0d5..08b7a78220 100644 --- a/internal/sysfs/dirfs_test.go +++ b/internal/sysfs/dirfs_test.go @@ -11,7 +11,6 @@ import ( "time" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/platform" "github.com/tetratelabs/wazero/internal/testing/require" @@ -21,20 +20,20 @@ func TestNewDirFS(t *testing.T) { testFS := NewDirFS(".") // Guest can look up / - f, errno := testFS.OpenFile("/", fsapi.O_RDONLY, 0) + f, errno := testFS.OpenFile("/", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) require.EqualErrno(t, 0, f.Close()) t.Run("host path not found", func(t *testing.T) { testFS := NewDirFS("a") - _, errno = testFS.OpenFile(".", fsapi.O_RDONLY, 0) + _, errno = testFS.OpenFile(".", sys.O_RDONLY, 0) require.EqualErrno(t, sys.ENOENT, errno) }) t.Run("host path not a directory", func(t *testing.T) { arg0 := os.Args[0] // should be safe in scratch tests which don't have the source mounted. testFS := NewDirFS(arg0) - d, errno := testFS.OpenFile(".", fsapi.O_RDONLY, 0) + d, errno := testFS.OpenFile(".", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) _, errno = d.Readdir(-1) require.EqualErrno(t, sys.EBADF, errno) @@ -128,7 +127,7 @@ func TestDirFS_MkDir(t *testing.T) { }) } -func testChmod(t *testing.T, testFS fsapi.FS, path string) { +func testChmod(t *testing.T, testFS sys.FS, path string) { // Test base case, using 0o444 not 0o400 for read-back on windows. requireMode(t, testFS, path, 0o444) @@ -143,7 +142,7 @@ func testChmod(t *testing.T, testFS fsapi.FS, path string) { } } -func requireMode(t *testing.T, testFS fsapi.FS, path string, mode fs.FileMode) { +func requireMode(t *testing.T, testFS sys.FS, path string, mode fs.FileMode) { st, errno := testFS.Stat(path) require.EqualErrno(t, 0, errno) @@ -433,7 +432,7 @@ func TestDirFS_Rmdir(t *testing.T) { realPath := path.Join(tmpDir, name) require.NoError(t, os.Mkdir(realPath, 0o700)) - f, errno := testFS.OpenFile(name, fsapi.O_DIRECTORY, 0o700) + f, errno := testFS.OpenFile(name, sys.O_DIRECTORY, 0o700) require.EqualErrno(t, 0, errno) defer f.Close() @@ -547,17 +546,17 @@ func TestDirFS_Utimesns(t *testing.T) { }, { name: "a=omit,m=omit", - atim: fsapi.UTIME_OMIT, - mtim: fsapi.UTIME_OMIT, + atim: sys.UTIME_OMIT, + mtim: sys.UTIME_OMIT, }, { name: "a=set,m=omit", atim: int64(123*time.Second + 4*time.Microsecond), - mtim: fsapi.UTIME_OMIT, + mtim: sys.UTIME_OMIT, }, { name: "a=omit,m=set", - atim: fsapi.UTIME_OMIT, + atim: sys.UTIME_OMIT, mtim: int64(123*time.Second + 4*time.Microsecond), }, { @@ -613,7 +612,7 @@ func TestDirFS_Utimesns(t *testing.T) { require.EqualErrno(t, 0, errno) if platform.CompilerSupported() { - if tc.atim == fsapi.UTIME_OMIT { + if tc.atim == sys.UTIME_OMIT { require.Equal(t, oldSt.Atim, newSt.Atim) } else { require.Equal(t, tc.atim, newSt.Atim) @@ -621,7 +620,7 @@ func TestDirFS_Utimesns(t *testing.T) { } // When compiler isn't supported, we can still check mtim. - if tc.mtim == fsapi.UTIME_OMIT { + if tc.mtim == sys.UTIME_OMIT { require.Equal(t, oldSt.Mtim, newSt.Mtim) } else { require.Equal(t, tc.mtim, newSt.Mtim) @@ -634,7 +633,7 @@ func TestDirFS_Utimesns(t *testing.T) { func TestDirFS_OpenFile(t *testing.T) { tmpDir := t.TempDir() - // Create a subdirectory, so we can test reads outside the fsapi.FS root. + // Create a subdirectory, so we can test reads outside the sys.FS root. tmpDir = path.Join(tmpDir, t.Name()) require.NoError(t, os.Mkdir(tmpDir, 0o700)) require.NoError(t, fstest.WriteTestFiles(tmpDir)) @@ -646,9 +645,9 @@ func TestDirFS_OpenFile(t *testing.T) { testOpen_O_RDWR(t, tmpDir, testFS) t.Run("path outside root valid", func(t *testing.T) { - _, err := testFS.OpenFile("../foo", fsapi.O_RDONLY, 0) + _, err := testFS.OpenFile("../foo", sys.O_RDONLY, 0) - // fsapi.FS allows relative path lookups + // sys.FS allows relative path lookups require.True(t, errors.Is(err, fs.ErrNotExist)) }) } @@ -681,7 +680,7 @@ func TestDirFS_Readdir(t *testing.T) { require.EqualErrno(t, 0, errno) // Open the empty directory - dirFile, errno := testFS.OpenFile(readDirTarget, fsapi.O_RDONLY, 0) + dirFile, errno := testFS.OpenFile(readDirTarget, sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer dirFile.Close() diff --git a/internal/sysfs/file.go b/internal/sysfs/file.go index b9b96076c0..dc686014f1 100644 --- a/internal/sysfs/file.go +++ b/internal/sysfs/file.go @@ -7,11 +7,10 @@ import ( "time" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/sys" ) -func NewStdioFile(stdin bool, f fs.File) (fsapi.File, error) { +func NewStdioFile(stdin bool, f fs.File) (experimentalsys.File, error) { // Return constant stat, which has fake times, but keep the underlying // file mode. Fake times are needed to pass wasi-testsuite. // https://github.com/WebAssembly/wasi-testsuite/blob/af57727/tests/rust/src/bin/fd_filestat_get.rs#L1-L19 @@ -21,13 +20,13 @@ func NewStdioFile(stdin bool, f fs.File) (fsapi.File, error) { } else { mode = st.Mode() } - var flag fsapi.Oflag + var flag experimentalsys.Oflag if stdin { - flag = fsapi.O_RDONLY + flag = experimentalsys.O_RDONLY } else { - flag = fsapi.O_WRONLY + flag = experimentalsys.O_WRONLY } - var file fsapi.File + var file experimentalsys.File if of, ok := f.(*os.File); ok { // This is ok because functions that need path aren't used by stdioFile file = newOsFile("", flag, 0, of) @@ -37,14 +36,14 @@ func NewStdioFile(stdin bool, f fs.File) (fsapi.File, error) { return &stdioFile{File: file, st: sys.Stat_t{Mode: mode, Nlink: 1}}, nil } -func OpenFile(path string, flag fsapi.Oflag, perm fs.FileMode) (*os.File, experimentalsys.Errno) { - if flag&fsapi.O_DIRECTORY != 0 && flag&(fsapi.O_WRONLY|fsapi.O_RDWR) != 0 { +func OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (*os.File, experimentalsys.Errno) { + if flag&experimentalsys.O_DIRECTORY != 0 && flag&(experimentalsys.O_WRONLY|experimentalsys.O_RDWR) != 0 { return nil, experimentalsys.EISDIR // invalid to open a directory writeable } return openFile(path, flag, perm) } -func OpenOSFile(path string, flag fsapi.Oflag, perm fs.FileMode) (fsapi.File, experimentalsys.Errno) { +func OpenOSFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { f, errno := OpenFile(path, flag, perm) if errno != 0 { return nil, errno @@ -52,8 +51,8 @@ func OpenOSFile(path string, flag fsapi.Oflag, perm fs.FileMode) (fsapi.File, ex return newOsFile(path, flag, perm, f), 0 } -func OpenFSFile(fs fs.FS, path string, flag fsapi.Oflag, perm fs.FileMode) (fsapi.File, experimentalsys.Errno) { - if flag&fsapi.O_DIRECTORY != 0 && flag&(fsapi.O_WRONLY|fsapi.O_RDWR) != 0 { +func OpenFSFile(fs fs.FS, path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { + if flag&experimentalsys.O_DIRECTORY != 0 && flag&(experimentalsys.O_WRONLY|experimentalsys.O_RDWR) != 0 { return nil, experimentalsys.EISDIR // invalid to open a directory writeable } f, err := fs.Open(path) @@ -66,7 +65,7 @@ func OpenFSFile(fs fs.FS, path string, flag fsapi.Oflag, perm fs.FileMode) (fsap } type stdioFile struct { - fsapi.File + experimentalsys.File st sys.Stat_t } @@ -95,7 +94,7 @@ func (f *stdioFile) Close() experimentalsys.Errno { // implementation. Notably, this does not have access to the full file path. // so certain operations can't be supported, such as inode lookups on Windows. type fsFile struct { - fsapi.UnimplementedFile + experimentalsys.UnimplementedFile // fs is the file-system that opened the file, or nil when wrapped for // pre-opens like stdio. @@ -121,17 +120,17 @@ type fsFile struct { } type cachedStat struct { - // dev is the same as fsapi.Stat_t Dev. + // dev is the same as sys.Stat_t Dev. dev uint64 - // dev is the same as fsapi.Stat_t Ino. + // dev is the same as sys.Stat_t Ino. ino sys.Inode - // isDir is fsapi.Stat_t Mode masked with fs.ModeDir + // isDir is sys.Stat_t Mode masked with fs.ModeDir isDir bool } -// cachedStat returns the cacheable parts of fsapi.Stat_t or an error if they +// cachedStat returns the cacheable parts of sys.Stat_t or an error if they // couldn't be retrieved. func (f *fsFile) cachedStat() (dev uint64, ino sys.Inode, isDir bool, errno experimentalsys.Errno) { if f.cachedSt == nil { @@ -142,35 +141,35 @@ func (f *fsFile) cachedStat() (dev uint64, ino sys.Inode, isDir bool, errno expe return f.cachedSt.dev, f.cachedSt.ino, f.cachedSt.isDir, 0 } -// Dev implements the same method as documented on fsapi.File +// Dev implements the same method as documented on sys.File func (f *fsFile) Dev() (uint64, experimentalsys.Errno) { dev, _, _, errno := f.cachedStat() return dev, errno } -// Ino implements the same method as documented on fsapi.File +// Ino implements the same method as documented on sys.File func (f *fsFile) Ino() (sys.Inode, experimentalsys.Errno) { _, ino, _, errno := f.cachedStat() return ino, errno } -// IsDir implements the same method as documented on fsapi.File +// IsDir implements the same method as documented on sys.File func (f *fsFile) IsDir() (bool, experimentalsys.Errno) { _, _, isDir, errno := f.cachedStat() return isDir, errno } -// IsAppend implements the same method as documented on fsapi.File +// IsAppend implements the same method as documented on sys.File func (f *fsFile) IsAppend() bool { return false } -// SetAppend implements the same method as documented on fsapi.File +// SetAppend implements the same method as documented on sys.File func (f *fsFile) SetAppend(bool) (errno experimentalsys.Errno) { return fileError(f, f.closed, experimentalsys.ENOSYS) } -// Stat implements the same method as documented on fsapi.File +// Stat implements the same method as documented on sys.File func (f *fsFile) Stat() (sys.Stat_t, experimentalsys.Errno) { if f.closed { return sys.Stat_t{}, experimentalsys.EBADF @@ -186,7 +185,7 @@ func (f *fsFile) Stat() (sys.Stat_t, experimentalsys.Errno) { return st, errno } -// Read implements the same method as documented on fsapi.File +// Read implements the same method as documented on sys.File func (f *fsFile) Read(buf []byte) (n int, errno experimentalsys.Errno) { if n, errno = read(f.file, buf); errno != 0 { // Defer validation overhead until we've already had an error. @@ -195,7 +194,7 @@ func (f *fsFile) Read(buf []byte) (n int, errno experimentalsys.Errno) { return } -// Pread implements the same method as documented on fsapi.File +// Pread implements the same method as documented on sys.File func (f *fsFile) Pread(buf []byte, off int64) (n int, errno experimentalsys.Errno) { if ra, ok := f.file.(io.ReaderAt); ok { if n, errno = pread(ra, buf, off); errno != 0 { @@ -234,7 +233,7 @@ func (f *fsFile) Pread(buf []byte, off int64) (n int, errno experimentalsys.Errn return } -// Seek implements the same method as documented on fsapi.File +// Seek implements the same method as documented on sys.File func (f *fsFile) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) { // If this is a directory, and we're attempting to seek to position zero, // we have to re-open the file to ensure the directory state is reset. @@ -257,11 +256,11 @@ func (f *fsFile) Seek(offset int64, whence int) (newOffset int64, errno experime return } -// Readdir implements the same method as documented on fsapi.File +// Readdir implements the same method as documented on sys.File // // Notably, this uses readdirFile or fs.ReadDirFile if available. This does not // return inodes on windows. -func (f *fsFile) Readdir(n int) (dirents []fsapi.Dirent, errno experimentalsys.Errno) { +func (f *fsFile) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { // Windows lets you Readdir after close, fs.File also may not implement // close in a meaningful way. read our closed field to return consistent // results. @@ -278,7 +277,7 @@ func (f *fsFile) Readdir(n int) (dirents []fsapi.Dirent, errno experimentalsys.E } if of, ok := f.file.(readdirFile); ok { - // We can't use f.name here because it is the path up to the fsapi.FS, + // We can't use f.name here because it is the path up to the sys.FS, // not necessarily the real path. For this reason, Windows may not be // able to populate inodes. However, Darwin and Linux will. if dirents, errno = readdir(of, "", n); errno != 0 { @@ -294,10 +293,10 @@ func (f *fsFile) Readdir(n int) (dirents []fsapi.Dirent, errno experimentalsys.E if errno = adjustReaddirErr(f, f.closed, e); errno != 0 { return } - dirents = make([]fsapi.Dirent, 0, len(entries)) + dirents = make([]experimentalsys.Dirent, 0, len(entries)) for _, e := range entries { // By default, we don't attempt to read inode data - dirents = append(dirents, fsapi.Dirent{Name: e.Name(), Type: e.Type()}) + dirents = append(dirents, experimentalsys.Dirent{Name: e.Name(), Type: e.Type()}) } } else { errno = experimentalsys.EBADF // not a directory @@ -305,7 +304,7 @@ func (f *fsFile) Readdir(n int) (dirents []fsapi.Dirent, errno experimentalsys.E return } -// Write implements the same method as documented on fsapi.File. +// Write implements the same method as documented on sys.File. func (f *fsFile) Write(buf []byte) (n int, errno experimentalsys.Errno) { if w, ok := f.file.(io.Writer); ok { if n, errno = write(w, buf); errno != 0 { @@ -318,7 +317,7 @@ func (f *fsFile) Write(buf []byte) (n int, errno experimentalsys.Errno) { return } -// Pwrite implements the same method as documented on fsapi.File. +// Pwrite implements the same method as documented on sys.File. func (f *fsFile) Pwrite(buf []byte, off int64) (n int, errno experimentalsys.Errno) { if wa, ok := f.file.(io.WriterAt); ok { if n, errno = pwrite(wa, buf, off); errno != 0 { @@ -331,7 +330,7 @@ func (f *fsFile) Pwrite(buf []byte, off int64) (n int, errno experimentalsys.Err return } -// Close implements the same method as documented on fsapi.File. +// Close implements the same method as documented on sys.File. func (f *fsFile) Close() experimentalsys.Errno { if f.closed { return 0 @@ -345,7 +344,7 @@ func (f *fsFile) close() experimentalsys.Errno { } // dirError is used for commands that work against a directory, but not a file. -func dirError(f fsapi.File, isClosed bool, errno experimentalsys.Errno) experimentalsys.Errno { +func dirError(f experimentalsys.File, isClosed bool, errno experimentalsys.Errno) experimentalsys.Errno { if vErrno := validate(f, isClosed, false, true); vErrno != 0 { return vErrno } @@ -353,7 +352,7 @@ func dirError(f fsapi.File, isClosed bool, errno experimentalsys.Errno) experime } // fileError is used for commands that work against a file, but not a directory. -func fileError(f fsapi.File, isClosed bool, errno experimentalsys.Errno) experimentalsys.Errno { +func fileError(f experimentalsys.File, isClosed bool, errno experimentalsys.Errno) experimentalsys.Errno { if vErrno := validate(f, isClosed, true, false); vErrno != 0 { return vErrno } @@ -361,7 +360,7 @@ func fileError(f fsapi.File, isClosed bool, errno experimentalsys.Errno) experim } // validate is used to making syscalls which will fail. -func validate(f fsapi.File, isClosed, wantFile, wantDir bool) experimentalsys.Errno { +func validate(f experimentalsys.File, isClosed, wantFile, wantDir bool) experimentalsys.Errno { if isClosed { return experimentalsys.EBADF } @@ -427,13 +426,13 @@ type readdirFile interface { } // readdir uses readdirFile.Readdir, special casing windows when path !="". -func readdir(f readdirFile, path string, n int) (dirents []fsapi.Dirent, errno experimentalsys.Errno) { +func readdir(f readdirFile, path string, n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { fis, e := f.Readdir(n) if errno = experimentalsys.UnwrapOSError(e); errno != 0 { return } - dirents = make([]fsapi.Dirent, 0, len(fis)) + dirents = make([]experimentalsys.Dirent, 0, len(fis)) // linux/darwin won't have to fan out to lstat, but windows will. var ino sys.Inode @@ -444,7 +443,7 @@ func readdir(f readdirFile, path string, n int) (dirents []fsapi.Dirent, errno e if ino, errno = inoFromFileInfo(path, t); errno != 0 { return } - dirents = append(dirents, fsapi.Dirent{Name: t.Name(), Ino: ino, Type: t.Mode().Type()}) + dirents = append(dirents, experimentalsys.Dirent{Name: t.Name(), Ino: ino, Type: t.Mode().Type()}) } return } @@ -469,7 +468,7 @@ func pwrite(w io.WriterAt, buf []byte, off int64) (n int, errno experimentalsys. func chtimes(path string, atim, mtim int64) (errno experimentalsys.Errno) { //nolint:unused // When both inputs are omitted, there is nothing to change. - if atim == fsapi.UTIME_OMIT && mtim == fsapi.UTIME_OMIT { + if atim == experimentalsys.UTIME_OMIT && mtim == experimentalsys.UTIME_OMIT { return } @@ -478,17 +477,17 @@ func chtimes(path string, atim, mtim int64) (errno experimentalsys.Errno) { //no // - https://github.com/golang/go/issues/32558. // - https://go-review.googlesource.com/c/go/+/219638 (unmerged) var st sys.Stat_t - if atim == fsapi.UTIME_OMIT || mtim == fsapi.UTIME_OMIT { + if atim == experimentalsys.UTIME_OMIT || mtim == experimentalsys.UTIME_OMIT { if st, errno = stat(path); errno != 0 { return } } var atime, mtime time.Time - if atim == fsapi.UTIME_OMIT { + if atim == experimentalsys.UTIME_OMIT { atime = epochNanosToTime(st.Atim) mtime = epochNanosToTime(mtim) - } else if mtim == fsapi.UTIME_OMIT { + } else if mtim == experimentalsys.UTIME_OMIT { atime = epochNanosToTime(atim) mtime = epochNanosToTime(st.Mtim) } else { diff --git a/internal/sysfs/file_test.go b/internal/sysfs/file_test.go index c3ab23716c..d50093301a 100644 --- a/internal/sysfs/file_test.go +++ b/internal/sysfs/file_test.go @@ -11,7 +11,6 @@ import ( gofstest "testing/fstest" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/platform" "github.com/tetratelabs/wazero/internal/testing/require" "github.com/tetratelabs/wazero/sys" @@ -53,7 +52,7 @@ func TestRegularFileSetNonblock(t *testing.T) { defer r.Close() defer w.Close() - rF := newOsFile("", fsapi.O_RDONLY, 0, r) + rF := newOsFile("", experimentalsys.O_RDONLY, 0, r) errno := rF.SetNonblock(true) require.EqualErrno(t, 0, errno) @@ -124,7 +123,7 @@ func TestFileSetAppend(t *testing.T) { require.NoError(t, os.WriteFile(fPath, []byte("0123456789"), 0o600)) // Open without APPEND. - f, errno := OpenOSFile(fPath, fsapi.O_RDWR, 0o600) + f, errno := OpenOSFile(fPath, experimentalsys.O_RDWR, 0o600) require.EqualErrno(t, 0, errno) require.False(t, f.IsAppend()) @@ -185,7 +184,7 @@ func TestFileIno(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { - d, errno := OpenFSFile(tc.fs, ".", fsapi.O_RDONLY, 0) + d, errno := OpenFSFile(tc.fs, ".", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer d.Close() @@ -199,7 +198,7 @@ func TestFileIno(t *testing.T) { } t.Run("OS", func(t *testing.T) { - d, errno := OpenOSFile(tmpDir, fsapi.O_RDONLY, 0) + d, errno := OpenOSFile(tmpDir, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer d.Close() @@ -212,7 +211,7 @@ func TestFileIno(t *testing.T) { }) } -// statSetsIno returns true if this will set fsapi.Stat_t Ino on stat. The +// statSetsIno returns true if this will set sys.Stat_t Ino on stat. The // reverse doesn't mean it won't. Rather it is inconsistent. This is needed // because Windows on Go 1.18 sometimes, but not always returns non-zero inode. func statSetsIno() bool { @@ -243,7 +242,7 @@ func TestFileIsDir(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Run("file", func(t *testing.T) { - f, errno := OpenFSFile(tc.fs, wazeroFile, fsapi.O_RDONLY, 0) + f, errno := OpenFSFile(tc.fs, wazeroFile, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -253,7 +252,7 @@ func TestFileIsDir(t *testing.T) { }) t.Run("dir", func(t *testing.T) { - d, errno := OpenFSFile(tc.fs, ".", fsapi.O_RDONLY, 0) + d, errno := OpenFSFile(tc.fs, ".", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer d.Close() @@ -265,7 +264,7 @@ func TestFileIsDir(t *testing.T) { } t.Run("OS dir", func(t *testing.T) { - d, errno := OpenOSFile(t.TempDir(), fsapi.O_RDONLY, 0) + d, errno := OpenOSFile(t.TempDir(), experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer d.Close() @@ -293,7 +292,7 @@ func TestFileReadAndPread(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { - f, errno := OpenFSFile(tc.fs, wazeroFile, fsapi.O_RDONLY, 0) + f, errno := OpenFSFile(tc.fs, wazeroFile, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -320,7 +319,7 @@ func TestFileReadAndPread(t *testing.T) { } func TestFilePoll_POLLIN(t *testing.T) { - pflag := fsapi.POLLIN + pflag := experimentalsys.POLLIN // Test using os.Pipe as it is known to support poll. r, w, err := os.Pipe() @@ -356,7 +355,7 @@ func TestFilePoll_POLLIN(t *testing.T) { } func TestFilePoll_POLLOUT(t *testing.T) { - pflag := fsapi.POLLOUT + pflag := experimentalsys.POLLOUT // Test using os.Pipe as it is known to support poll. r, w, err := os.Pipe() @@ -374,13 +373,13 @@ func TestFilePoll_POLLOUT(t *testing.T) { require.False(t, ready) } -func requireRead(t *testing.T, f fsapi.File, buf []byte) { +func requireRead(t *testing.T, f experimentalsys.File, buf []byte) { n, errno := f.Read(buf) require.EqualErrno(t, 0, errno) require.Equal(t, len(buf), n) } -func requirePread(t *testing.T, f fsapi.File, buf []byte, off int64) { +func requirePread(t *testing.T, f experimentalsys.File, buf []byte, off int64) { n, errno := f.Pread(buf, off) require.EqualErrno(t, 0, errno) require.Equal(t, len(buf), n) @@ -404,7 +403,7 @@ func TestFileRead_empty(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { - f, errno := OpenFSFile(tc.fs, emptyFile, fsapi.O_RDONLY, 0) + f, errno := OpenFSFile(tc.fs, emptyFile, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -437,7 +436,7 @@ func TestFilePread_Unsupported(t *testing.T) { embedFS, err := fs.Sub(testdata, "testdata") require.NoError(t, err) - f, errno := OpenFSFile(&maskFS{embedFS}, emptyFile, fsapi.O_RDONLY, 0) + f, errno := OpenFSFile(&maskFS{embedFS}, emptyFile, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -451,20 +450,20 @@ func TestFileRead_Errors(t *testing.T) { path := path.Join(t.TempDir(), emptyFile) // Open the file write-only - flag := fsapi.O_WRONLY | fsapi.O_CREAT + flag := experimentalsys.O_WRONLY | experimentalsys.O_CREAT f := requireOpenFile(t, path, flag, 0o600) defer f.Close() buf := make([]byte, 5) tests := []struct { name string - fn func(fsapi.File) experimentalsys.Errno + fn func(experimentalsys.File) experimentalsys.Errno }{ - {name: "Read", fn: func(f fsapi.File) experimentalsys.Errno { + {name: "Read", fn: func(f experimentalsys.File) experimentalsys.Errno { _, errno := f.Read(buf) return errno }}, - {name: "Pread", fn: func(f fsapi.File) experimentalsys.Errno { + {name: "Pread", fn: func(f experimentalsys.File) experimentalsys.Errno { _, errno := f.Pread(buf, 0) return errno }}, @@ -490,19 +489,19 @@ func TestFileSeek(t *testing.T) { tests := []struct { name string - openFile func(string) (fsapi.File, experimentalsys.Errno) + openFile func(string) (experimentalsys.File, experimentalsys.Errno) }{ - {name: "fsFile os.DirFS", openFile: func(name string) (fsapi.File, experimentalsys.Errno) { - return OpenFSFile(dirFS, name, fsapi.O_RDONLY, 0) + {name: "fsFile os.DirFS", openFile: func(name string) (experimentalsys.File, experimentalsys.Errno) { + return OpenFSFile(dirFS, name, experimentalsys.O_RDONLY, 0) }}, - {name: "fsFile embed.api.FS", openFile: func(name string) (fsapi.File, experimentalsys.Errno) { - return OpenFSFile(embedFS, name, fsapi.O_RDONLY, 0) + {name: "fsFile embed.api.FS", openFile: func(name string) (experimentalsys.File, experimentalsys.Errno) { + return OpenFSFile(embedFS, name, experimentalsys.O_RDONLY, 0) }}, - {name: "fsFile fstest.MapFS", openFile: func(name string) (fsapi.File, experimentalsys.Errno) { - return OpenFSFile(mapFS, name, fsapi.O_RDONLY, 0) + {name: "fsFile fstest.MapFS", openFile: func(name string) (experimentalsys.File, experimentalsys.Errno) { + return OpenFSFile(mapFS, name, experimentalsys.O_RDONLY, 0) }}, - {name: "osFile", openFile: func(name string) (fsapi.File, experimentalsys.Errno) { - return OpenOSFile(path.Join(tmpDir, name), fsapi.O_RDONLY, 0o666) + {name: "osFile", openFile: func(name string) (experimentalsys.File, experimentalsys.Errno) { + return OpenOSFile(path.Join(tmpDir, name), experimentalsys.O_RDONLY, 0o666) }}, } @@ -580,7 +579,7 @@ func TestFileSeek(t *testing.T) { require.Equal(t, direntCount, len(dirents)) }) - seekToZero := func(f fsapi.File) experimentalsys.Errno { + seekToZero := func(f experimentalsys.File) experimentalsys.Errno { _, errno := f.Seek(0, io.SeekStart) return errno } @@ -589,7 +588,7 @@ func TestFileSeek(t *testing.T) { } } -func requireSeek(t *testing.T, f fsapi.File, off int64, whence int) int64 { +func requireSeek(t *testing.T, f experimentalsys.File, off int64, whence int) int64 { n, errno := f.Seek(off, whence) require.EqualErrno(t, 0, errno) return n @@ -611,7 +610,7 @@ func TestFileSeek_empty(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { - f, errno := OpenFSFile(tc.fs, emptyFile, fsapi.O_RDONLY, 0) + f, errno := OpenFSFile(tc.fs, emptyFile, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -634,7 +633,7 @@ func TestFileSeek_Unsupported(t *testing.T) { embedFS, err := fs.Sub(testdata, "testdata") require.NoError(t, err) - f, errno := OpenFSFile(&maskFS{embedFS}, emptyFile, fsapi.O_RDONLY, 0) + f, errno := OpenFSFile(&maskFS{embedFS}, emptyFile, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -643,10 +642,10 @@ func TestFileSeek_Unsupported(t *testing.T) { } func TestFileWriteAndPwrite(t *testing.T) { - // fsapi.FS doesn't support writes, and there is no other built-in + // sys.FS doesn't support writes, and there is no other built-in // implementation except os.File. path := path.Join(t.TempDir(), wazeroFile) - f := requireOpenFile(t, path, fsapi.O_RDWR|fsapi.O_CREAT, 0o600) + f := requireOpenFile(t, path, experimentalsys.O_RDWR|experimentalsys.O_CREAT, 0o600) defer f.Close() text := "wazero" @@ -683,36 +682,36 @@ func TestFileWriteAndPwrite(t *testing.T) { require.Equal(t, "wazerowazeroero", string(b)) } -func requireWrite(t *testing.T, f fsapi.File, buf []byte) { +func requireWrite(t *testing.T, f experimentalsys.File, buf []byte) { n, errno := f.Write(buf) require.EqualErrno(t, 0, errno) require.Equal(t, len(buf), n) } -func requirePwrite(t *testing.T, f fsapi.File, buf []byte, off int64) { +func requirePwrite(t *testing.T, f experimentalsys.File, buf []byte, off int64) { n, errno := f.Pwrite(buf, off) require.EqualErrno(t, 0, errno) require.Equal(t, len(buf), n) } func TestFileWrite_empty(t *testing.T) { - // fsapi.FS doesn't support writes, and there is no other built-in + // sys.FS doesn't support writes, and there is no other built-in // implementation except os.File. path := path.Join(t.TempDir(), emptyFile) - f := requireOpenFile(t, path, fsapi.O_RDWR|fsapi.O_CREAT, 0o600) + f := requireOpenFile(t, path, experimentalsys.O_RDWR|experimentalsys.O_CREAT, 0o600) defer f.Close() tests := []struct { name string - fn func(fsapi.File, []byte) (int, experimentalsys.Errno) + fn func(experimentalsys.File, []byte) (int, experimentalsys.Errno) }{ - {name: "Write", fn: func(f fsapi.File, buf []byte) (int, experimentalsys.Errno) { + {name: "Write", fn: func(f experimentalsys.File, buf []byte) (int, experimentalsys.Errno) { return f.Write(buf) }}, - {name: "Pwrite from zero", fn: func(f fsapi.File, buf []byte) (int, experimentalsys.Errno) { + {name: "Pwrite from zero", fn: func(f experimentalsys.File, buf []byte) (int, experimentalsys.Errno) { return f.Pwrite(buf, 0) }}, - {name: "Pwrite from 3", fn: func(f fsapi.File, buf []byte) (int, experimentalsys.Errno) { + {name: "Pwrite from 3", fn: func(f experimentalsys.File, buf []byte) (int, experimentalsys.Errno) { return f.Pwrite(buf, 3) }}, } @@ -739,19 +738,19 @@ func TestFileWrite_Unsupported(t *testing.T) { embedFS, err := fs.Sub(testdata, "testdata") require.NoError(t, err) - // Use fsapi.O_RDWR so that it fails due to type not flags - f, errno := OpenFSFile(&maskFS{embedFS}, wazeroFile, fsapi.O_RDWR, 0) + // Use sys.O_RDWR so that it fails due to type not flags + f, errno := OpenFSFile(&maskFS{embedFS}, wazeroFile, experimentalsys.O_RDWR, 0) require.EqualErrno(t, 0, errno) defer f.Close() tests := []struct { name string - fn func(fsapi.File, []byte) (int, experimentalsys.Errno) + fn func(experimentalsys.File, []byte) (int, experimentalsys.Errno) }{ - {name: "Write", fn: func(f fsapi.File, buf []byte) (int, experimentalsys.Errno) { + {name: "Write", fn: func(f experimentalsys.File, buf []byte) (int, experimentalsys.Errno) { return f.Write(buf) }}, - {name: "Pwrite", fn: func(f fsapi.File, buf []byte) (int, experimentalsys.Errno) { + {name: "Pwrite", fn: func(f experimentalsys.File, buf []byte) (int, experimentalsys.Errno) { return f.Pwrite(buf, 0) }}, } @@ -776,20 +775,20 @@ func TestFileWrite_Errors(t *testing.T) { require.NoError(t, of.Close()) // Open the file read-only - flag := fsapi.O_RDONLY + flag := experimentalsys.O_RDONLY f := requireOpenFile(t, path, flag, 0o600) defer f.Close() buf := []byte("wazero") tests := []struct { name string - fn func(fsapi.File) experimentalsys.Errno + fn func(experimentalsys.File) experimentalsys.Errno }{ - {name: "Write", fn: func(f fsapi.File) experimentalsys.Errno { + {name: "Write", fn: func(f experimentalsys.File) experimentalsys.Errno { _, errno := f.Write(buf) return errno }}, - {name: "Pwrite", fn: func(f fsapi.File) experimentalsys.Errno { + {name: "Pwrite", fn: func(f experimentalsys.File) experimentalsys.Errno { _, errno := f.Pwrite(buf, 0) return errno }}, @@ -810,29 +809,29 @@ func TestFileWrite_Errors(t *testing.T) { } func TestFileSync_NoError(t *testing.T) { - testSync_NoError(t, fsapi.File.Sync) + testSync_NoError(t, experimentalsys.File.Sync) } func TestFileDatasync_NoError(t *testing.T) { - testSync_NoError(t, fsapi.File.Datasync) + testSync_NoError(t, experimentalsys.File.Datasync) } -func testSync_NoError(t *testing.T, sync func(fsapi.File) experimentalsys.Errno) { +func testSync_NoError(t *testing.T, sync func(experimentalsys.File) experimentalsys.Errno) { roPath := "file_test.go" - ro, errno := OpenFSFile(embedFS, roPath, fsapi.O_RDONLY, 0) + ro, errno := OpenFSFile(embedFS, roPath, experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer ro.Close() rwPath := path.Join(t.TempDir(), "datasync") - rw, errno := OpenOSFile(rwPath, fsapi.O_CREAT|fsapi.O_RDWR, 0o600) + rw, errno := OpenOSFile(rwPath, experimentalsys.O_CREAT|experimentalsys.O_RDWR, 0o600) require.EqualErrno(t, 0, errno) defer rw.Close() tests := []struct { name string - f fsapi.File + f experimentalsys.File }{ - {name: "UnimplementedFile", f: fsapi.UnimplementedFile{}}, + {name: "UnimplementedFile", f: experimentalsys.UnimplementedFile{}}, {name: "File of read-only fs.File", f: ro}, {name: "File of os.File", f: rw}, } @@ -847,20 +846,20 @@ func testSync_NoError(t *testing.T, sync func(fsapi.File) experimentalsys.Errno) } func TestFileSync(t *testing.T) { - testSync(t, fsapi.File.Sync) + testSync(t, experimentalsys.File.Sync) } func TestFileDatasync(t *testing.T) { - testSync(t, fsapi.File.Datasync) + testSync(t, experimentalsys.File.Datasync) } // testSync doesn't guarantee sync works because the operating system may // sync anyway. There is no test in Go for syscall.Fdatasync, but closest is // similar to below. Effectively, this only tests that things don't error. -func testSync(t *testing.T, sync func(fsapi.File) experimentalsys.Errno) { +func testSync(t *testing.T, sync func(experimentalsys.File) experimentalsys.Errno) { // Even though it is invalid, try to sync a directory dPath := t.TempDir() - d := requireOpenFile(t, dPath, fsapi.O_RDONLY, 0) + d := requireOpenFile(t, dPath, experimentalsys.O_RDONLY, 0) defer d.Close() errno := sync(d) @@ -868,7 +867,7 @@ func testSync(t *testing.T, sync func(fsapi.File) experimentalsys.Errno) { fPath := path.Join(dPath, t.Name()) - f := requireOpenFile(t, fPath, fsapi.O_RDWR|fsapi.O_CREAT, 0o600) + f := requireOpenFile(t, fPath, experimentalsys.O_RDWR|experimentalsys.O_CREAT, 0o600) defer f.Close() expected := "hello world!" @@ -949,7 +948,7 @@ func TestFileTruncate(t *testing.T) { }) } - truncateToZero := func(f fsapi.File) experimentalsys.Errno { + truncateToZero := func(f experimentalsys.File) experimentalsys.Errno { return f.Truncate(0) } @@ -985,11 +984,11 @@ func TestFileUtimens(t *testing.T) { testUtimens(t, true) - testEBADFIfFileClosed(t, func(f fsapi.File) experimentalsys.Errno { - return f.Utimens(fsapi.UTIME_OMIT, fsapi.UTIME_OMIT) + testEBADFIfFileClosed(t, func(f experimentalsys.File) experimentalsys.Errno { + return f.Utimens(experimentalsys.UTIME_OMIT, experimentalsys.UTIME_OMIT) }) - testEBADFIfDirClosed(t, func(d fsapi.File) experimentalsys.Errno { - return d.Utimens(fsapi.UTIME_OMIT, fsapi.UTIME_OMIT) + testEBADFIfDirClosed(t, func(d experimentalsys.File) experimentalsys.Errno { + return d.Utimens(experimentalsys.UTIME_OMIT, experimentalsys.UTIME_OMIT) }) } @@ -1017,7 +1016,7 @@ func TestNewStdioFile(t *testing.T) { tests := []struct { name string - f fsapi.File + f experimentalsys.File // Depending on how the tests run, os.Stdin won't necessarily be a char // device. We compare against an os.File, to account for this. expectedType fs.FileMode @@ -1062,9 +1061,9 @@ func TestNewStdioFile(t *testing.T) { } } -func testEBADFIfDirClosed(t *testing.T, fn func(fsapi.File) experimentalsys.Errno) bool { +func testEBADFIfDirClosed(t *testing.T, fn func(experimentalsys.File) experimentalsys.Errno) bool { return t.Run("EBADF if dir closed", func(t *testing.T) { - d := requireOpenFile(t, t.TempDir(), fsapi.O_RDONLY, 0o755) + d := requireOpenFile(t, t.TempDir(), experimentalsys.O_RDONLY, 0o755) // close the directory underneath require.EqualErrno(t, 0, d.Close()) @@ -1073,7 +1072,7 @@ func testEBADFIfDirClosed(t *testing.T, fn func(fsapi.File) experimentalsys.Errn }) } -func testEBADFIfFileClosed(t *testing.T, fn func(fsapi.File) experimentalsys.Errno) bool { +func testEBADFIfFileClosed(t *testing.T, fn func(experimentalsys.File) experimentalsys.Errno) bool { return t.Run("EBADF if file closed", func(t *testing.T) { tmpDir := t.TempDir() @@ -1086,24 +1085,24 @@ func testEBADFIfFileClosed(t *testing.T, fn func(fsapi.File) experimentalsys.Err }) } -func testEISDIR(t *testing.T, fn func(fsapi.File) experimentalsys.Errno) bool { +func testEISDIR(t *testing.T, fn func(experimentalsys.File) experimentalsys.Errno) bool { return t.Run("EISDIR if directory", func(t *testing.T) { - f := requireOpenFile(t, os.TempDir(), fsapi.O_RDONLY|fsapi.O_DIRECTORY, 0o666) + f := requireOpenFile(t, os.TempDir(), experimentalsys.O_RDONLY|experimentalsys.O_DIRECTORY, 0o666) defer f.Close() require.EqualErrno(t, experimentalsys.EISDIR, fn(f)) }) } -func openForWrite(t *testing.T, path string, content []byte) fsapi.File { +func openForWrite(t *testing.T, path string, content []byte) experimentalsys.File { require.NoError(t, os.WriteFile(path, content, 0o0666)) - f := requireOpenFile(t, path, fsapi.O_RDWR, 0o666) + f := requireOpenFile(t, path, experimentalsys.O_RDWR, 0o666) _, errno := f.Write(content) require.EqualErrno(t, 0, errno) return f } -func requireOpenFile(t *testing.T, path string, flag fsapi.Oflag, perm fs.FileMode) fsapi.File { +func requireOpenFile(t *testing.T, path string, flag experimentalsys.Oflag, perm fs.FileMode) experimentalsys.File { f, errno := OpenOSFile(path, flag, perm) require.EqualErrno(t, 0, errno) return f diff --git a/internal/sysfs/futimens.go b/internal/sysfs/futimens.go index c122da7946..1f670ca116 100644 --- a/internal/sysfs/futimens.go +++ b/internal/sysfs/futimens.go @@ -6,7 +6,7 @@ import ( "syscall" "unsafe" - "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/experimental/sys" ) func timesToPtr(times *[2]syscall.Timespec) unsafe.Pointer { //nolint:unused @@ -18,15 +18,15 @@ func timesToPtr(times *[2]syscall.Timespec) unsafe.Pointer { //nolint:unused func timesToTimespecs(atim int64, mtim int64) (times *[2]syscall.Timespec) { // When both inputs are omitted, there is nothing to change. - if atim == fsapi.UTIME_OMIT && mtim == fsapi.UTIME_OMIT { + if atim == sys.UTIME_OMIT && mtim == sys.UTIME_OMIT { return } times = &[2]syscall.Timespec{} - if atim == fsapi.UTIME_OMIT { + if atim == sys.UTIME_OMIT { times[0] = syscall.Timespec{Nsec: _UTIME_OMIT} times[1] = syscall.NsecToTimespec(mtim) - } else if mtim == fsapi.UTIME_OMIT { + } else if mtim == sys.UTIME_OMIT { times[0] = syscall.NsecToTimespec(atim) times[1] = syscall.Timespec{Nsec: _UTIME_OMIT} } else { diff --git a/internal/sysfs/futimens_test.go b/internal/sysfs/futimens_test.go index ba6a3f3b27..5e690b0dfc 100644 --- a/internal/sysfs/futimens_test.go +++ b/internal/sysfs/futimens_test.go @@ -10,7 +10,6 @@ import ( "time" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/platform" "github.com/tetratelabs/wazero/internal/testing/require" ) @@ -37,17 +36,17 @@ func testUtimens(t *testing.T, futimes bool) { }, { name: "a=omit,m=omit", - atim: fsapi.UTIME_OMIT, - mtim: fsapi.UTIME_OMIT, + atim: sys.UTIME_OMIT, + mtim: sys.UTIME_OMIT, }, { name: "a=set,m=omit", atim: int64(123*time.Second + 4*time.Microsecond), - mtim: fsapi.UTIME_OMIT, + mtim: sys.UTIME_OMIT, }, { name: "a=omit,m=set", - atim: fsapi.UTIME_OMIT, + atim: sys.UTIME_OMIT, mtim: int64(123*time.Second + 4*time.Microsecond), }, { @@ -97,9 +96,9 @@ func testUtimens(t *testing.T, futimes bool) { errno = utimens(path, tc.atim, tc.mtim) require.EqualErrno(t, 0, errno) } else { - flag := fsapi.O_RDWR + flag := sys.O_RDWR if path == dir { - flag = fsapi.O_RDONLY + flag = sys.O_RDONLY if runtime.GOOS == "windows" { // windows requires O_RDWR, which is invalid for directories t.Skip("windows cannot update timestamps on a dir") @@ -117,7 +116,7 @@ func testUtimens(t *testing.T, futimes bool) { require.EqualErrno(t, 0, errno) if platform.CompilerSupported() { - if tc.atim == fsapi.UTIME_OMIT { + if tc.atim == sys.UTIME_OMIT { require.Equal(t, oldSt.Atim, newSt.Atim) } else { require.Equal(t, tc.atim, newSt.Atim) @@ -125,7 +124,7 @@ func testUtimens(t *testing.T, futimes bool) { } // When compiler isn't supported, we can still check mtim. - if tc.mtim == fsapi.UTIME_OMIT { + if tc.mtim == sys.UTIME_OMIT { require.Equal(t, oldSt.Mtim, newSt.Mtim) } else { require.Equal(t, tc.mtim, newSt.Mtim) diff --git a/internal/sysfs/futimens_windows.go b/internal/sysfs/futimens_windows.go index 68223f5e0f..3a5289b70b 100644 --- a/internal/sysfs/futimens_windows.go +++ b/internal/sysfs/futimens_windows.go @@ -4,7 +4,6 @@ import ( "syscall" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/platform" ) @@ -20,7 +19,7 @@ func futimens(fd uintptr, atim, mtim int64) error { } // Per docs, zero isn't a valid timestamp as it cannot be differentiated - // from nil. In both cases, it is a marker like fsapi.UTIME_OMIT. + // from nil. In both cases, it is a marker like sys.UTIME_OMIT. // See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfiletime a, w := timespecToFiletime(atim, mtim) @@ -42,7 +41,7 @@ func timespecToFiletime(atim, mtim int64) (a, w *syscall.Filetime) { } func timespecToFileTime(tim int64) *syscall.Filetime { - if tim == fsapi.UTIME_OMIT { + if tim == sys.UTIME_OMIT { return nil } ft := syscall.NsecToFiletime(tim) diff --git a/internal/sysfs/nonblock_unix.go b/internal/sysfs/nonblock_unix.go index c7ac1859af..07fb15cf12 100644 --- a/internal/sysfs/nonblock_unix.go +++ b/internal/sysfs/nonblock_unix.go @@ -6,7 +6,6 @@ import ( "syscall" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) func setNonblock(fd uintptr, enable bool) sys.Errno { @@ -14,5 +13,5 @@ func setNonblock(fd uintptr, enable bool) sys.Errno { } func isNonblock(f *osFile) bool { - return f.flag&fsapi.O_NONBLOCK == fsapi.O_NONBLOCK + return f.flag&sys.O_NONBLOCK == sys.O_NONBLOCK } diff --git a/internal/sysfs/nonblock_windows.go b/internal/sysfs/nonblock_windows.go index 8c6d952b29..eb38ea5afa 100644 --- a/internal/sysfs/nonblock_windows.go +++ b/internal/sysfs/nonblock_windows.go @@ -5,7 +5,6 @@ import ( "syscall" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) func setNonblock(fd uintptr, enable bool) sys.Errno { @@ -20,5 +19,5 @@ func isNonblock(f *osFile) bool { if errno == 0 { isValid = st.Mode&fs.ModeNamedPipe != 0 } - return isValid && f.flag&fsapi.O_NONBLOCK == fsapi.O_NONBLOCK + return isValid && f.flag&sys.O_NONBLOCK == sys.O_NONBLOCK } diff --git a/internal/sysfs/oflag.go b/internal/sysfs/oflag.go index e6c3b06c28..be6d2c35f6 100644 --- a/internal/sysfs/oflag.go +++ b/internal/sysfs/oflag.go @@ -3,35 +3,35 @@ package sysfs import ( "os" - "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/experimental/sys" ) // toOsOpenFlag converts the input to the flag parameter of os.OpenFile -func toOsOpenFlag(oflag fsapi.Oflag) (flag int) { +func toOsOpenFlag(oflag sys.Oflag) (flag int) { // First flags are exclusive - switch oflag & (fsapi.O_RDONLY | fsapi.O_RDWR | fsapi.O_WRONLY) { - case fsapi.O_RDONLY: + switch oflag & (sys.O_RDONLY | sys.O_RDWR | sys.O_WRONLY) { + case sys.O_RDONLY: flag |= os.O_RDONLY - case fsapi.O_RDWR: + case sys.O_RDWR: flag |= os.O_RDWR - case fsapi.O_WRONLY: + case sys.O_WRONLY: flag |= os.O_WRONLY } // Run down the flags defined in the os package - if oflag&fsapi.O_APPEND != 0 { + if oflag&sys.O_APPEND != 0 { flag |= os.O_APPEND } - if oflag&fsapi.O_CREAT != 0 { + if oflag&sys.O_CREAT != 0 { flag |= os.O_CREATE } - if oflag&fsapi.O_EXCL != 0 { + if oflag&sys.O_EXCL != 0 { flag |= os.O_EXCL } - if oflag&fsapi.O_SYNC != 0 { + if oflag&sys.O_SYNC != 0 { flag |= os.O_SYNC } - if oflag&fsapi.O_TRUNC != 0 { + if oflag&sys.O_TRUNC != 0 { flag |= os.O_TRUNC } return withSyscallOflag(oflag, flag) diff --git a/internal/sysfs/oflag_test.go b/internal/sysfs/oflag_test.go index e1c9beb364..575a0373c3 100644 --- a/internal/sysfs/oflag_test.go +++ b/internal/sysfs/oflag_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/experimental/sys" "github.com/tetratelabs/wazero/internal/testing/require" ) @@ -14,17 +14,17 @@ import ( func Test_toOsOpenFlag(t *testing.T) { tests := []struct { name string - flag fsapi.Oflag + flag sys.Oflag expected int }{ - {name: "O_RDONLY", flag: fsapi.O_RDONLY, expected: os.O_RDONLY}, - {name: "O_RDWR", flag: fsapi.O_RDWR, expected: os.O_RDWR}, - {name: "O_WRONLY", flag: fsapi.O_WRONLY, expected: os.O_WRONLY}, - {name: "O_CREAT", flag: fsapi.O_CREAT, expected: os.O_RDONLY | os.O_CREATE}, - {name: "O_APPEND", flag: fsapi.O_APPEND, expected: os.O_RDONLY | os.O_APPEND}, + {name: "O_RDONLY", flag: sys.O_RDONLY, expected: os.O_RDONLY}, + {name: "O_RDWR", flag: sys.O_RDWR, expected: os.O_RDWR}, + {name: "O_WRONLY", flag: sys.O_WRONLY, expected: os.O_WRONLY}, + {name: "O_CREAT", flag: sys.O_CREAT, expected: os.O_RDONLY | os.O_CREATE}, + {name: "O_APPEND", flag: sys.O_APPEND, expected: os.O_RDONLY | os.O_APPEND}, { name: "all portable", - flag: fsapi.O_RDWR | fsapi.O_APPEND | fsapi.O_CREAT | fsapi.O_EXCL | fsapi.O_SYNC | fsapi.O_TRUNC, + flag: sys.O_RDWR | sys.O_APPEND | sys.O_CREAT | sys.O_EXCL | sys.O_SYNC | sys.O_TRUNC, expected: os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC, }, {name: "undefined", flag: 1 << 15, expected: os.O_RDONLY}, @@ -35,12 +35,12 @@ func Test_toOsOpenFlag(t *testing.T) { } // Tests any supported syscall flags - for n, f := range map[string]fsapi.Oflag{ - "O_DIRECTORY": fsapi.O_DIRECTORY, - "O_DSYNC": fsapi.O_DSYNC, - "O_NOFOLLOW": fsapi.O_NOFOLLOW, - "O_NONBLOCK": fsapi.O_NONBLOCK, - "O_RSYNC": fsapi.O_RSYNC, + for n, f := range map[string]sys.Oflag{ + "O_DIRECTORY": sys.O_DIRECTORY, + "O_DSYNC": sys.O_DSYNC, + "O_NOFOLLOW": sys.O_NOFOLLOW, + "O_NONBLOCK": sys.O_NONBLOCK, + "O_RSYNC": sys.O_RSYNC, } { if supportedSyscallOflag&f == 0 { continue @@ -50,6 +50,6 @@ func Test_toOsOpenFlag(t *testing.T) { // Example of a flag that can be or'd into O_RDONLY even if not // currently supported in WASI or GOOS=js - const O_NOATIME = fsapi.Oflag(0x40000) + const O_NOATIME = sys.Oflag(0x40000) require.Zero(t, 0, toOsOpenFlag(O_NOATIME)) } diff --git a/internal/sysfs/open_file_darwin.go b/internal/sysfs/open_file_darwin.go index 82275393b5..a4f54ca2cc 100644 --- a/internal/sysfs/open_file_darwin.go +++ b/internal/sysfs/open_file_darwin.go @@ -3,22 +3,22 @@ package sysfs import ( "syscall" - "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/experimental/sys" ) -const supportedSyscallOflag = fsapi.O_DIRECTORY | fsapi.O_DSYNC | fsapi.O_NOFOLLOW | fsapi.O_NONBLOCK +const supportedSyscallOflag = sys.O_DIRECTORY | sys.O_DSYNC | sys.O_NOFOLLOW | sys.O_NONBLOCK -func withSyscallOflag(oflag fsapi.Oflag, flag int) int { - if oflag&fsapi.O_DIRECTORY != 0 { +func withSyscallOflag(oflag sys.Oflag, flag int) int { + if oflag&sys.O_DIRECTORY != 0 { flag |= syscall.O_DIRECTORY } - if oflag&fsapi.O_DSYNC != 0 { + if oflag&sys.O_DSYNC != 0 { flag |= syscall.O_DSYNC } - if oflag&fsapi.O_NOFOLLOW != 0 { + if oflag&sys.O_NOFOLLOW != 0 { flag |= syscall.O_NOFOLLOW } - if oflag&fsapi.O_NONBLOCK != 0 { + if oflag&sys.O_NONBLOCK != 0 { flag |= syscall.O_NONBLOCK } // syscall.O_RSYNC not defined on darwin diff --git a/internal/sysfs/open_file_freebsd.go b/internal/sysfs/open_file_freebsd.go index e91da95dfa..42adaa2140 100644 --- a/internal/sysfs/open_file_freebsd.go +++ b/internal/sysfs/open_file_freebsd.go @@ -3,20 +3,20 @@ package sysfs import ( "syscall" - "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/experimental/sys" ) -const supportedSyscallOflag = fsapi.O_DIRECTORY | fsapi.O_NOFOLLOW | fsapi.O_NONBLOCK +const supportedSyscallOflag = sys.O_DIRECTORY | sys.O_NOFOLLOW | sys.O_NONBLOCK -func withSyscallOflag(oflag fsapi.Oflag, flag int) int { - if oflag&fsapi.O_DIRECTORY != 0 { +func withSyscallOflag(oflag sys.Oflag, flag int) int { + if oflag&sys.O_DIRECTORY != 0 { flag |= syscall.O_DIRECTORY } // syscall.O_DSYNC not defined on darwin - if oflag&fsapi.O_NOFOLLOW != 0 { + if oflag&sys.O_NOFOLLOW != 0 { flag |= syscall.O_NOFOLLOW } - if oflag&fsapi.O_NONBLOCK != 0 { + if oflag&sys.O_NONBLOCK != 0 { flag |= syscall.O_NONBLOCK } // syscall.O_RSYNC not defined on darwin diff --git a/internal/sysfs/open_file_linux.go b/internal/sysfs/open_file_linux.go index bfa9a23e19..7f4915480c 100644 --- a/internal/sysfs/open_file_linux.go +++ b/internal/sysfs/open_file_linux.go @@ -3,25 +3,25 @@ package sysfs import ( "syscall" - "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/experimental/sys" ) -const supportedSyscallOflag = fsapi.O_DIRECTORY | fsapi.O_DSYNC | fsapi.O_NOFOLLOW | fsapi.O_NONBLOCK | fsapi.O_RSYNC +const supportedSyscallOflag = sys.O_DIRECTORY | sys.O_DSYNC | sys.O_NOFOLLOW | sys.O_NONBLOCK | sys.O_RSYNC -func withSyscallOflag(oflag fsapi.Oflag, flag int) int { - if oflag&fsapi.O_DIRECTORY != 0 { +func withSyscallOflag(oflag sys.Oflag, flag int) int { + if oflag&sys.O_DIRECTORY != 0 { flag |= syscall.O_DIRECTORY } - if oflag&fsapi.O_DSYNC != 0 { + if oflag&sys.O_DSYNC != 0 { flag |= syscall.O_DSYNC } - if oflag&fsapi.O_NOFOLLOW != 0 { + if oflag&sys.O_NOFOLLOW != 0 { flag |= syscall.O_NOFOLLOW } - if oflag&fsapi.O_NONBLOCK != 0 { + if oflag&sys.O_NONBLOCK != 0 { flag |= syscall.O_NONBLOCK } - if oflag&fsapi.O_RSYNC != 0 { + if oflag&sys.O_RSYNC != 0 { flag |= syscall.O_RSYNC } return flag diff --git a/internal/sysfs/open_file_notwindows.go b/internal/sysfs/open_file_notwindows.go index 4e886fb550..9ae1e2bcdb 100644 --- a/internal/sysfs/open_file_notwindows.go +++ b/internal/sysfs/open_file_notwindows.go @@ -7,14 +7,13 @@ import ( "os" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) -// openFile is like os.OpenFile except it accepts a fsapi.Oflag and returns +// openFile is like os.OpenFile except it accepts a sys.Oflag and returns // sys.Errno. A zero sys.Errno is success. -func openFile(path string, oflag fsapi.Oflag, perm fs.FileMode) (*os.File, sys.Errno) { +func openFile(path string, oflag sys.Oflag, perm fs.FileMode) (*os.File, sys.Errno) { f, err := os.OpenFile(path, toOsOpenFlag(oflag), perm) - // Note: This does not return a fsapi.File because fsapi.FS that returns + // Note: This does not return a sys.File because sys.FS that returns // one may want to hide the real OS path. For example, this is needed for // pre-opens. return f, sys.UnwrapOSError(err) diff --git a/internal/sysfs/open_file_sun.go b/internal/sysfs/open_file_sun.go index 6589ddac3f..bdf7dd84d2 100644 --- a/internal/sysfs/open_file_sun.go +++ b/internal/sysfs/open_file_sun.go @@ -5,26 +5,26 @@ package sysfs import ( "syscall" - "github.com/tetratelabs/wazero/internal/fsapi" + "github.com/tetratelabs/wazero/experimental/sys" ) -const supportedSyscallOflag = fsapi.O_DIRECTORY | fsapi.O_DSYNC | fsapi.O_NOFOLLOW | fsapi.O_NONBLOCK | fsapi.O_RSYNC +const supportedSyscallOflag = sys.O_DIRECTORY | sys.O_DSYNC | sys.O_NOFOLLOW | sys.O_NONBLOCK | sys.O_RSYNC -func withSyscallOflag(oflag fsapi.Oflag, flag int) int { - if oflag&fsapi.O_DIRECTORY != 0 { +func withSyscallOflag(oflag sys.Oflag, flag int) int { + if oflag&sys.O_DIRECTORY != 0 { // See https://github.com/illumos/illumos-gate/blob/edd580643f2cf1434e252cd7779e83182ea84945/usr/src/uts/common/sys/fcntl.h#L90 flag |= 0x1000000 } - if oflag&fsapi.O_DSYNC != 0 { + if oflag&sys.O_DSYNC != 0 { flag |= syscall.O_DSYNC } - if oflag&fsapi.O_NOFOLLOW != 0 { + if oflag&sys.O_NOFOLLOW != 0 { flag |= syscall.O_NOFOLLOW } - if oflag&fsapi.O_NONBLOCK != 0 { + if oflag&sys.O_NONBLOCK != 0 { flag |= syscall.O_NONBLOCK } - if oflag&fsapi.O_RSYNC != 0 { + if oflag&sys.O_RSYNC != 0 { flag |= syscall.O_RSYNC } return flag diff --git a/internal/sysfs/open_file_test.go b/internal/sysfs/open_file_test.go index 3381e6ba9e..1b4ea29266 100644 --- a/internal/sysfs/open_file_test.go +++ b/internal/sysfs/open_file_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/testing/require" ) @@ -19,7 +18,7 @@ func TestOpenFile(t *testing.T) { err := os.MkdirAll(path, 0o700) require.NoError(t, err) - f, errno := OpenFile(path+"/", fsapi.O_RDONLY, 0) + f, errno := OpenFile(path+"/", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) require.NoError(t, f.Close()) }) @@ -27,7 +26,7 @@ func TestOpenFile(t *testing.T) { // from os.TestDirFSPathsValid if runtime.GOOS != "windows" { t.Run("strange name", func(t *testing.T) { - f, errno := OpenFile(path.Join(tmpDir, `e:xperi\ment.txt`), fsapi.O_WRONLY|fsapi.O_CREAT|fsapi.O_TRUNC, 0o600) + f, errno := OpenFile(path.Join(tmpDir, `e:xperi\ment.txt`), sys.O_WRONLY|sys.O_CREAT|sys.O_TRUNC, 0o600) require.EqualErrno(t, 0, errno) require.NoError(t, f.Close()) }) @@ -46,23 +45,23 @@ func TestOpenFile_Errors(t *testing.T) { err = os.WriteFile(nestedFile, nil, 0o700) require.NoError(t, err) - _, errno := OpenFile(nestedFile+"/", fsapi.O_RDONLY, 0) + _, errno := OpenFile(nestedFile+"/", sys.O_RDONLY, 0) require.EqualErrno(t, sys.ENOTDIR, errno) }) t.Run("not found must be ENOENT", func(t *testing.T) { - _, errno := OpenFile(path.Join(tmpDir, "not-really-exist.txt"), fsapi.O_RDONLY, 0o600) + _, errno := OpenFile(path.Join(tmpDir, "not-really-exist.txt"), sys.O_RDONLY, 0o600) require.EqualErrno(t, sys.ENOENT, errno) }) // 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 := path.Join(tmpDir, "file.txt") - f, errno := OpenFile(filepath, fsapi.O_RDWR|fsapi.O_CREAT|fsapi.O_EXCL, 0o666) + f, errno := OpenFile(filepath, sys.O_RDWR|sys.O_CREAT|sys.O_EXCL, 0o666) require.EqualErrno(t, 0, errno) defer f.Close() - _, err := OpenFile(filepath, fsapi.O_RDWR|fsapi.O_CREAT|fsapi.O_EXCL, 0o666) + _, err := OpenFile(filepath, sys.O_RDWR|sys.O_CREAT|sys.O_EXCL, 0o666) require.EqualErrno(t, sys.EEXIST, err) }) @@ -70,7 +69,7 @@ func TestOpenFile_Errors(t *testing.T) { path := path.Join(tmpDir, "file") require.NoError(t, os.WriteFile(path, nil, 0o600)) - f := requireOpenFile(t, path, fsapi.O_RDONLY, 0) + f := requireOpenFile(t, path, sys.O_RDONLY, 0) defer f.Close() _, errno := f.Write([]byte{1, 2, 3, 4}) @@ -81,7 +80,7 @@ func TestOpenFile_Errors(t *testing.T) { path := path.Join(tmpDir, "diragain") require.NoError(t, os.Mkdir(path, 0o755)) - f := requireOpenFile(t, path, fsapi.O_RDONLY, 0) + f := requireOpenFile(t, path, sys.O_RDONLY, 0) defer f.Close() _, errno := f.Write([]byte{1, 2, 3, 4}) @@ -96,18 +95,18 @@ func TestOpenFile_Errors(t *testing.T) { err := os.Symlink(target, symlink) require.NoError(t, err) - _, errno := OpenFile(symlink, fsapi.O_DIRECTORY|fsapi.O_NOFOLLOW, 0o0666) + _, errno := OpenFile(symlink, sys.O_DIRECTORY|sys.O_NOFOLLOW, 0o0666) require.EqualErrno(t, sys.ENOTDIR, errno) - _, errno = OpenFile(symlink, fsapi.O_NOFOLLOW, 0o0666) + _, errno = OpenFile(symlink, sys.O_NOFOLLOW, 0o0666) require.EqualErrno(t, sys.ELOOP, errno) }) t.Run("opening a directory writeable is EISDIR", func(t *testing.T) { - _, errno := OpenFile(tmpDir, fsapi.O_DIRECTORY|fsapi.O_WRONLY, 0o0666) + _, errno := OpenFile(tmpDir, sys.O_DIRECTORY|sys.O_WRONLY, 0o0666) require.EqualErrno(t, sys.EISDIR, errno) - _, errno = OpenFile(tmpDir, fsapi.O_DIRECTORY|fsapi.O_WRONLY, 0o0666) + _, errno = OpenFile(tmpDir, sys.O_DIRECTORY|sys.O_WRONLY, 0o0666) require.EqualErrno(t, sys.EISDIR, errno) }) } diff --git a/internal/sysfs/open_file_unsupported.go b/internal/sysfs/open_file_unsupported.go index 9b925949aa..9f7a6d0885 100644 --- a/internal/sysfs/open_file_unsupported.go +++ b/internal/sysfs/open_file_unsupported.go @@ -2,11 +2,13 @@ package sysfs -import "github.com/tetratelabs/wazero/internal/fsapi" +import ( + "github.com/tetratelabs/wazero/experimental/sys" +) -const supportedSyscallOflag = fsapi.Oflag(0) +const supportedSyscallOflag = sys.Oflag(0) -func withSyscallOflag(oflag fsapi.Oflag, flag int) int { +func withSyscallOflag(oflag sys.Oflag, flag int) int { // O_DIRECTORY not defined // O_DSYNC not defined // O_NOFOLLOW not defined diff --git a/internal/sysfs/open_file_windows.go b/internal/sysfs/open_file_windows.go index bc7a7f7d0c..bcfbfbcd6b 100644 --- a/internal/sysfs/open_file_windows.go +++ b/internal/sysfs/open_file_windows.go @@ -8,12 +8,11 @@ import ( "unsafe" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/platform" ) -func openFile(path string, oflag fsapi.Oflag, perm fs.FileMode) (*os.File, sys.Errno) { - isDir := oflag&fsapi.O_DIRECTORY > 0 +func openFile(path string, oflag sys.Oflag, perm fs.FileMode) (*os.File, sys.Errno) { + isDir := oflag&sys.O_DIRECTORY > 0 flag := toOsOpenFlag(oflag) // TODO: document why we are opening twice @@ -55,14 +54,14 @@ func openFile(path string, oflag fsapi.Oflag, perm fs.FileMode) (*os.File, sys.E return f, errno } -const supportedSyscallOflag = fsapi.O_NONBLOCK +const supportedSyscallOflag = sys.O_NONBLOCK // Map to synthetic values here https://github.com/golang/go/blob/go1.20/src/syscall/types_windows.go#L34-L48 -func withSyscallOflag(oflag fsapi.Oflag, flag int) int { +func withSyscallOflag(oflag sys.Oflag, flag int) int { // O_DIRECTORY not defined in windows // O_DSYNC not defined in windows // O_NOFOLLOW not defined in windows - if oflag&fsapi.O_NONBLOCK != 0 { + if oflag&sys.O_NONBLOCK != 0 { flag |= syscall.O_NONBLOCK } // O_RSYNC not defined in windows diff --git a/internal/sysfs/osfile.go b/internal/sysfs/osfile.go index 36d6ecc489..adb664fc81 100644 --- a/internal/sysfs/osfile.go +++ b/internal/sysfs/osfile.go @@ -7,11 +7,10 @@ import ( "runtime" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/sys" ) -func newOsFile(path string, flag fsapi.Oflag, perm fs.FileMode, f *os.File) fsapi.File { +func newOsFile(path string, flag experimentalsys.Oflag, perm fs.FileMode, f *os.File) experimentalsys.File { // Windows cannot read files written to a directory after it was opened. // This was noticed in #1087 in zig tests. Use a flag instead of a // different type. @@ -23,7 +22,7 @@ func newOsFile(path string, flag fsapi.Oflag, perm fs.FileMode, f *os.File) fsap // implement api.File. type osFile struct { path string - flag fsapi.Oflag + flag experimentalsys.Oflag perm fs.FileMode file *os.File fd uintptr @@ -41,7 +40,7 @@ type osFile struct { cachedSt *cachedStat } -// cachedStat returns the cacheable parts of fsapi.Stat_t or an error if they +// cachedStat returns the cacheable parts of sys.Stat_t or an error if they // couldn't be retrieved. func (f *osFile) cachedStat() (dev uint64, ino sys.Inode, isDir bool, errno experimentalsys.Errno) { if f.cachedSt == nil { @@ -52,19 +51,19 @@ func (f *osFile) cachedStat() (dev uint64, ino sys.Inode, isDir bool, errno expe return f.cachedSt.dev, f.cachedSt.ino, f.cachedSt.isDir, 0 } -// Dev implements the same method as documented on fsapi.File +// Dev implements the same method as documented on sys.File func (f *osFile) Dev() (uint64, experimentalsys.Errno) { dev, _, _, errno := f.cachedStat() return dev, errno } -// Ino implements the same method as documented on fsapi.File +// Ino implements the same method as documented on sys.File func (f *osFile) Ino() (sys.Inode, experimentalsys.Errno) { _, ino, _, errno := f.cachedStat() return ino, errno } -// IsDir implements the same method as documented on fsapi.File +// IsDir implements the same method as documented on sys.File func (f *osFile) IsDir() (bool, experimentalsys.Errno) { _, _, isDir, errno := f.cachedStat() return isDir, errno @@ -72,19 +71,19 @@ func (f *osFile) IsDir() (bool, experimentalsys.Errno) { // IsAppend implements File.IsAppend func (f *osFile) IsAppend() bool { - return f.flag&fsapi.O_APPEND == fsapi.O_APPEND + return f.flag&experimentalsys.O_APPEND == experimentalsys.O_APPEND } -// SetAppend implements the same method as documented on fsapi.File +// SetAppend implements the same method as documented on sys.File func (f *osFile) SetAppend(enable bool) (errno experimentalsys.Errno) { if enable { - f.flag |= fsapi.O_APPEND + f.flag |= experimentalsys.O_APPEND } else { - f.flag &= ^fsapi.O_APPEND + f.flag &= ^experimentalsys.O_APPEND } // Clear any create flag, as we are re-opening, not re-creating. - f.flag &= ^fsapi.O_CREAT + f.flag &= ^experimentalsys.O_CREAT // appendMode (bool) cannot be changed later, so we have to re-open the // file. https://github.com/golang/go/blob/go1.20/src/os/file_unix.go#L60 @@ -96,24 +95,24 @@ var _ reopenFile = (*fsFile)(nil).reopen func (f *osFile) reopen() (errno experimentalsys.Errno) { // Clear any create flag, as we are re-opening, not re-creating. - f.flag &= ^fsapi.O_CREAT + f.flag &= ^experimentalsys.O_CREAT _ = f.close() f.file, errno = OpenFile(f.path, f.flag, f.perm) return } -// IsNonblock implements the same method as documented on fsapi.File +// IsNonblock implements the same method as documented on sys.File func (f *osFile) IsNonblock() bool { return isNonblock(f) } -// SetNonblock implements the same method as documented on fsapi.File +// SetNonblock implements the same method as documented on sys.File func (f *osFile) SetNonblock(enable bool) (errno experimentalsys.Errno) { if enable { - f.flag |= fsapi.O_NONBLOCK + f.flag |= experimentalsys.O_NONBLOCK } else { - f.flag &= ^fsapi.O_NONBLOCK + f.flag &= ^experimentalsys.O_NONBLOCK } if errno = setNonblock(f.fd, enable); errno != 0 { return fileError(f, f.closed, errno) @@ -121,7 +120,7 @@ func (f *osFile) SetNonblock(enable bool) (errno experimentalsys.Errno) { return 0 } -// Stat implements the same method as documented on fsapi.File +// Stat implements the same method as documented on sys.File func (f *osFile) Stat() (sys.Stat_t, experimentalsys.Errno) { if f.closed { return sys.Stat_t{}, experimentalsys.EBADF @@ -137,7 +136,7 @@ func (f *osFile) Stat() (sys.Stat_t, experimentalsys.Errno) { return st, errno } -// Read implements the same method as documented on fsapi.File +// Read implements the same method as documented on sys.File func (f *osFile) Read(buf []byte) (n int, errno experimentalsys.Errno) { if len(buf) == 0 { return 0, 0 // Short-circuit 0-len reads. @@ -154,7 +153,7 @@ func (f *osFile) Read(buf []byte) (n int, errno experimentalsys.Errno) { return } -// Pread implements the same method as documented on fsapi.File +// Pread implements the same method as documented on sys.File func (f *osFile) Pread(buf []byte, off int64) (n int, errno experimentalsys.Errno) { if n, errno = pread(f.file, buf, off); errno != 0 { // Defer validation overhead until we've already had an error. @@ -163,7 +162,7 @@ func (f *osFile) Pread(buf []byte, off int64) (n int, errno experimentalsys.Errn return } -// Seek implements the same method as documented on fsapi.File +// Seek implements the same method as documented on sys.File func (f *osFile) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) { if newOffset, errno = seek(f.file, offset, whence); errno != 0 { // Defer validation overhead until we've already had an error. @@ -179,14 +178,14 @@ func (f *osFile) Seek(offset int64, whence int) (newOffset int64, errno experime return } -// Poll implements the same method as documented on fsapi.File -func (f *osFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { +// Poll implements the same method as documented on sys.File +func (f *osFile) Poll(flag experimentalsys.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) { return poll(f.fd, flag, timeoutMillis) } // Readdir implements File.Readdir. Notably, this uses "Readdir", not // "ReadDir", from os.File. -func (f *osFile) Readdir(n int) (dirents []fsapi.Dirent, errno experimentalsys.Errno) { +func (f *osFile) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { if f.reopenDir { // re-open the directory if needed. f.reopenDir = false if errno = adjustReaddirErr(f, f.closed, f.reopen()); errno != 0 { @@ -200,7 +199,7 @@ func (f *osFile) Readdir(n int) (dirents []fsapi.Dirent, errno experimentalsys.E return } -// Write implements the same method as documented on fsapi.File +// Write implements the same method as documented on sys.File func (f *osFile) Write(buf []byte) (n int, errno experimentalsys.Errno) { if len(buf) == 0 { return 0, 0 // Short-circuit 0-len writes. @@ -214,7 +213,7 @@ func (f *osFile) Write(buf []byte) (n int, errno experimentalsys.Errno) { return } -// Pwrite implements the same method as documented on fsapi.File +// Pwrite implements the same method as documented on sys.File func (f *osFile) Pwrite(buf []byte, off int64) (n int, errno experimentalsys.Errno) { if n, errno = pwrite(f.file, buf, off); errno != 0 { // Defer validation overhead until we've already had an error. @@ -223,7 +222,7 @@ func (f *osFile) Pwrite(buf []byte, off int64) (n int, errno experimentalsys.Err return } -// Truncate implements the same method as documented on fsapi.File +// Truncate implements the same method as documented on sys.File func (f *osFile) Truncate(size int64) (errno experimentalsys.Errno) { if errno = experimentalsys.UnwrapOSError(f.file.Truncate(size)); errno != 0 { // Defer validation overhead until we've already had an error. @@ -232,17 +231,17 @@ func (f *osFile) Truncate(size int64) (errno experimentalsys.Errno) { return } -// Sync implements the same method as documented on fsapi.File +// Sync implements the same method as documented on sys.File func (f *osFile) Sync() experimentalsys.Errno { return fsync(f.file) } -// Datasync implements the same method as documented on fsapi.File +// Datasync implements the same method as documented on sys.File func (f *osFile) Datasync() experimentalsys.Errno { return datasync(f.file) } -// Utimens implements the same method as documented on fsapi.File +// Utimens implements the same method as documented on sys.File func (f *osFile) Utimens(atim, mtim int64) experimentalsys.Errno { if f.closed { return experimentalsys.EBADF @@ -252,7 +251,7 @@ func (f *osFile) Utimens(atim, mtim int64) experimentalsys.Errno { return experimentalsys.UnwrapOSError(err) } -// Close implements the same method as documented on fsapi.File +// Close implements the same method as documented on sys.File func (f *osFile) Close() experimentalsys.Errno { if f.closed { return 0 diff --git a/internal/sysfs/poll.go b/internal/sysfs/poll.go index 09c14b9aaf..4041699fcf 100644 --- a/internal/sysfs/poll.go +++ b/internal/sysfs/poll.go @@ -4,12 +4,11 @@ package sysfs import ( "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) -// poll implements `Poll` as documented on fsapi.File via a file descriptor. -func poll(fd uintptr, flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno sys.Errno) { - if flag != fsapi.POLLIN { +// poll implements `Poll` as documented on sys.File via a file descriptor. +func poll(fd uintptr, flag sys.Pflag, timeoutMillis int32) (ready bool, errno sys.Errno) { + if flag != sys.POLLIN { return false, sys.ENOTSUP } fds := []pollFd{newPollFd(fd, _POLLIN, 0)} diff --git a/internal/sysfs/poll_unsupported.go b/internal/sysfs/poll_unsupported.go index 0d07492bf9..f546e1549a 100644 --- a/internal/sysfs/poll_unsupported.go +++ b/internal/sysfs/poll_unsupported.go @@ -4,10 +4,9 @@ package sysfs import ( "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) -// poll implements `Poll` as documented on fsapi.File via a file descriptor. -func poll(fd uintptr, flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno sys.Errno) { +// poll implements `Poll` as documented on sys.File via a file descriptor. +func poll(fd uintptr, flag sys.Pflag, timeoutMillis int32) (ready bool, errno sys.Errno) { return false, sys.ENOSYS } diff --git a/internal/sysfs/readfs.go b/internal/sysfs/readfs.go index 6e5fd65024..a81b64c0bf 100644 --- a/internal/sysfs/readfs.go +++ b/internal/sysfs/readfs.go @@ -4,28 +4,27 @@ import ( "io/fs" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" ) -// NewReadFS is used to mask an existing fsapi.FS for reads. Notably, this allows +// NewReadFS is used to mask an existing sys.FS for reads. Notably, this allows // the CLI to do read-only mounts of directories the host user can write, but // doesn't want the guest wasm to. For example, Python libraries shouldn't be // written to at runtime by the python wasm file. -func NewReadFS(fs fsapi.FS) fsapi.FS { +func NewReadFS(fs experimentalsys.FS) experimentalsys.FS { if _, ok := fs.(*readFS); ok { return fs - } else if _, ok = fs.(fsapi.UnimplementedFS); ok { + } else if _, ok = fs.(experimentalsys.UnimplementedFS); ok { return fs // unimplemented is read-only } return &readFS{fs} } type readFS struct { - fsapi.FS + experimentalsys.FS } -// OpenFile implements the same method as documented on fsapi.FS -func (r *readFS) OpenFile(path string, flag fsapi.Oflag, perm fs.FileMode) (fsapi.File, experimentalsys.Errno) { +// OpenFile implements the same method as documented on sys.FS +func (r *readFS) OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { // TODO: Once the real implementation is complete, move the below to // /RATIONALE.md. Doing this while the type is unstable creates // documentation drift as we expect a lot of reshaping meanwhile. @@ -45,13 +44,13 @@ func (r *readFS) OpenFile(path string, flag fsapi.Oflag, perm fs.FileMode) (fsap // there isn't a current flag to OR in with that, there may be in the // future. What we do instead is mask the flags about read/write mode and // check if they are the opposite of read or not. - switch flag & (fsapi.O_RDONLY | fsapi.O_WRONLY | fsapi.O_RDWR) { - case fsapi.O_WRONLY, fsapi.O_RDWR: - if flag&fsapi.O_DIRECTORY != 0 { + switch flag & (experimentalsys.O_RDONLY | experimentalsys.O_WRONLY | experimentalsys.O_RDWR) { + case experimentalsys.O_WRONLY, experimentalsys.O_RDWR: + if flag&experimentalsys.O_DIRECTORY != 0 { return nil, experimentalsys.EISDIR } return nil, experimentalsys.ENOSYS - default: // fsapi.O_RDONLY (or no flag) so we are ok! + default: // sys.O_RDONLY (or no flag) so we are ok! } f, errno := r.FS.OpenFile(path, flag, perm) @@ -61,79 +60,79 @@ func (r *readFS) OpenFile(path string, flag fsapi.Oflag, perm fs.FileMode) (fsap return &readFile{f}, 0 } -// Mkdir implements the same method as documented on fsapi.FS +// Mkdir implements the same method as documented on sys.FS func (r *readFS) Mkdir(path string, perm fs.FileMode) experimentalsys.Errno { return experimentalsys.EROFS } -// Chmod implements the same method as documented on fsapi.FS +// Chmod implements the same method as documented on sys.FS func (r *readFS) Chmod(path string, perm fs.FileMode) experimentalsys.Errno { return experimentalsys.EROFS } -// Rename implements the same method as documented on fsapi.FS +// Rename implements the same method as documented on sys.FS func (r *readFS) Rename(from, to string) experimentalsys.Errno { return experimentalsys.EROFS } -// Rmdir implements the same method as documented on fsapi.FS +// Rmdir implements the same method as documented on sys.FS func (r *readFS) Rmdir(path string) experimentalsys.Errno { return experimentalsys.EROFS } -// Link implements the same method as documented on fsapi.FS +// Link implements the same method as documented on sys.FS func (r *readFS) Link(_, _ string) experimentalsys.Errno { return experimentalsys.EROFS } -// Symlink implements the same method as documented on fsapi.FS +// Symlink implements the same method as documented on sys.FS func (r *readFS) Symlink(_, _ string) experimentalsys.Errno { return experimentalsys.EROFS } -// Unlink implements the same method as documented on fsapi.FS +// Unlink implements the same method as documented on sys.FS func (r *readFS) Unlink(path string) experimentalsys.Errno { return experimentalsys.EROFS } -// Utimens implements the same method as documented on fsapi.FS +// Utimens implements the same method as documented on sys.FS func (r *readFS) Utimens(path string, atim, mtim int64) experimentalsys.Errno { return experimentalsys.EROFS } // compile-time check to ensure readFile implements api.File. -var _ fsapi.File = (*readFile)(nil) +var _ experimentalsys.File = (*readFile)(nil) type readFile struct { - fsapi.File + experimentalsys.File } -// Write implements the same method as documented on fsapi.File. +// Write implements the same method as documented on sys.File. func (r *readFile) Write([]byte) (int, experimentalsys.Errno) { return 0, r.writeErr() } -// Pwrite implements the same method as documented on fsapi.File. +// Pwrite implements the same method as documented on sys.File. func (r *readFile) Pwrite([]byte, int64) (n int, errno experimentalsys.Errno) { return 0, r.writeErr() } -// Truncate implements the same method as documented on fsapi.File. +// Truncate implements the same method as documented on sys.File. func (r *readFile) Truncate(int64) experimentalsys.Errno { return r.writeErr() } -// Sync implements the same method as documented on fsapi.File. +// Sync implements the same method as documented on sys.File. func (r *readFile) Sync() experimentalsys.Errno { return experimentalsys.EBADF } -// Datasync implements the same method as documented on fsapi.File. +// Datasync implements the same method as documented on sys.File. func (r *readFile) Datasync() experimentalsys.Errno { return experimentalsys.EBADF } -// Utimens implements the same method as documented on fsapi.File. +// Utimens implements the same method as documented on sys.File. func (r *readFile) Utimens(int64, int64) experimentalsys.Errno { return experimentalsys.EBADF } diff --git a/internal/sysfs/readfs_test.go b/internal/sysfs/readfs_test.go index 6e877ad7c8..25a47fa318 100644 --- a/internal/sysfs/readfs_test.go +++ b/internal/sysfs/readfs_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/testing/require" ) @@ -16,9 +15,9 @@ func TestNewReadFS(t *testing.T) { tmpDir := t.TempDir() // Doesn't double-wrap file systems that are already read-only - require.Equal(t, fsapi.UnimplementedFS{}, NewReadFS(fsapi.UnimplementedFS{})) + require.Equal(t, sys.UnimplementedFS{}, NewReadFS(sys.UnimplementedFS{})) - // Wraps a fsapi.FS because it allows access to Write + // Wraps a sys.FS because it allows access to Write adapted := Adapt(os.DirFS(tmpDir)) require.NotEqual(t, adapted, NewReadFS(adapted)) @@ -114,14 +113,14 @@ func TestReadFS_UtimesNano(t *testing.T) { realPath := joinPath(tmpDir, path) require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600)) - err := testFS.Utimens(path, fsapi.UTIME_OMIT, fsapi.UTIME_OMIT) + err := testFS.Utimens(path, sys.UTIME_OMIT, sys.UTIME_OMIT) require.EqualErrno(t, sys.EROFS, err) } func TestReadFS_Open_Read(t *testing.T) { type test struct { name string - fs func(tmpDir string) fsapi.FS + fs func(tmpDir string) sys.FS expectFileIno bool expectDirIno bool } @@ -129,7 +128,7 @@ func TestReadFS_Open_Read(t *testing.T) { tests := []test{ { name: "DirFS", - fs: func(tmpDir string) fsapi.FS { + fs: func(tmpDir string) sys.FS { return NewDirFS(tmpDir) }, expectFileIno: true, @@ -137,7 +136,7 @@ func TestReadFS_Open_Read(t *testing.T) { }, { name: "fstest.MapFS", - fs: func(tmpDir string) fsapi.FS { + fs: func(tmpDir string) sys.FS { return Adapt(fstest.FS) }, expectFileIno: false, @@ -145,7 +144,7 @@ func TestReadFS_Open_Read(t *testing.T) { }, { name: "os.DirFS", - fs: func(tmpDir string) fsapi.FS { + fs: func(tmpDir string) sys.FS { return Adapt(os.DirFS(tmpDir)) }, expectFileIno: statSetsIno(), @@ -153,7 +152,7 @@ func TestReadFS_Open_Read(t *testing.T) { }, { name: "mask(os.DirFS)", - fs: func(tmpDir string) fsapi.FS { + fs: func(tmpDir string) sys.FS { return Adapt(&MaskOsFS{Fs: os.DirFS(tmpDir)}) }, expectFileIno: statSetsIno(), @@ -161,7 +160,7 @@ func TestReadFS_Open_Read(t *testing.T) { }, { name: "mask(os.DirFS) ZeroIno", - fs: func(tmpDir string) fsapi.FS { + fs: func(tmpDir string) sys.FS { return Adapt(&MaskOsFS{Fs: os.DirFS(tmpDir), ZeroIno: true}) }, expectFileIno: false, diff --git a/internal/sysfs/sock.go b/internal/sysfs/sock.go index ea59409943..af739a9082 100644 --- a/internal/sysfs/sock.go +++ b/internal/sysfs/sock.go @@ -5,7 +5,6 @@ import ( "os" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" socketapi "github.com/tetratelabs/wazero/internal/sock" "github.com/tetratelabs/wazero/sys" ) @@ -18,10 +17,10 @@ func NewTCPListenerFile(tl *net.TCPListener) socketapi.TCPSock { // baseSockFile implements base behavior for all TCPSock, TCPConn files, // regardless the platform. type baseSockFile struct { - fsapi.UnimplementedFile + experimentalsys.UnimplementedFile } -var _ fsapi.File = (*baseSockFile)(nil) +var _ experimentalsys.File = (*baseSockFile)(nil) // IsDir implements the same method as documented on File.IsDir func (*baseSockFile) IsDir() (bool, experimentalsys.Errno) { diff --git a/internal/sysfs/sock_unix.go b/internal/sysfs/sock_unix.go index 2509a17303..ef67952091 100644 --- a/internal/sysfs/sock_unix.go +++ b/internal/sysfs/sock_unix.go @@ -55,12 +55,12 @@ func (f *tcpListenerFile) Accept() (socketapi.TCPConn, sys.Errno) { return &tcpConnFile{fd: uintptr(nfd)}, 0 } -// SetNonblock implements the same method as documented on fsapi.File +// SetNonblock implements the same method as documented on sys.File func (f *tcpListenerFile) SetNonblock(enabled bool) sys.Errno { return sys.UnwrapOSError(setNonblock(f.fd, enabled)) } -// Close implements the same method as documented on fsapi.File +// Close implements the same method as documented on sys.File func (f *tcpListenerFile) Close() sys.Errno { return sys.UnwrapOSError(syscall.Close(int(f.fd))) } @@ -89,12 +89,12 @@ func newTcpConn(tc *net.TCPConn) socketapi.TCPConn { return &tcpConnFile{fd: f.Fd()} } -// SetNonblock implements the same method as documented on fsapi.File +// SetNonblock implements the same method as documented on sys.File func (f *tcpConnFile) SetNonblock(enabled bool) (errno sys.Errno) { return sys.UnwrapOSError(setNonblock(f.fd, enabled)) } -// Read implements the same method as documented on fsapi.File +// Read implements the same method as documented on sys.File func (f *tcpConnFile) Read(buf []byte) (n int, errno sys.Errno) { n, err := syscall.Read(int(f.fd), buf) if err != nil { @@ -105,7 +105,7 @@ func (f *tcpConnFile) Read(buf []byte) (n int, errno sys.Errno) { return n, errno } -// Write implements the same method as documented on fsapi.File +// Write implements the same method as documented on sys.File func (f *tcpConnFile) Write(buf []byte) (n int, errno sys.Errno) { n, err := syscall.Write(int(f.fd), buf) if err != nil { @@ -127,7 +127,7 @@ func (f *tcpConnFile) Recvfrom(p []byte, flags int) (n int, errno sys.Errno) { return n, errno } -// Shutdown implements the same method as documented on fsapi.Conn +// Shutdown implements the same method as documented on sys.Conn func (f *tcpConnFile) Shutdown(how int) sys.Errno { var err error switch how { @@ -141,7 +141,7 @@ func (f *tcpConnFile) Shutdown(how int) sys.Errno { return sys.UnwrapOSError(err) } -// Close implements the same method as documented on fsapi.File +// Close implements the same method as documented on sys.File func (f *tcpConnFile) Close() sys.Errno { return f.close() } diff --git a/internal/sysfs/sock_windows.go b/internal/sysfs/sock_windows.go index db8c6ac6ff..325d739f92 100644 --- a/internal/sysfs/sock_windows.go +++ b/internal/sysfs/sock_windows.go @@ -141,7 +141,7 @@ func (f *winTcpListenerFile) IsNonblock() bool { return f.nonblock } -// SetNonblock implements the same method as documented on fsapi.File +// SetNonblock implements the same method as documented on sys.File func (f *winTcpListenerFile) SetNonblock(enabled bool) sys.Errno { f.nonblock = enabled _, errno := syscallConnControl(f.tl, func(fd uintptr) (int, sys.Errno) { @@ -150,7 +150,7 @@ func (f *winTcpListenerFile) SetNonblock(enabled bool) sys.Errno { return errno } -// Close implements the same method as documented on fsapi.File +// Close implements the same method as documented on sys.File func (f *winTcpListenerFile) Close() sys.Errno { if !f.closed { return sys.UnwrapOSError(f.tl.Close()) @@ -184,7 +184,7 @@ func newTcpConn(tc *net.TCPConn) socketapi.TCPConn { return &winTcpConnFile{tc: tc} } -// SetNonblock implements the same method as documented on fsapi.File +// SetNonblock implements the same method as documented on sys.File func (f *winTcpConnFile) SetNonblock(enabled bool) (errno sys.Errno) { _, errno = syscallConnControl(f.tc, func(fd uintptr) (int, sys.Errno) { return 0, sys.UnwrapOSError(setNonblockSocket(syscall.Handle(fd), enabled)) @@ -197,7 +197,7 @@ func (f *winTcpConnFile) IsNonblock() bool { return f.nonblock } -// Read implements the same method as documented on fsapi.File +// Read implements the same method as documented on sys.File func (f *winTcpConnFile) Read(buf []byte) (n int, errno sys.Errno) { if len(buf) == 0 { return 0, 0 // Short-circuit 0-len reads. @@ -216,7 +216,7 @@ func (f *winTcpConnFile) Read(buf []byte) (n int, errno sys.Errno) { return } -// Write implements the same method as documented on fsapi.File +// Write implements the same method as documented on sys.File func (f *winTcpConnFile) Write(buf []byte) (n int, errno sys.Errno) { if nonBlockingFileWriteSupported && f.IsNonblock() { return syscallConnControl(f.tc, func(fd uintptr) (int, sys.Errno) { @@ -243,7 +243,7 @@ func (f *winTcpConnFile) Recvfrom(p []byte, flags int) (n int, errno sys.Errno) }) } -// Shutdown implements the same method as documented on fsapi.Conn +// Shutdown implements the same method as documented on sys.Conn func (f *winTcpConnFile) Shutdown(how int) sys.Errno { // FIXME: can userland shutdown listeners? var err error @@ -260,7 +260,7 @@ func (f *winTcpConnFile) Shutdown(how int) sys.Errno { return sys.UnwrapOSError(err) } -// Close implements the same method as documented on fsapi.File +// Close implements the same method as documented on sys.File func (f *winTcpConnFile) Close() sys.Errno { return f.close() } diff --git a/internal/sysfs/stat_test.go b/internal/sysfs/stat_test.go index 81df9b1e44..8dbaf5eb3a 100644 --- a/internal/sysfs/stat_test.go +++ b/internal/sysfs/stat_test.go @@ -8,7 +8,6 @@ import ( "time" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/testing/require" "github.com/tetratelabs/wazero/sys" ) @@ -104,7 +103,7 @@ func TestStat(t *testing.T) { func TestStatFile(t *testing.T) { tmpDir := t.TempDir() - tmpDirF := requireOpenFile(t, tmpDir, fsapi.O_RDONLY, 0) + tmpDirF := requireOpenFile(t, tmpDir, experimentalsys.O_RDONLY, 0) defer tmpDirF.Close() t.Run("dir", func(t *testing.T) { @@ -126,7 +125,7 @@ func TestStatFile(t *testing.T) { file := path.Join(tmpDir, "file") require.NoError(t, os.WriteFile(file, nil, 0o400)) - fileF := requireOpenFile(t, file, fsapi.O_RDONLY, 0) + fileF := requireOpenFile(t, file, experimentalsys.O_RDONLY, 0) defer fileF.Close() t.Run("file", func(t *testing.T) { @@ -145,7 +144,7 @@ func TestStatFile(t *testing.T) { subdir := path.Join(tmpDir, "sub") require.NoError(t, os.Mkdir(subdir, 0o500)) - subdirF := requireOpenFile(t, subdir, fsapi.O_RDONLY, 0) + subdirF := requireOpenFile(t, subdir, experimentalsys.O_RDONLY, 0) defer subdirF.Close() t.Run("subdir", func(t *testing.T) { @@ -203,7 +202,7 @@ func Test_StatFile_times(t *testing.T) { err := os.Chtimes(file, time.UnixMicro(tc.atimeNsec/1e3), time.UnixMicro(tc.mtimeNsec/1e3)) require.NoError(t, err) - f := requireOpenFile(t, file, fsapi.O_RDONLY, 0) + f := requireOpenFile(t, file, experimentalsys.O_RDONLY, 0) defer f.Close() st, errno := f.Stat() @@ -217,21 +216,21 @@ func Test_StatFile_times(t *testing.T) { func TestStatFile_dev_inode(t *testing.T) { tmpDir := t.TempDir() - d := requireOpenFile(t, tmpDir, fsapi.O_RDONLY, 0) + d := requireOpenFile(t, tmpDir, experimentalsys.O_RDONLY, 0) defer d.Close() path1 := path.Join(tmpDir, "1") - f1 := requireOpenFile(t, path1, fsapi.O_CREAT, 0o666) + f1 := requireOpenFile(t, path1, experimentalsys.O_CREAT, 0o666) defer f1.Close() path2 := path.Join(tmpDir, "2") - f2 := requireOpenFile(t, path2, fsapi.O_CREAT, 0o666) + f2 := requireOpenFile(t, path2, experimentalsys.O_CREAT, 0o666) defer f2.Close() pathLink2 := path.Join(tmpDir, "link2") err := os.Symlink(path2, pathLink2) require.NoError(t, err) - l2 := requireOpenFile(t, pathLink2, fsapi.O_RDONLY, 0) + l2 := requireOpenFile(t, pathLink2, experimentalsys.O_RDONLY, 0) defer l2.Close() // First, stat the directory @@ -274,7 +273,7 @@ func TestStatFile_dev_inode(t *testing.T) { // Renaming a file shouldn't change its inodes. require.EqualErrno(t, 0, rename(path1, path2)) - f1 = requireOpenFile(t, path2, fsapi.O_RDONLY, 0) + f1 = requireOpenFile(t, path2, experimentalsys.O_RDONLY, 0) defer f1.Close() st1Again, errno = f1.Stat() @@ -283,7 +282,7 @@ func TestStatFile_dev_inode(t *testing.T) { require.Equal(t, st1.Ino, st1Again.Ino) } -func requireNotDir(t *testing.T, d fsapi.File, st sys.Stat_t) { +func requireNotDir(t *testing.T, d experimentalsys.File, st sys.Stat_t) { // Verify cached state is correct isDir, errno := d.IsDir() require.EqualErrno(t, 0, errno) @@ -291,7 +290,7 @@ func requireNotDir(t *testing.T, d fsapi.File, st sys.Stat_t) { require.False(t, st.Mode.IsDir()) } -func requireDir(t *testing.T, d fsapi.File, st sys.Stat_t) { +func requireDir(t *testing.T, d experimentalsys.File, st sys.Stat_t) { // Verify cached state is correct isDir, errno := d.IsDir() require.EqualErrno(t, 0, errno) @@ -299,7 +298,7 @@ func requireDir(t *testing.T, d fsapi.File, st sys.Stat_t) { require.True(t, st.Mode.IsDir()) } -func requireDevIno(t *testing.T, f fsapi.File, st sys.Stat_t) { +func requireDevIno(t *testing.T, f experimentalsys.File, st sys.Stat_t) { // Results are inconsistent, so don't validate the opposite. if statSetsIno() { require.NotEqual(t, uint64(0), st.Dev) diff --git a/internal/sysfs/sysfs_test.go b/internal/sysfs/sysfs_test.go index 0b8149d3a6..0411b8dc4e 100644 --- a/internal/sysfs/sysfs_test.go +++ b/internal/sysfs/sysfs_test.go @@ -11,19 +11,18 @@ import ( "testing" experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" "github.com/tetratelabs/wazero/internal/platform" "github.com/tetratelabs/wazero/internal/testing/require" "github.com/tetratelabs/wazero/sys" ) -func testOpen_O_RDWR(t *testing.T, tmpDir string, testFS fsapi.FS) { +func testOpen_O_RDWR(t *testing.T, tmpDir string, testFS experimentalsys.FS) { file := "file" realPath := path.Join(tmpDir, file) err := os.WriteFile(realPath, []byte{}, 0o600) require.NoError(t, err) - f, errno := testFS.OpenFile(file, fsapi.O_RDWR, 0) + f, errno := testFS.OpenFile(file, experimentalsys.O_RDWR, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -42,7 +41,7 @@ func testOpen_O_RDWR(t *testing.T, tmpDir string, testFS fsapi.FS) { // re-create as read-only, using 0444 to allow read-back on windows. require.NoError(t, os.Remove(realPath)) - f, errno = testFS.OpenFile(file, fsapi.O_RDONLY|fsapi.O_CREAT, 0o444) + f, errno = testFS.OpenFile(file, experimentalsys.O_RDONLY|experimentalsys.O_CREAT, 0o444) require.EqualErrno(t, 0, errno) defer f.Close() @@ -60,7 +59,7 @@ func testOpen_O_RDWR(t *testing.T, tmpDir string, testFS fsapi.FS) { // from os.TestDirFSPathsValid if runtime.GOOS != "windows" { t.Run("strange name", func(t *testing.T) { - f, errno = testFS.OpenFile(`e:xperi\ment.txt`, fsapi.O_WRONLY|fsapi.O_CREAT|fsapi.O_TRUNC, 0o600) + f, errno = testFS.OpenFile(`e:xperi\ment.txt`, experimentalsys.O_WRONLY|experimentalsys.O_CREAT|experimentalsys.O_TRUNC, 0o600) require.EqualErrno(t, 0, errno) defer f.Close() @@ -77,7 +76,7 @@ func testOpen_O_RDWR(t *testing.T, tmpDir string, testFS fsapi.FS) { realPath := path.Join(tmpDir, name) require.NoError(t, os.WriteFile(realPath, []byte("123456"), 0o0666)) - f, errno = testFS.OpenFile(name, fsapi.O_RDWR|fsapi.O_TRUNC, 0o444) + f, errno = testFS.OpenFile(name, experimentalsys.O_RDWR|experimentalsys.O_TRUNC, 0o444) require.EqualErrno(t, 0, errno) require.EqualErrno(t, 0, f.Close()) @@ -87,18 +86,18 @@ func testOpen_O_RDWR(t *testing.T, tmpDir string, testFS fsapi.FS) { }) } -func testOpen_Read(t *testing.T, testFS fsapi.FS, requireFileIno, expectDirIno bool) { +func testOpen_Read(t *testing.T, testFS experimentalsys.FS, requireFileIno, expectDirIno bool) { t.Helper() t.Run("doesn't exist", func(t *testing.T) { - _, errno := testFS.OpenFile("nope", fsapi.O_RDONLY, 0) + _, errno := testFS.OpenFile("nope", experimentalsys.O_RDONLY, 0) // We currently follow os.Open not syscall.Open, so the error is wrapped. require.EqualErrno(t, experimentalsys.ENOENT, errno) }) t.Run("readdir . opens root", func(t *testing.T) { - f, errno := testFS.OpenFile(".", fsapi.O_RDONLY, 0) + f, errno := testFS.OpenFile(".", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -109,7 +108,7 @@ func testOpen_Read(t *testing.T, testFS fsapi.FS, requireFileIno, expectDirIno b dirents[i].Ino = 0 } - require.Equal(t, []fsapi.Dirent{ + require.Equal(t, []experimentalsys.Dirent{ {Name: "animals.txt", Type: 0}, {Name: "dir", Type: fs.ModeDir}, {Name: "empty.txt", Type: 0}, @@ -119,7 +118,7 @@ func testOpen_Read(t *testing.T, testFS fsapi.FS, requireFileIno, expectDirIno b }) t.Run("readdir empty", func(t *testing.T) { - f, errno := testFS.OpenFile("emptydir", fsapi.O_RDONLY, 0) + f, errno := testFS.OpenFile("emptydir", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -128,7 +127,7 @@ func testOpen_Read(t *testing.T, testFS fsapi.FS, requireFileIno, expectDirIno b }) t.Run("readdir partial", func(t *testing.T) { - dirF, errno := testFS.OpenFile("dir", fsapi.O_RDONLY, 0) + dirF, errno := testFS.OpenFile("dir", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer dirF.Close() @@ -145,7 +144,7 @@ func testOpen_Read(t *testing.T, testFS fsapi.FS, requireFileIno, expectDirIno b require.EqualErrno(t, 0, errno) require.Equal(t, 1, len(dirents3)) - dirents := []fsapi.Dirent{dirents1[0], dirents2[0], dirents3[0]} + dirents := []experimentalsys.Dirent{dirents1[0], dirents2[0], dirents3[0]} sort.Slice(dirents, func(i, j int) bool { return dirents[i].Name < dirents[j].Name }) requireIno(t, dirents, expectDirIno) @@ -155,7 +154,7 @@ func testOpen_Read(t *testing.T, testFS fsapi.FS, requireFileIno, expectDirIno b dirents[i].Ino = 0 } - require.Equal(t, []fsapi.Dirent{ + require.Equal(t, []experimentalsys.Dirent{ {Name: "-", Type: 0}, {Name: "a-", Type: fs.ModeDir}, {Name: "ab-", Type: 0}, @@ -167,7 +166,7 @@ func testOpen_Read(t *testing.T, testFS fsapi.FS, requireFileIno, expectDirIno b }) t.Run("file exists", func(t *testing.T) { - f, errno := testFS.OpenFile("animals.txt", fsapi.O_RDONLY, 0) + f, errno := testFS.OpenFile("animals.txt", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -198,7 +197,7 @@ human }) t.Run("file stat includes inode", func(t *testing.T) { - f, errno := testFS.OpenFile("empty.txt", fsapi.O_RDONLY, 0) + f, errno := testFS.OpenFile("empty.txt", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -215,15 +214,15 @@ human t.Run("or'd flag", func(t *testing.T) { // Example of a flag that can be or'd into O_RDONLY even if not // currently supported in WASI or GOOS=js - const O_NOATIME = fsapi.Oflag(0x40000) + const O_NOATIME = experimentalsys.Oflag(0x40000) - f, errno := testFS.OpenFile("animals.txt", fsapi.O_RDONLY|O_NOATIME, 0) + f, errno := testFS.OpenFile("animals.txt", experimentalsys.O_RDONLY|O_NOATIME, 0) require.EqualErrno(t, 0, errno) defer f.Close() }) t.Run("writing to a read-only file is EBADF", func(t *testing.T) { - f, errno := testFS.OpenFile("animals.txt", fsapi.O_RDONLY, 0) + f, errno := testFS.OpenFile("animals.txt", experimentalsys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) defer f.Close() @@ -232,12 +231,12 @@ human }) t.Run("opening a directory with O_RDWR is EISDIR", func(t *testing.T) { - _, errno := testFS.OpenFile("sub", fsapi.O_DIRECTORY|fsapi.O_RDWR, 0) + _, errno := testFS.OpenFile("sub", experimentalsys.O_DIRECTORY|experimentalsys.O_RDWR, 0) require.EqualErrno(t, experimentalsys.EISDIR, errno) }) } -func testLstat(t *testing.T, testFS fsapi.FS) { +func testLstat(t *testing.T, testFS experimentalsys.FS) { _, errno := testFS.Lstat("cat") require.EqualErrno(t, experimentalsys.ENOENT, errno) _, errno = testFS.Lstat("sub/cat") @@ -289,7 +288,7 @@ func testLstat(t *testing.T, testFS fsapi.FS) { }) } -func requireLinkStat(t *testing.T, testFS fsapi.FS, path string, stat sys.Stat_t) { +func requireLinkStat(t *testing.T, testFS experimentalsys.FS, path string, stat sys.Stat_t) { link := path + "-link" stLink, errno := testFS.Lstat(link) require.EqualErrno(t, 0, errno) @@ -306,7 +305,7 @@ func requireLinkStat(t *testing.T, testFS fsapi.FS, path string, stat sys.Stat_t } } -func testStat(t *testing.T, testFS fsapi.FS) { +func testStat(t *testing.T, testFS experimentalsys.FS) { _, errno := testFS.Stat("cat") require.EqualErrno(t, experimentalsys.ENOENT, errno) _, errno = testFS.Stat("sub/cat") @@ -332,7 +331,7 @@ func testStat(t *testing.T, testFS fsapi.FS) { // requireReaddir ensures the input file is a directory, and returns its // entries. -func requireReaddir(t *testing.T, f fsapi.File, n int, expectDirIno bool) []fsapi.Dirent { +func requireReaddir(t *testing.T, f experimentalsys.File, n int, expectDirIno bool) []experimentalsys.Dirent { entries, errno := f.Readdir(n) require.EqualErrno(t, 0, errno) @@ -341,7 +340,7 @@ func requireReaddir(t *testing.T, f fsapi.File, n int, expectDirIno bool) []fsap return entries } -func testReadlink(t *testing.T, readFS, writeFS fsapi.FS) { +func testReadlink(t *testing.T, readFS, writeFS experimentalsys.FS) { testLinks := []struct { old, dst string }{ @@ -373,7 +372,7 @@ func testReadlink(t *testing.T, readFS, writeFS fsapi.FS) { }) } -func requireIno(t *testing.T, dirents []fsapi.Dirent, expectDirIno bool) { +func requireIno(t *testing.T, dirents []experimentalsys.Dirent, expectDirIno bool) { for i := range dirents { d := dirents[i] if expectDirIno { diff --git a/internal/wasm/module_instance_test.go b/internal/wasm/module_instance_test.go index 1c33588a44..7be778546f 100644 --- a/internal/wasm/module_instance_test.go +++ b/internal/wasm/module_instance_test.go @@ -10,7 +10,6 @@ import ( "time" "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" internalsys "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/sysfs" testfs "github.com/tetratelabs/wazero/internal/testing/fs" @@ -117,7 +116,7 @@ func TestModuleInstance_Close(t *testing.T) { sysCtx := internalsys.DefaultContext(testFS) fsCtx := sysCtx.FS() - _, errno := fsCtx.OpenFile(testFS, "/foo", fsapi.O_RDONLY, 0) + _, errno := fsCtx.OpenFile(testFS, "/foo", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil) @@ -152,13 +151,13 @@ func TestModuleInstance_Close(t *testing.T) { sysCtx := internalsys.DefaultContext(testFS) fsCtx := sysCtx.FS() - _, errno := fsCtx.OpenFile(testFS, "/foo", fsapi.O_RDONLY, 0) + _, errno := fsCtx.OpenFile(testFS, "/foo", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil) require.NoError(t, err) - // In fsapi.FS, non syscall errors map to sys.EIO. + // In sys.FS, non syscall errors map to sys.EIO. require.EqualErrno(t, sys.EIO, m.Close(testCtx)) // Verify our intended side-effect @@ -222,7 +221,7 @@ func TestModuleInstance_CallDynamic(t *testing.T) { sysCtx := internalsys.DefaultContext(testFS) fsCtx := sysCtx.FS() - _, errno := fsCtx.OpenFile(testFS, "/foo", fsapi.O_RDONLY, 0) + _, errno := fsCtx.OpenFile(testFS, "/foo", sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil) @@ -251,13 +250,13 @@ func TestModuleInstance_CallDynamic(t *testing.T) { fsCtx := sysCtx.FS() path := "/foo" - _, errno := fsCtx.OpenFile(testFS, path, fsapi.O_RDONLY, 0) + _, errno := fsCtx.OpenFile(testFS, path, sys.O_RDONLY, 0) require.EqualErrno(t, 0, errno) m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil) require.NoError(t, err) - // In fsapi.FS, non syscall errors map to sys.EIO. + // In sys.FS, non syscall errors map to sys.EIO. require.EqualErrno(t, sys.EIO, m.Close(testCtx)) // Verify our intended side-effect