1 #![deny(unsafe_op_in_unsafe_fn)]
5 use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
7 use crate::net::Shutdown;
14 fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
15 assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>());
16 assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>());
17 // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
18 unsafe { mem::transmute(a) }
21 fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
22 assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>());
23 assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>());
24 // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
25 unsafe { mem::transmute(a) }
29 pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd {
33 pub fn into_raw(self) -> wasi::Fd {
39 pub fn as_raw(&self) -> wasi::Fd {
43 pub fn datasync(&self) -> io::Result<()> {
44 unsafe { wasi::fd_datasync(self.fd).map_err(err2io) }
47 pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
48 unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) }
51 pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
52 unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) }
55 pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
56 unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) }
59 pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
60 unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) }
63 pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
64 let (whence, offset) = match pos {
65 SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64),
66 SeekFrom::End(pos) => (wasi::WHENCE_END, pos),
67 SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos),
69 unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) }
72 pub fn tell(&self) -> io::Result<u64> {
73 unsafe { wasi::fd_tell(self.fd).map_err(err2io) }
76 // FIXME: __wasi_fd_fdstat_get
78 pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> {
79 unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) }
82 pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> {
83 unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) }
86 pub fn sync(&self) -> io::Result<()> {
87 unsafe { wasi::fd_sync(self.fd).map_err(err2io) }
90 pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
91 unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) }
94 pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
95 unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) }
98 pub fn create_directory(&self, path: &str) -> io::Result<()> {
99 unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) }
104 old_flags: wasi::Lookupflags,
108 ) -> io::Result<()> {
110 wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path).map_err(err2io)
116 dirflags: wasi::Lookupflags,
118 oflags: wasi::Oflags,
119 fs_rights_base: wasi::Rights,
120 fs_rights_inheriting: wasi::Rights,
121 fs_flags: wasi::Fdflags,
122 ) -> io::Result<WasiFd> {
130 fs_rights_inheriting,
133 .map(|fd| WasiFd::from_raw(fd))
138 pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result<usize> {
139 unsafe { wasi::fd_readdir(self.fd, buf.as_mut_ptr(), buf.len(), cookie).map_err(err2io) }
142 pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result<usize> {
143 unsafe { wasi::path_readlink(self.fd, path, buf.as_mut_ptr(), buf.len()).map_err(err2io) }
146 pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> {
147 unsafe { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) }
150 pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
151 unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) }
154 pub fn filestat_set_times(
156 atim: wasi::Timestamp,
157 mtim: wasi::Timestamp,
158 fstflags: wasi::Fstflags,
159 ) -> io::Result<()> {
160 unsafe { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) }
163 pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
164 unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) }
167 pub fn path_filestat_get(
169 flags: wasi::Lookupflags,
171 ) -> io::Result<wasi::Filestat> {
172 unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) }
175 pub fn path_filestat_set_times(
177 flags: wasi::Lookupflags,
179 atim: wasi::Timestamp,
180 mtim: wasi::Timestamp,
181 fstflags: wasi::Fstflags,
182 ) -> io::Result<()> {
184 wasi::path_filestat_set_times(self.fd, flags, path, atim, mtim, fstflags)
189 pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> {
190 unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) }
193 pub fn unlink_file(&self, path: &str) -> io::Result<()> {
194 unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) }
197 pub fn remove_directory(&self, path: &str) -> io::Result<()> {
198 unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) }
203 ri_data: &mut [IoSliceMut<'_>],
204 ri_flags: wasi::Riflags,
205 ) -> io::Result<(usize, wasi::Roflags)> {
206 unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) }
209 pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result<usize> {
210 unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) }
213 pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
214 let how = match how {
215 Shutdown::Read => wasi::SDFLAGS_RD,
216 Shutdown::Write => wasi::SDFLAGS_WR,
217 Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD,
219 unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) }
223 impl Drop for WasiFd {
225 // FIXME: can we handle the return code here even though we can't on
227 let _ = unsafe { wasi::fd_close(self.fd) };