1package sys
2
3import "github.com/tetratelabs/wazero/sys"
4
5// File is a writeable fs.File bridge backed by syscall functions needed for ABI
6// including WASI.
7//
8// Implementations should embed UnimplementedFile for forward compatibility. Any
9// unsupported method or parameter should return ENOSYS.
10//
11// # Errors
12//
13// All methods that can return an error return a Errno, which is zero
14// on success.
15//
16// Restricting to Errno matches current WebAssembly host functions,
17// which are constrained to well-known error codes. For example, WASI maps syscall
18// errors to u32 numeric values.
19//
20// # Notes
21//
22// - You must call Close to avoid file resource conflicts. For example,
23// Windows cannot delete the underlying directory while a handle to it
24// remains open.
25// - A writable filesystem abstraction is not yet implemented as of Go 1.20.
26// See https://github.com/golang/go/issues/45757
27type File interface {
28 // Dev returns the device ID (Stat_t.Dev) of this file, zero if unknown or
29 // an error retrieving it.
30 //
31 // # Errors
32 //
33 // Possible errors are those from Stat, except ENOSYS should not
34 // be returned. Zero should be returned if there is no implementation.
35 //
36 // # Notes
37 //
38 // - Implementations should cache this result.
39 // - This combined with Ino can implement os.SameFile.
40 Dev() (uint64, Errno)
41
42 // Ino returns the serial number (Stat_t.Ino) of this file, zero if unknown
43 // or an error retrieving it.
44 //
45 // # Errors
46 //
47 // Possible errors are those from Stat, except ENOSYS should not
48 // be returned. Zero should be returned if there is no implementation.
49 //
50 // # Notes
51 //
52 // - Implementations should cache this result.
53 // - This combined with Dev can implement os.SameFile.
54 Ino() (sys.Inode, Errno)
55
56 // IsDir returns true if this file is a directory or an error there was an
57 // error retrieving this information.
58 //
59 // # Errors
60 //
61 // Possible errors are those from Stat, except ENOSYS should not
62 // be returned. false should be returned if there is no implementation.
63 //
64 // # Notes
65 //
66 // - Implementations should cache this result.
67 IsDir() (bool, Errno)
68
69 // IsAppend returns true if the file was opened with O_APPEND, or
70 // SetAppend was successfully enabled on this file.
71 //
72 // # Notes
73 //
74 // - This might not match the underlying state of the file descriptor if
75 // the file was not opened via OpenFile.
76 IsAppend() bool
77
78 // SetAppend toggles the append mode (O_APPEND) of this file.
79 //
80 // # Errors
81 //
82 // A zero Errno is success. The below are expected otherwise:
83 // - ENOSYS: the implementation does not support this function.
84 // - EBADF: the file or directory was closed.
85 //
86 // # Notes
87 //
88 // - There is no `O_APPEND` for `fcntl` in POSIX, so implementations may
89 // have to re-open the underlying file to apply this. See
90 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
91 SetAppend(enable bool) Errno
92
93 // Stat is similar to syscall.Fstat.
94 //
95 // # Errors
96 //
97 // A zero Errno is success. The below are expected otherwise:
98 // - ENOSYS: the implementation does not support this function.
99 // - EBADF: the file or directory was closed.
100 //
101 // # Notes
102 //
103 // - This is like syscall.Fstat and `fstatat` with `AT_FDCWD` in POSIX.
104 // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html
105 // - A fs.FileInfo backed implementation sets atim, mtim and ctim to the
106 // same value.
107 // - Windows allows you to stat a closed directory.
108 Stat() (sys.Stat_t, Errno)
109
110 // Read attempts to read all bytes in the file into `buf`, and returns the
111 // count read even on error.
112 //
113 // # Errors
114 //
115 // A zero Errno is success. The below are expected otherwise:
116 // - ENOSYS: the implementation does not support this function.
117 // - EBADF: the file or directory was closed or not readable.
118 // - EISDIR: the file was a directory.
119 //
120 // # Notes
121 //
122 // - This is like io.Reader and `read` in POSIX, preferring semantics of
123 // io.Reader. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
124 // - Unlike io.Reader, there is no io.EOF returned on end-of-file. To
125 // read the file completely, the caller must repeat until `n` is zero.
126 Read(buf []byte) (n int, errno Errno)
127
128 // Pread attempts to read all bytes in the file into `p`, starting at the
129 // offset `off`, and returns the count read even on error.
130 //
131 // # Errors
132 //
133 // A zero Errno is success. The below are expected otherwise:
134 // - ENOSYS: the implementation does not support this function.
135 // - EBADF: the file or directory was closed or not readable.
136 // - EINVAL: the offset was negative.
137 // - EISDIR: the file was a directory.
138 //
139 // # Notes
140 //
141 // - This is like io.ReaderAt and `pread` in POSIX, preferring semantics
142 // of io.ReaderAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html
143 // - Unlike io.ReaderAt, there is no io.EOF returned on end-of-file. To
144 // read the file completely, the caller must repeat until `n` is zero.
145 Pread(buf []byte, off int64) (n int, errno Errno)
146
147 // Seek attempts to set the next offset for Read or Write and returns the
148 // resulting absolute offset or an error.
149 //
150 // # Parameters
151 //
152 // The `offset` parameters is interpreted in terms of `whence`:
153 // - io.SeekStart: relative to the start of the file, e.g. offset=0 sets
154 // the next Read or Write to the beginning of the file.
155 // - io.SeekCurrent: relative to the current offset, e.g. offset=16 sets
156 // the next Read or Write 16 bytes past the prior.
157 // - io.SeekEnd: relative to the end of the file, e.g. offset=-1 sets the
158 // next Read or Write to the last byte in the file.
159 //
160 // # Behavior when a directory
161 //
162 // The only supported use case for a directory is seeking to `offset` zero
163 // (`whence` = io.SeekStart). This should have the same behavior as
164 // os.File, which resets any internal state used by Readdir.
165 //
166 // # Errors
167 //
168 // A zero Errno is success. The below are expected otherwise:
169 // - ENOSYS: the implementation does not support this function.
170 // - EBADF: the file or directory was closed or not readable.
171 // - EINVAL: the offset was negative.
172 //
173 // # Notes
174 //
175 // - This is like io.Seeker and `fseek` in POSIX, preferring semantics
176 // of io.Seeker. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fseek.html
177 Seek(offset int64, whence int) (newOffset int64, errno Errno)
178
179 // Readdir reads the contents of the directory associated with file and
180 // returns a slice of up to n Dirent values in an arbitrary order. This is
181 // a stateful function, so subsequent calls return any next values.
182 //
183 // If n > 0, Readdir returns at most n entries or an error.
184 // If n <= 0, Readdir returns all remaining entries or an error.
185 //
186 // # Errors
187 //
188 // A zero Errno is success. The below are expected otherwise:
189 // - ENOSYS: the implementation does not support this function.
190 // - EBADF: the file was closed or not a directory.
191 // - ENOENT: the directory could not be read (e.g. deleted).
192 //
193 // # Notes
194 //
195 // - This is like `Readdir` on os.File, but unlike `readdir` in POSIX.
196 // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html
197 // - Unlike os.File, there is no io.EOF returned on end-of-directory. To
198 // read the directory completely, the caller must repeat until the
199 // count read (`len(dirents)`) is less than `n`.
200 // - See /RATIONALE.md for design notes.
201 Readdir(n int) (dirents []Dirent, errno Errno)
202
203 // Write attempts to write all bytes in `p` to the file, and returns the
204 // count written even on error.
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 // - EBADF: the file was closed, not writeable, or a directory.
211 //
212 // # Notes
213 //
214 // - This is like io.Writer and `write` in POSIX, preferring semantics of
215 // io.Writer. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
216 Write(buf []byte) (n int, errno Errno)
217
218 // Pwrite attempts to write all bytes in `p` to the file at the given
219 // offset `off`, and returns the count written even on error.
220 //
221 // # Errors
222 //
223 // A zero Errno is success. The below are expected otherwise:
224 // - ENOSYS: the implementation does not support this function.
225 // - EBADF: the file or directory was closed or not writeable.
226 // - EINVAL: the offset was negative.
227 // - EISDIR: the file was a directory.
228 //
229 // # Notes
230 //
231 // - This is like io.WriterAt and `pwrite` in POSIX, preferring semantics
232 // of io.WriterAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html
233 Pwrite(buf []byte, off int64) (n int, errno Errno)
234
235 // Truncate truncates a file to a specified length.
236 //
237 // # Errors
238 //
239 // A zero Errno is success. The below are expected otherwise:
240 // - ENOSYS: the implementation does not support this function.
241 // - EBADF: the file or directory was closed.
242 // - EINVAL: the `size` is negative.
243 // - EISDIR: the file was a directory.
244 //
245 // # Notes
246 //
247 // - This is like syscall.Ftruncate and `ftruncate` in POSIX. See
248 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
249 // - Windows does not error when calling Truncate on a closed file.
250 Truncate(size int64) Errno
251
252 // Sync synchronizes changes to the file.
253 //
254 // # Errors
255 //
256 // A zero Errno is success. The below are expected otherwise:
257 // - EBADF: the file or directory was closed.
258 //
259 // # Notes
260 //
261 // - This is like syscall.Fsync and `fsync` in POSIX. See
262 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html
263 // - This returns with no error instead of ENOSYS when
264 // unimplemented. This prevents fake filesystems from erring.
265 // - Windows does not error when calling Sync on a closed file.
266 Sync() Errno
267
268 // Datasync synchronizes the data of a file.
269 //
270 // # Errors
271 //
272 // A zero Errno is success. The below are expected otherwise:
273 // - EBADF: the file or directory was closed.
274 //
275 // # Notes
276 //
277 // - This is like syscall.Fdatasync and `fdatasync` in POSIX. See
278 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html
279 // - This returns with no error instead of ENOSYS when
280 // unimplemented. This prevents fake filesystems from erring.
281 // - As this is commonly missing, some implementations dispatch to Sync.
282 Datasync() Errno
283
284 // Utimens set file access and modification times of this file, at
285 // nanosecond precision.
286 //
287 // # Parameters
288 //
289 // The `atim` and `mtim` parameters refer to access and modification time
290 // stamps as defined in sys.Stat_t. To retain one or the other, substitute
291 // it with the pseudo-timestamp UTIME_OMIT.
292 //
293 // # Errors
294 //
295 // A zero Errno is success. The below are expected otherwise:
296 // - ENOSYS: the implementation does not support this function.
297 // - EBADF: the file or directory was closed.
298 //
299 // # Notes
300 //
301 // - This is like syscall.UtimesNano and `futimens` in POSIX. See
302 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
303 // - Windows requires files to be open with O_RDWR, which means you
304 // cannot use this to update timestamps on a directory (EPERM).
305 Utimens(atim, mtim int64) Errno
306
307 // Close closes the underlying file.
308 //
309 // A zero Errno is returned if unimplemented or success.
310 //
311 // # Notes
312 //
313 // - This is like syscall.Close and `close` in POSIX. See
314 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
315 Close() Errno
316}