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 }