3 use crate::io::{self, IoVec, IoVecMut, SeekFrom};
5 use crate::net::Shutdown;
6 use crate::sys::cvt_wasi;
7 use libc::{self, c_char, c_void};
10 fd: libc::__wasi_fd_t,
13 // FIXME: these should probably all be fancier structs, builders, enums, etc
14 pub type LookupFlags = u32;
15 pub type FdFlags = u16;
17 pub type Rights = u64;
18 pub type Oflags = u16;
19 pub type DirCookie = u64;
20 pub type Timestamp = u64;
21 pub type FstFlags = u16;
22 pub type RiFlags = u16;
23 pub type RoFlags = u16;
24 pub type SiFlags = u16;
26 fn iovec(a: &mut [IoVecMut<'_>]) -> (*const libc::__wasi_iovec_t, usize) {
28 mem::size_of::<IoVecMut<'_>>(),
29 mem::size_of::<libc::__wasi_iovec_t>()
32 mem::align_of::<IoVecMut<'_>>(),
33 mem::align_of::<libc::__wasi_iovec_t>()
35 (a.as_ptr() as *const libc::__wasi_iovec_t, a.len())
38 fn ciovec(a: &[IoVec<'_>]) -> (*const libc::__wasi_ciovec_t, usize) {
40 mem::size_of::<IoVec<'_>>(),
41 mem::size_of::<libc::__wasi_ciovec_t>()
44 mem::align_of::<IoVec<'_>>(),
45 mem::align_of::<libc::__wasi_ciovec_t>()
47 (a.as_ptr() as *const libc::__wasi_ciovec_t, a.len())
51 pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd {
55 pub fn datasync(&self) -> io::Result<()> {
56 cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) })
59 pub fn pread(&self, bufs: &mut [IoVecMut<'_>], offset: u64) -> io::Result<usize> {
61 let (ptr, len) = iovec(bufs);
62 cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?;
66 pub fn pwrite(&self, bufs: &[IoVec<'_>], offset: u64) -> io::Result<usize> {
68 let (ptr, len) = ciovec(bufs);
69 cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?;
73 pub fn read(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
75 let (ptr, len) = iovec(bufs);
76 cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?;
80 pub fn write(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
82 let (ptr, len) = ciovec(bufs);
83 cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?;
87 pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
88 let (whence, offset) = match pos {
89 SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64),
90 SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos),
91 SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos),
94 cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?;
98 pub fn tell(&self) -> io::Result<u64> {
100 cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?;
104 // FIXME: __wasi_fd_fdstat_get
106 pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> {
107 cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) })
110 pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> {
111 cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) })
114 pub fn sync(&self) -> io::Result<()> {
115 cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) })
118 pub fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
119 cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) })
122 pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
123 cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) })
126 pub fn crate_directory(&self, path: &[u8]) -> io::Result<()> {
128 libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len())
134 old_flags: LookupFlags,
138 ) -> io::Result<()> {
140 libc::__wasi_path_link(
143 old_path.as_ptr() as *const c_char,
146 new_path.as_ptr() as *const c_char,
154 dirflags: LookupFlags,
157 fs_rights_base: Rights,
158 fs_rights_inheriting: Rights,
160 ) -> io::Result<WasiFd> {
163 cvt_wasi(libc::__wasi_path_open(
166 path.as_ptr() as *const c_char,
170 fs_rights_inheriting,
174 Ok(WasiFd::from_raw(fd))
178 pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result<usize> {
181 libc::__wasi_fd_readdir(
183 buf.as_mut_ptr() as *mut c_void,
192 pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
195 libc::__wasi_path_readlink(
197 path.as_ptr() as *const c_char,
199 buf.as_mut_ptr() as *mut c_char,
207 pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
209 libc::__wasi_path_rename(
211 old_path.as_ptr() as *const c_char,
214 new_path.as_ptr() as *const c_char,
220 // FIXME: __wasi_fd_filestat_get
222 pub fn filestat_set_times(
227 ) -> io::Result<()> {
228 cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_times(self.fd, atim, mtim, fstflags) })
231 pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
232 cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) })
235 // FIXME: __wasi_path_filestat_get
237 pub fn path_filestat_set_times(
244 ) -> io::Result<()> {
246 libc::__wasi_path_filestat_set_times(
249 path.as_ptr() as *const c_char,
258 pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
260 libc::__wasi_path_symlink(
261 old_path.as_ptr() as *const c_char,
264 new_path.as_ptr() as *const c_char,
270 pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
272 libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len())
276 pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
278 libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len())
284 ri_data: &mut [IoVecMut<'_>],
286 ) -> io::Result<(usize, RoFlags)> {
287 let mut ro_datalen = 0;
288 let mut ro_flags = 0;
289 let (ptr, len) = iovec(ri_data);
291 libc::__wasi_sock_recv(self.fd, ptr, len, ri_flags, &mut ro_datalen, &mut ro_flags)
293 Ok((ro_datalen, ro_flags))
296 pub fn sock_send(&self, si_data: &[IoVec<'_>], si_flags: SiFlags) -> io::Result<usize> {
297 let mut so_datalen = 0;
298 let (ptr, len) = ciovec(si_data);
299 cvt_wasi(unsafe { libc::__wasi_sock_send(self.fd, ptr, len, si_flags, &mut so_datalen) })?;
303 pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
304 let how = match how {
305 Shutdown::Read => libc::__WASI_SHUT_RD,
306 Shutdown::Write => libc::__WASI_SHUT_WR,
307 Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD,
309 cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?;
314 impl Drop for WasiFd {
317 // FIXME: can we handle the return code here even though we can't on
319 libc::__wasi_fd_close(self.fd);