github.com/tetratelabs/wazero@v1.2.1/internal/fsapi/file.go (about) 1 package fsapi 2 3 import ( 4 "io/fs" 5 "syscall" 6 "time" 7 ) 8 9 // File is a writeable fs.File bridge backed by syscall functions needed for ABI 10 // including WASI and runtime.GOOS=js. 11 // 12 // Implementations should embed UnimplementedFile for forward compatability. Any 13 // unsupported method or parameter should return syscall.ENOSYS. 14 // 15 // # Errors 16 // 17 // All methods that can return an error return a syscall.Errno, which is zero 18 // on success. 19 // 20 // Restricting to syscall.Errno matches current WebAssembly host functions, 21 // which are constrained to well-known error codes. For example, `GOOS=js` maps 22 // hard coded values and panics otherwise. More commonly, WASI maps syscall 23 // errors to u32 numeric values. 24 // 25 // # Notes 26 // 27 // A writable filesystem abstraction is not yet implemented as of Go 1.20. See 28 // https://github.com/golang/go/issues/45757 29 type File interface { 30 // Ino returns the inode (Stat_t.Ino) of this file, zero if unknown or an 31 // error there was an error retrieving it. 32 // 33 // # Errors 34 // 35 // Possible errors are those from Stat, except syscall.ENOSYS should not 36 // be returned. Zero should be returned if there is no implementation. 37 // 38 // # Notes 39 // 40 // - Some implementations implement this with a cached call to Stat. 41 Ino() (uint64, syscall.Errno) 42 43 // IsNonblock returns true if the file was opened with O_NONBLOCK, or 44 // SetNonblock was successfully enabled on this file. 45 // 46 // # Notes 47 // 48 // - This might not match the underlying state of the file descriptor if 49 // the file was not opened via OpenFile. 50 IsNonblock() bool 51 52 // SetNonblock toggles the non-blocking mode (O_NONBLOCK) of this file. 53 // 54 // # Errors 55 // 56 // A zero syscall.Errno is success. The below are expected otherwise: 57 // - syscall.ENOSYS: the implementation does not support this function. 58 // - syscall.EBADF: the file or directory was closed. 59 // 60 // # Notes 61 // 62 // - This is like syscall.SetNonblock and `fcntl` with O_NONBLOCK in 63 // POSIX. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html 64 SetNonblock(enable bool) syscall.Errno 65 66 // IsAppend returns true if the file was opened with syscall.O_APPEND, or 67 // SetAppend was successfully enabled on this file. 68 // 69 // # Notes 70 // 71 // - This might not match the underlying state of the file descriptor if 72 // the file was not opened via OpenFile. 73 IsAppend() bool 74 75 // SetAppend toggles the append mode (syscall.O_APPEND) of this file. 76 // 77 // # Errors 78 // 79 // A zero syscall.Errno is success. The below are expected otherwise: 80 // - syscall.ENOSYS: the implementation does not support this function. 81 // - syscall.EBADF: the file or directory was closed. 82 // 83 // # Notes 84 // 85 // - There is no `O_APPEND` for `fcntl` in POSIX, so implementations may 86 // have to re-open the underlying file to apply this. See 87 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html 88 SetAppend(enable bool) syscall.Errno 89 90 // Stat is similar to syscall.Fstat. 91 // 92 // # Errors 93 // 94 // A zero syscall.Errno is success. The below are expected otherwise: 95 // - syscall.ENOSYS: the implementation does not support this function. 96 // - syscall.EBADF: the file or directory was closed. 97 // 98 // # Notes 99 // 100 // - This is like syscall.Fstat and `fstatat` with `AT_FDCWD` in POSIX. 101 // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html 102 // - A fs.FileInfo backed implementation sets atim, mtim and ctim to the 103 // same value. 104 // - Windows allows you to stat a closed directory. 105 Stat() (Stat_t, syscall.Errno) 106 107 // IsDir returns true if this file is a directory or an error there was an 108 // error retrieving this information. 109 // 110 // # Errors 111 // 112 // Possible errors are those from Stat. 113 // 114 // # Notes 115 // 116 // - Some implementations implement this with a cached call to Stat. 117 IsDir() (bool, syscall.Errno) 118 119 // Read attempts to read all bytes in the file into `buf`, and returns the 120 // count read even on error. 121 // 122 // # Errors 123 // 124 // A zero syscall.Errno is success. The below are expected otherwise: 125 // - syscall.ENOSYS: the implementation does not support this function. 126 // - syscall.EBADF: the file or directory was closed or not readable. 127 // - syscall.EISDIR: the file was a directory. 128 // 129 // # Notes 130 // 131 // - This is like io.Reader and `read` in POSIX, preferring semantics of 132 // io.Reader. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html 133 // - Unlike io.Reader, there is no io.EOF returned on end-of-file. To 134 // read the file completely, the caller must repeat until `n` is zero. 135 Read(buf []byte) (n int, errno syscall.Errno) 136 137 // Pread attempts to read all bytes in the file into `p`, starting at the 138 // offset `off`, and returns the count read even on error. 139 // 140 // # Errors 141 // 142 // A zero syscall.Errno is success. The below are expected otherwise: 143 // - syscall.ENOSYS: the implementation does not support this function. 144 // - syscall.EBADF: the file or directory was closed or not readable. 145 // - syscall.EINVAL: the offset was negative. 146 // - syscall.EISDIR: the file was a directory. 147 // 148 // # Notes 149 // 150 // - This is like io.ReaderAt and `pread` in POSIX, preferring semantics 151 // of io.ReaderAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html 152 // - Unlike io.ReaderAt, there is no io.EOF returned on end-of-file. To 153 // read the file completely, the caller must repeat until `n` is zero. 154 Pread(buf []byte, off int64) (n int, errno syscall.Errno) 155 156 // Seek attempts to set the next offset for Read or Write and returns the 157 // resulting absolute offset or an error. 158 // 159 // # Parameters 160 // 161 // The `offset` parameters is interpreted in terms of `whence`: 162 // - io.SeekStart: relative to the start of the file, e.g. offset=0 sets 163 // the next Read or Write to the beginning of the file. 164 // - io.SeekCurrent: relative to the current offset, e.g. offset=16 sets 165 // the next Read or Write 16 bytes past the prior. 166 // - io.SeekEnd: relative to the end of the file, e.g. offset=-1 sets the 167 // next Read or Write to the last byte in the file. 168 // 169 // # Behavior when a directory 170 // 171 // The only supported use case for a directory is seeking to `offset` zero 172 // (`whence` = io.SeekStart). This should have the same behavior as 173 // os.File, which resets any internal state used by Readdir. 174 // 175 // # Errors 176 // 177 // A zero syscall.Errno is success. The below are expected otherwise: 178 // - syscall.ENOSYS: the implementation does not support this function. 179 // - syscall.EBADF: the file or directory was closed or not readable. 180 // - syscall.EINVAL: the offset was negative. 181 // 182 // # Notes 183 // 184 // - This is like io.Seeker and `fseek` in POSIX, preferring semantics 185 // of io.Seeker. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fseek.html 186 Seek(offset int64, whence int) (newOffset int64, errno syscall.Errno) 187 188 // PollRead returns if the file has data ready to be read or an error. 189 // 190 // # Parameters 191 // 192 // The `timeout` parameter when nil blocks up to forever. 193 // 194 // # Errors 195 // 196 // A zero syscall.Errno is success. The below are expected otherwise: 197 // - syscall.ENOSYS: the implementation does not support this function. 198 // 199 // # Notes 200 // 201 // - This is like `poll` in POSIX, for a single file. 202 // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html 203 // - No-op files, such as those which read from /dev/null, should return 204 // immediately true to avoid hangs (because data will never become 205 // available). 206 PollRead(timeout *time.Duration) (ready bool, errno syscall.Errno) 207 208 // Readdir reads the contents of the directory associated with file and 209 // returns a slice of up to n Dirent values in an arbitrary order. This is 210 // a stateful function, so subsequent calls return any next values. 211 // 212 // If n > 0, Readdir returns at most n entries or an error. 213 // If n <= 0, Readdir returns all remaining entries or an error. 214 // 215 // # Errors 216 // 217 // A zero syscall.Errno is success. The below are expected otherwise: 218 // - syscall.ENOSYS: the implementation does not support this function. 219 // - syscall.ENOTDIR: the file was not a directory 220 // 221 // # Notes 222 // 223 // - This is like `Readdir` on os.File, but unlike `readdir` in POSIX. 224 // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html 225 // - For portability reasons, no error is returned at the end of the 226 // directory, when the file is closed or removed while open. 227 // See https://github.com/ziglang/zig/blob/0.10.1/lib/std/fs.zig#L635-L637 228 Readdir(n int) (dirents []Dirent, errno syscall.Errno) 229 // ^-- TODO: consider being more like POSIX, for example, returning a 230 // closeable Dirent object that can iterate on demand. This would 231 // centralize sizing logic needed by wasi, particularly extra dirents 232 // stored in the sys.FileEntry type. It could possibly reduce the need to 233 // reopen the whole file. 234 235 // Write attempts to write all bytes in `p` to the file, and returns the 236 // count written even on error. 237 // 238 // # Errors 239 // 240 // A zero syscall.Errno is success. The below are expected otherwise: 241 // - syscall.ENOSYS: the implementation does not support this function. 242 // - syscall.EBADF: the file was closed, not writeable, or a directory. 243 // 244 // # Notes 245 // 246 // - This is like io.Writer and `write` in POSIX, preferring semantics of 247 // io.Writer. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html 248 Write(buf []byte) (n int, errno syscall.Errno) 249 250 // Pwrite attempts to write all bytes in `p` to the file at the given 251 // offset `off`, and returns the count written even on error. 252 // 253 // # Errors 254 // 255 // A zero syscall.Errno is success. The below are expected otherwise: 256 // - syscall.ENOSYS: the implementation does not support this function. 257 // - syscall.EBADF: the file or directory was closed or not writeable. 258 // - syscall.EINVAL: the offset was negative. 259 // - syscall.EISDIR: the file was a directory. 260 // 261 // # Notes 262 // 263 // - This is like io.WriterAt and `pwrite` in POSIX, preferring semantics 264 // of io.WriterAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html 265 Pwrite(buf []byte, off int64) (n int, errno syscall.Errno) 266 267 // Truncate truncates a file to a specified length. 268 // 269 // # Errors 270 // 271 // A zero syscall.Errno is success. The below are expected otherwise: 272 // - syscall.ENOSYS: the implementation does not support this function. 273 // - syscall.EBADF: the file or directory was closed. 274 // - syscall.EINVAL: the `size` is negative. 275 // - syscall.EISDIR: the file was a directory. 276 // 277 // # Notes 278 // 279 // - This is like syscall.Ftruncate and `ftruncate` in POSIX. See 280 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html 281 // - Windows does not error when calling Truncate on a closed file. 282 Truncate(size int64) syscall.Errno 283 284 // Sync synchronizes changes to the file. 285 // 286 // # Errors 287 // 288 // A zero syscall.Errno is success. The below are expected otherwise: 289 // - syscall.EBADF: the file or directory was closed. 290 // 291 // # Notes 292 // 293 // - This is like syscall.Fsync and `fsync` in POSIX. See 294 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html 295 // - This returns with no error instead of syscall.ENOSYS when 296 // unimplemented. This prevents fake filesystems from erring. 297 // - Windows does not error when calling Sync on a closed file. 298 Sync() syscall.Errno 299 300 // Datasync synchronizes the data of a file. 301 // 302 // # Errors 303 // 304 // A zero syscall.Errno is success. The below are expected otherwise: 305 // - syscall.EBADF: the file or directory was closed. 306 // 307 // # Notes 308 // 309 // - This is like syscall.Fdatasync and `fdatasync` in POSIX. See 310 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html 311 // - This returns with no error instead of syscall.ENOSYS when 312 // unimplemented. This prevents fake filesystems from erring. 313 // - As this is commonly missing, some implementations dispatch to Sync. 314 Datasync() syscall.Errno 315 316 // Chmod changes the mode of the file. 317 // 318 // # Errors 319 // 320 // A zero syscall.Errno is success. The below are expected otherwise: 321 // - syscall.ENOSYS: the implementation does not support this function. 322 // - syscall.EBADF: the file or directory was closed. 323 // 324 // # Notes 325 // 326 // - This is like syscall.Fchmod and `fchmod` in POSIX. See 327 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html 328 // - Windows ignores the execute bit, and any permissions come back as 329 // group and world. For example, chmod of 0400 reads back as 0444, and 330 // 0700 0666. Also, permissions on directories aren't supported at all. 331 Chmod(fs.FileMode) syscall.Errno 332 333 // Chown changes the owner and group of a file. 334 // 335 // # Errors 336 // 337 // A zero syscall.Errno is success. The below are expected otherwise: 338 // - syscall.ENOSYS: the implementation does not support this function. 339 // - syscall.EBADF: the file or directory was closed. 340 // 341 // # Notes 342 // 343 // - This is like syscall.Fchown and `fchown` in POSIX. See 344 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html 345 // - This always returns syscall.ENOSYS on windows. 346 Chown(uid, gid int) syscall.Errno 347 348 // Utimens set file access and modification times of this file, at 349 // nanosecond precision. 350 // 351 // # Parameters 352 // 353 // The `times` parameter includes the access and modification timestamps to 354 // assign. Special syscall.Timespec NSec values UTIME_NOW and UTIME_OMIT may be 355 // specified instead of real timestamps. A nil `times` parameter behaves the 356 // same as if both were set to UTIME_NOW. 357 // 358 // # Errors 359 // 360 // A zero syscall.Errno is success. The below are expected otherwise: 361 // - syscall.ENOSYS: the implementation does not support this function. 362 // - syscall.EBADF: the file or directory was closed. 363 // 364 // # Notes 365 // 366 // - This is like syscall.UtimesNano and `futimens` in POSIX. See 367 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html 368 // - Windows requires files to be open with syscall.O_RDWR, which means you 369 // cannot use this to update timestamps on a directory (syscall.EPERM). 370 Utimens(times *[2]syscall.Timespec) syscall.Errno 371 372 // Close closes the underlying file. 373 // 374 // A zero syscall.Errno is success. The below are expected otherwise: 375 // - syscall.ENOSYS: the implementation does not support this function. 376 // 377 // # Notes 378 // 379 // - This is like syscall.Close and `close` in POSIX. See 380 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html 381 Close() syscall.Errno 382 }