1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
use crate::fs::{error::wasi_errno_to_io_error, Metadata}; use crate::{host, hostcalls, wasi, WasiCtx}; use std::io; /// A reference to an open file on the filesystem. /// /// This corresponds to [`std::fs::File`]. /// /// Note that this `File` has no `open` or `create` methods. To open or create /// a file, you must first obtain a [`Dir`] containing the file, and then call /// [`Dir::open_file`] or [`Dir::create_file`]. /// /// [`std::fs::File`]: https://doc.rust-lang.org/std/fs/struct.File.html /// [`Dir`]: struct.Dir.html /// [`Dir::open_file`]: struct.Dir.html#method.open_file /// [`Dir::create_file`]: struct.Dir.html#method.create_file pub struct File<'ctx> { ctx: &'ctx mut WasiCtx, fd: wasi::__wasi_fd_t, } impl<'ctx> File<'ctx> { /// Constructs a new instance of `Self` from the given raw WASI file descriptor. /// /// This corresponds to [`std::fs::File::from_raw_fd`]. /// /// [`std::fs::File::from_raw_fd`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.from_raw_fd pub unsafe fn from_raw_wasi_fd(ctx: &'ctx mut WasiCtx, fd: wasi::__wasi_fd_t) -> Self { Self { ctx, fd } } /// Attempts to sync all OS-internal metadata to disk. /// /// This corresponds to [`std::fs::File::sync_all`]. /// /// [`std::fs::File::sync_all`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.sync_all pub fn sync_all(&self) -> io::Result<()> { wasi_errno_to_io_error(unsafe { hostcalls::fd_sync(self.ctx, &mut [], self.fd) }) } /// This function is similar to `sync_all`, except that it may not synchronize /// file metadata to the filesystem. /// /// This corresponds to [`std::fs::File::sync_data`]. /// /// [`std::fs::File::sync_data`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.sync_data pub fn sync_data(&self) -> io::Result<()> { wasi_errno_to_io_error(unsafe { hostcalls::fd_datasync(self.ctx, &mut [], self.fd) }) } /// Truncates or extends the underlying file, updating the size of this file /// to become size. /// /// This corresponds to [`std::fs::File::set_len`]. /// /// [`std::fs::File::set_len`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.set_len pub fn set_len(&self, size: u64) -> io::Result<()> { wasi_errno_to_io_error(unsafe { hostcalls::fd_filestat_set_size(self.ctx, &mut [], self.fd, size) }) } /// Queries metadata about the underlying file. /// /// This corresponds to [`std::fs::File::metadata`]. /// /// [`std::fs::File::metadata`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.metadata pub fn metadata(&self) -> io::Result<Metadata> { Ok(Metadata {}) } } impl<'ctx> Drop for File<'ctx> { fn drop(&mut self) { // Note that errors are ignored when closing a file descriptor. The // reason for this is that if an error occurs we don't actually know if // the file descriptor was closed or not, and if we retried (for // something like EINTR), we might close another valid file descriptor // opened after we closed ours. let _ = unsafe { hostcalls::fd_close(self.ctx, &mut [], self.fd) }; } } impl<'ctx> io::Read for File<'ctx> { /// TODO: Not yet implemented. See the comment in `Dir::open_file`. fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { let iov = [host::__wasi_iovec_t { buf: buf.as_mut_ptr() as *mut u8, buf_len: buf.len(), }]; let mut nread = 0; // TODO: See the comment in `Dir::open_file`. unimplemented!("File::read"); /* wasi_errno_to_io_error(unsafe { hostcalls::fd_read(self.ctx, self.fd, &iov, 1, &mut nread) })?; */ Ok(nread) } } // TODO: traits to implement: Write, Seek // TODO: functions from FileExt? // TODO: impl Debug for File