github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/experimental/sys/fs.go (about)

     1  package sys
     2  
     3  import (
     4  	"io/fs"
     5  
     6  	"github.com/tetratelabs/wazero/sys"
     7  )
     8  
     9  // FS is a writeable fs.FS bridge backed by syscall functions needed for ABI
    10  // including WASI.
    11  //
    12  // Implementations should embed UnimplementedFS for forward compatibility. Any
    13  // unsupported method or parameter should return ENO
    14  //
    15  // # Errors
    16  //
    17  // All methods that can return an error return a Errno, which is zero
    18  // on success.
    19  //
    20  // Restricting to Errno matches current WebAssembly host functions,
    21  // which are constrained to well-known error codes. For example, WASI maps syscall
    22  // errors to u32 numeric values.
    23  //
    24  // # Notes
    25  //
    26  // A writable filesystem abstraction is not yet implemented as of Go 1.20. See
    27  // https://github.com/golang/go/issues/45757
    28  type FS interface {
    29  	// OpenFile opens a file. It should be closed via Close on File.
    30  	//
    31  	// # Errors
    32  	//
    33  	// A zero Errno is success. The below are expected otherwise:
    34  	//   - ENOSYS: the implementation does not support this function.
    35  	//   - EINVAL: `path` or `flag` is invalid.
    36  	//   - EISDIR: the path was a directory, but flag included O_RDWR or
    37  	//     O_WRONLY
    38  	//   - ENOENT: `path` doesn't exist and `flag` doesn't contain O_CREAT.
    39  	//
    40  	// # Constraints on the returned file
    41  	//
    42  	// Implementations that can read flags should enforce them regardless of
    43  	// the type returned. For example, while os.File implements io.Writer,
    44  	// attempts to write to a directory or a file opened with O_RDONLY fail
    45  	// with a EBADF.
    46  	//
    47  	// Some implementations choose whether to enforce read-only opens, namely
    48  	// fs.FS. While fs.FS is supported (Adapt), wazero cannot runtime enforce
    49  	// open flags. Instead, we encourage good behavior and test our built-in
    50  	// implementations.
    51  	//
    52  	// # Notes
    53  	//
    54  	//   - This is like os.OpenFile, except the path is relative to this file
    55  	//     system, and Errno is returned instead of os.PathError.
    56  	//   - Implications of permissions when O_CREAT are described in Chmod notes.
    57  	//   - This is like `open` in POSIX. See
    58  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
    59  	OpenFile(path string, flag Oflag, perm fs.FileMode) (File, Errno)
    60  
    61  	// Lstat gets file status without following symbolic links.
    62  	//
    63  	// # Errors
    64  	//
    65  	// A zero Errno is success. The below are expected otherwise:
    66  	//   - ENOSYS: the implementation does not support this function.
    67  	//   - ENOENT: `path` doesn't exist.
    68  	//
    69  	// # Notes
    70  	//
    71  	//   - This is like syscall.Lstat, except the `path` is relative to this
    72  	//     file system.
    73  	//   - This is like `lstat` in POSIX. See
    74  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/lstat.html
    75  	//   - An fs.FileInfo backed implementation sets atim, mtim and ctim to the
    76  	//     same value.
    77  	//   - When the path is a symbolic link, the stat returned is for the link,
    78  	//     not the file it refers to.
    79  	Lstat(path string) (sys.Stat_t, Errno)
    80  
    81  	// Stat gets file status.
    82  	//
    83  	// # Errors
    84  	//
    85  	// A zero Errno is success. The below are expected otherwise:
    86  	//   - ENOSYS: the implementation does not support this function.
    87  	//   - ENOENT: `path` doesn't exist.
    88  	//
    89  	// # Notes
    90  	//
    91  	//   - This is like syscall.Stat, except the `path` is relative to this
    92  	//     file system.
    93  	//   - This is like `stat` in POSIX. See
    94  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html
    95  	//   - An fs.FileInfo backed implementation sets atim, mtim and ctim to the
    96  	//     same value.
    97  	//   - When the path is a symbolic link, the stat returned is for the file
    98  	//     it refers to.
    99  	Stat(path string) (sys.Stat_t, Errno)
   100  
   101  	// Mkdir makes a directory.
   102  	//
   103  	// # Errors
   104  	//
   105  	// A zero Errno is success. The below are expected otherwise:
   106  	//   - ENOSYS: the implementation does not support this function.
   107  	//   - EINVAL: `path` is invalid.
   108  	//   - EEXIST: `path` exists and is a directory.
   109  	//   - ENOTDIR: `path` exists and is a file.
   110  	//
   111  	// # Notes
   112  	//
   113  	//   - This is like syscall.Mkdir, except the `path` is relative to this
   114  	//     file system.
   115  	//   - This is like `mkdir` in POSIX. See
   116  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html
   117  	//   - Implications of permissions are described in Chmod notes.
   118  	Mkdir(path string, perm fs.FileMode) Errno
   119  
   120  	// Chmod changes the mode of the file.
   121  	//
   122  	// # Errors
   123  	//
   124  	// A zero Errno is success. The below are expected otherwise:
   125  	//   - ENOSYS: the implementation does not support this function.
   126  	//   - EINVAL: `path` is invalid.
   127  	//   - ENOENT: `path` does not exist.
   128  	//
   129  	// # Notes
   130  	//
   131  	//   - This is like syscall.Chmod, except the `path` is relative to this
   132  	//     file system.
   133  	//   - This is like `chmod` in POSIX. See
   134  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/chmod.html
   135  	//   - Windows ignores the execute bit, and any permissions come back as
   136  	//     group and world. For example, chmod of 0400 reads back as 0444, and
   137  	//     0700 0666. Also, permissions on directories aren't supported at all.
   138  	Chmod(path string, perm fs.FileMode) Errno
   139  
   140  	// Rename renames file or directory.
   141  	//
   142  	// # Errors
   143  	//
   144  	// A zero Errno is success. The below are expected otherwise:
   145  	//   - ENOSYS: the implementation does not support this function.
   146  	//   - EINVAL: `from` or `to` is invalid.
   147  	//   - ENOENT: `from` or `to` don't exist.
   148  	//   - ENOTDIR: `from` is a directory and `to` exists as a file.
   149  	//   - EISDIR: `from` is a file and `to` exists as a directory.
   150  	//   - ENOTEMPTY: `both from` and `to` are existing directory, but
   151  	//    `to` is not empty.
   152  	//
   153  	// # Notes
   154  	//
   155  	//   - This is like syscall.Rename, except the paths are relative to this
   156  	//     file system.
   157  	//   - This is like `rename` in POSIX. See
   158  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html
   159  	//   -  Windows doesn't let you overwrite an existing directory.
   160  	Rename(from, to string) Errno
   161  
   162  	// Rmdir removes a directory.
   163  	//
   164  	// # Errors
   165  	//
   166  	// A zero Errno is success. The below are expected otherwise:
   167  	//   - ENOSYS: the implementation does not support this function.
   168  	//   - EINVAL: `path` is invalid.
   169  	//   - ENOENT: `path` doesn't exist.
   170  	//   - ENOTDIR: `path` exists, but isn't a directory.
   171  	//   - ENOTEMPTY: `path` exists, but isn't empty.
   172  	//
   173  	// # Notes
   174  	//
   175  	//   - This is like syscall.Rmdir, except the `path` is relative to this
   176  	//     file system.
   177  	//   - This is like `rmdir` in POSIX. See
   178  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html
   179  	//   - As of Go 1.19, Windows maps ENOTDIR to ENOENT.
   180  	Rmdir(path string) Errno
   181  
   182  	// Unlink removes a directory entry.
   183  	//
   184  	// # Errors
   185  	//
   186  	// A zero Errno is success. The below are expected otherwise:
   187  	//   - ENOSYS: the implementation does not support this function.
   188  	//   - EINVAL: `path` is invalid.
   189  	//   - ENOENT: `path` doesn't exist.
   190  	//   - EISDIR: `path` exists, but is a directory.
   191  	//
   192  	// # Notes
   193  	//
   194  	//   - This is like syscall.Unlink, except the `path` is relative to this
   195  	//     file system.
   196  	//   - This is like `unlink` in POSIX. See
   197  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html
   198  	//   - On Windows, syscall.Unlink doesn't delete symlink to directory unlike other platforms. Implementations might
   199  	//     want to combine syscall.RemoveDirectory with syscall.Unlink in order to delete such links on Windows.
   200  	//     See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya
   201  	Unlink(path string) Errno
   202  
   203  	// Link creates a "hard" link from oldPath to newPath, in contrast to a
   204  	// soft link (via Symlink).
   205  	//
   206  	// # Errors
   207  	//
   208  	// A zero Errno is success. The below are expected otherwise:
   209  	//   - ENOSYS: the implementation does not support this function.
   210  	//   - EPERM: `oldPath` is invalid.
   211  	//   - ENOENT: `oldPath` doesn't exist.
   212  	//   - EISDIR: `newPath` exists, but is a directory.
   213  	//
   214  	// # Notes
   215  	//
   216  	//   - This is like syscall.Link, except the `oldPath` is relative to this
   217  	//     file system.
   218  	//   - This is like `link` in POSIX. See
   219  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html
   220  	Link(oldPath, newPath string) Errno
   221  
   222  	// Symlink creates a "soft" link from oldPath to newPath, in contrast to a
   223  	// hard link (via Link).
   224  	//
   225  	// # Errors
   226  	//
   227  	// A zero Errno is success. The below are expected otherwise:
   228  	//   - ENOSYS: the implementation does not support this function.
   229  	//   - EPERM: `oldPath` or `newPath` is invalid.
   230  	//   - EEXIST: `newPath` exists.
   231  	//
   232  	// # Notes
   233  	//
   234  	//   - This is like syscall.Symlink, except the `oldPath` is relative to
   235  	//     this file system.
   236  	//   - This is like `symlink` in POSIX. See
   237  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlink.html
   238  	//   - Only `newPath` is relative to this file system and `oldPath` is kept
   239  	//     as-is. That is because the link is only resolved relative to the
   240  	//     directory when dereferencing it (e.g. ReadLink).
   241  	//     See https://github.com/bytecodealliance/cap-std/blob/v1.0.4/cap-std/src/fs/dir.rs#L404-L409
   242  	//     for how others implement this.
   243  	//   - Symlinks in Windows requires `SeCreateSymbolicLinkPrivilege`.
   244  	//     Otherwise, EPERM results.
   245  	//     See https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
   246  	Symlink(oldPath, linkName string) Errno
   247  
   248  	// Readlink reads the contents of a symbolic link.
   249  	//
   250  	// # Errors
   251  	//
   252  	// A zero Errno is success. The below are expected otherwise:
   253  	//   - ENOSYS: the implementation does not support this function.
   254  	//   - EINVAL: `path` is invalid.
   255  	//
   256  	// # Notes
   257  	//
   258  	//   - This is like syscall.Readlink, except the path is relative to this
   259  	//     filesystem.
   260  	//   - This is like `readlink` in POSIX. See
   261  	//     https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html
   262  	//   - On Windows, the path separator is different from other platforms,
   263  	//     but to provide consistent results to Wasm, this normalizes to a "/"
   264  	//     separator.
   265  	Readlink(path string) (string, Errno)
   266  
   267  	// Utimens set file access and modification times on a path relative to
   268  	// this file system, at nanosecond precision.
   269  	//
   270  	// # Parameters
   271  	//
   272  	// If the path is a symbolic link, the target of expanding that link is
   273  	// updated.
   274  	//
   275  	// The `atim` and `mtim` parameters refer to access and modification time
   276  	// stamps as defined in sys.Stat_t. To retain one or the other, substitute
   277  	// it with the pseudo-timestamp UTIME_OMIT.
   278  	//
   279  	// # Errors
   280  	//
   281  	// A zero Errno is success. The below are expected otherwise:
   282  	//   - ENOSYS: the implementation does not support this function.
   283  	//   - EINVAL: `path` is invalid.
   284  	//   - EEXIST: `path` exists and is a directory.
   285  	//   - ENOTDIR: `path` exists and is a file.
   286  	//
   287  	// # Notes
   288  	//
   289  	//   - This is like syscall.UtimesNano and `utimensat` with `AT_FDCWD` in
   290  	//     POSIX. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
   291  	Utimens(path string, atim, mtim int64) Errno
   292  }