file.go

  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}