diff --git a/src/ctx.rs b/src/ctx.rs index 993f6dd924..35dd1eda78 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -1,6 +1,6 @@ use crate::fdentry::FdEntry; -use crate::sys::{dev_null, errno_from_ioerror}; -use crate::{host, Result}; +use crate::sys::dev_null; +use crate::{host, Error, Result}; use std::borrow::Borrow; use std::collections::HashMap; use std::ffi::CString; @@ -33,7 +33,7 @@ impl WasiCtxBuilder { pub fn args>(mut self, args: impl Iterator) -> Result { let args: Result> = args - .map(|arg| CString::new(arg.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE)) + .map(|arg| CString::new(arg.as_ref()).map_err(|_| Error::ENOTCAPABLE)) .collect(); self.args = args?; Ok(self) @@ -41,7 +41,7 @@ impl WasiCtxBuilder { pub fn arg(mut self, arg: &str) -> Result { self.args - .push(CString::new(arg).map_err(|_| host::__WASI_ENOTCAPABLE)?); + .push(CString::new(arg).map_err(|_| Error::ENOTCAPABLE)?); Ok(self) } @@ -58,8 +58,8 @@ impl WasiCtxBuilder { pub fn env>(mut self, k: S, v: S) -> Result { self.env.insert( - CString::new(k.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE)?, - CString::new(v.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE)?, + CString::new(k.as_ref()).map_err(|_| Error::ENOTCAPABLE)?, + CString::new(v.as_ref()).map_err(|_| Error::ENOTCAPABLE)?, ); Ok(self) } @@ -71,11 +71,11 @@ impl WasiCtxBuilder { let env: Result> = envs .map(|t| { let (k, v) = t.borrow(); - let k = CString::new(k.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE); - let v = CString::new(v.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE); + let k = CString::new(k.as_ref()).map_err(|_| Error::ENOTCAPABLE); + let v = CString::new(v.as_ref()).map_err(|_| Error::ENOTCAPABLE); match (k, v) { (Ok(k), Ok(v)) => Ok((k, v)), - _ => Err(host::__WASI_ENOTCAPABLE), + _ => Err(Error::ENOTCAPABLE), } }) .collect(); @@ -92,12 +92,12 @@ impl WasiCtxBuilder { // startup code starts looking at fd 3 for preopens let mut preopen_fd = 3; for (guest_path, dir) in self.preopens { - if !dir.metadata().map_err(errno_from_ioerror)?.is_dir() { - return Err(host::__WASI_EBADF); + if !dir.metadata()?.is_dir() { + return Err(Error::EBADF); } while self.fds.contains_key(&preopen_fd) { - preopen_fd = preopen_fd.checked_add(1).ok_or(host::__WASI_ENFILE)?; + preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?; } let mut fe = FdEntry::from(dir)?; fe.preopen_path = Some(guest_path); @@ -161,7 +161,7 @@ impl WasiCtx { if let Some(fe) = self.fds.get(&fd) { Self::validate_rights(fe, rights_base, rights_inheriting).and(Ok(fe)) } else { - Err(host::__WASI_EBADF) + Err(Error::EBADF) } } @@ -174,7 +174,7 @@ impl WasiCtx { if let Some(fe) = self.fds.get_mut(&fd) { Self::validate_rights(fe, rights_base, rights_inheriting).and(Ok(fe)) } else { - Err(host::__WASI_EBADF) + Err(Error::EBADF) } } @@ -184,7 +184,7 @@ impl WasiCtx { rights_inheriting: host::__wasi_rights_t, ) -> Result<()> { if !fe.rights_base & rights_base != 0 || !fe.rights_inheriting & rights_inheriting != 0 { - Err(host::__WASI_ENOTCAPABLE) + Err(Error::ENOTCAPABLE) } else { Ok(()) } @@ -197,7 +197,7 @@ impl WasiCtx { if let Some(next_fd) = fd.checked_add(1) { fd = next_fd; } else { - return Err(host::__WASI_EMFILE); + return Err(Error::EMFILE); } } self.fds.insert(fd, fe); diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000000..5fc82db323 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,223 @@ +use crate::host; +use crate::sys::errno_from_ioerror; +use std::num::TryFromIntError; + +#[derive(Clone, Copy, Debug)] +pub enum WasiError { + ESUCCESS = 0, + E2BIG = 1, + EACCES = 2, + EADDRINUSE = 3, + EADDRNOTAVAIL = 4, + EAFNOSUPPORT = 5, + EAGAIN = 6, + EALREADY = 7, + EBADF = 8, + EBADMSG = 9, + EBUSY = 10, + ECANCELED = 11, + ECHILD = 12, + ECONNABORTED = 13, + ECONNREFUSED = 14, + ECONNRESET = 15, + EDEADLK = 16, + EDESTADDRREQ = 17, + EDOM = 18, + EDQUOT = 19, + EEXIST = 20, + EFAULT = 21, + EFBIG = 22, + EHOSTUNREACH = 23, + EIDRM = 24, + EILSEQ = 25, + EINPROGRESS = 26, + EINTR = 27, + EINVAL = 28, + EIO = 29, + EISCONN = 30, + EISDIR = 31, + ELOOP = 32, + EMFILE = 33, + EMLINK = 34, + EMSGSIZE = 35, + EMULTIHOP = 36, + ENAMETOOLONG = 37, + ENETDOWN = 38, + ENETRESET = 39, + ENETUNREACH = 40, + ENFILE = 41, + ENOBUFS = 42, + ENODEV = 43, + ENOENT = 44, + ENOEXEC = 45, + ENOLCK = 46, + ENOLINK = 47, + ENOMEM = 48, + ENOMSG = 49, + ENOPROTOOPT = 50, + ENOSPC = 51, + ENOSYS = 52, + ENOTCONN = 53, + ENOTDIR = 54, + ENOTEMPTY = 55, + ENOTRECOVERABLE = 56, + ENOTSOCK = 57, + ENOTSUP = 58, + ENOTTY = 59, + ENXIO = 60, + EOVERFLOW = 61, + EOWNERDEAD = 62, + EPERM = 63, + EPIPE = 64, + EPROTO = 65, + EPROTONOSUPPORT = 66, + EPROTOTYPE = 67, + ERANGE = 68, + EROFS = 69, + ESPIPE = 70, + ESRCH = 71, + ESTALE = 72, + ETIMEDOUT = 73, + ETXTBSY = 74, + EXDEV = 75, + ENOTCAPABLE = 76, +} + +impl WasiError { + pub fn as_raw_errno(&self) -> host::__wasi_errno_t { + *self as host::__wasi_errno_t + } +} + +pub enum Error { + Wasi(WasiError), + Io(std::io::Error), + #[cfg(unix)] + Nix(nix::Error), + #[cfg(windows)] + Win(winx::winerror::WinError), +} + +impl From for Error { + fn from(err: WasiError) -> Self { + Self::Wasi(err) + } +} + +#[cfg(unix)] +impl From for Error { + fn from(err: nix::Error) -> Self { + Self::Nix(err) + } +} + +impl From for Error { + fn from(err: std::io::Error) -> Self { + Self::Io(err) + } +} + +impl From for Error { + fn from(_: TryFromIntError) -> Self { + Self::Wasi(WasiError::EOVERFLOW) + } +} + +#[cfg(windows)] +impl From for Error { + fn from(err: winx::winerror::WinError) -> Self { + Self::Win(err) + } +} + +impl Error { + pub(crate) fn as_wasi_errno(&self) -> host::__wasi_errno_t { + match self { + Self::Wasi(no) => no.as_raw_errno(), + #[cfg(unix)] + Self::Nix(err) => { + crate::sys::host_impl::errno_from_nix(err.as_errno().unwrap()).as_wasi_errno() + } // FIXME unwrap + Self::Io(e) => errno_from_ioerror(e.to_owned()), // fixme clone + #[cfg(windows)] + Self::Win(err) => crate::sys::host_impl::errno_from_win(*err), + } + } + pub const ESUCCESS: Self = Error::Wasi(WasiError::ESUCCESS); + pub const E2BIG: Self = Error::Wasi(WasiError::E2BIG); + pub const EACCES: Self = Error::Wasi(WasiError::EACCES); + pub const EADDRINUSE: Self = Error::Wasi(WasiError::EADDRINUSE); + pub const EADDRNOTAVAIL: Self = Error::Wasi(WasiError::EADDRNOTAVAIL); + pub const EAFNOSUPPORT: Self = Error::Wasi(WasiError::EAFNOSUPPORT); + pub const EAGAIN: Self = Error::Wasi(WasiError::EAGAIN); + pub const EALREADY: Self = Error::Wasi(WasiError::EALREADY); + pub const EBADF: Self = Error::Wasi(WasiError::EBADF); + pub const EBADMSG: Self = Error::Wasi(WasiError::EBADMSG); + pub const EBUSY: Self = Error::Wasi(WasiError::EBUSY); + pub const ECANCELED: Self = Error::Wasi(WasiError::ECANCELED); + pub const ECHILD: Self = Error::Wasi(WasiError::ECHILD); + pub const ECONNABORTED: Self = Error::Wasi(WasiError::ECONNABORTED); + pub const ECONNREFUSED: Self = Error::Wasi(WasiError::ECONNREFUSED); + pub const ECONNRESET: Self = Error::Wasi(WasiError::ECONNRESET); + pub const EDEADLK: Self = Error::Wasi(WasiError::EDEADLK); + pub const EDESTADDRREQ: Self = Error::Wasi(WasiError::EDESTADDRREQ); + pub const EDOM: Self = Error::Wasi(WasiError::EDOM); + pub const EDQUOT: Self = Error::Wasi(WasiError::EDQUOT); + pub const EEXIST: Self = Error::Wasi(WasiError::EEXIST); + pub const EFAULT: Self = Error::Wasi(WasiError::EFAULT); + pub const EFBIG: Self = Error::Wasi(WasiError::EFBIG); + pub const EHOSTUNREACH: Self = Error::Wasi(WasiError::EHOSTUNREACH); + pub const EIDRM: Self = Error::Wasi(WasiError::EIDRM); + pub const EILSEQ: Self = Error::Wasi(WasiError::EILSEQ); + pub const EINPROGRESS: Self = Error::Wasi(WasiError::EINPROGRESS); + pub const EINTR: Self = Error::Wasi(WasiError::EINTR); + pub const EINVAL: Self = Error::Wasi(WasiError::EINVAL); + pub const EIO: Self = Error::Wasi(WasiError::EIO); + pub const EISCONN: Self = Error::Wasi(WasiError::EISCONN); + pub const EISDIR: Self = Error::Wasi(WasiError::EISDIR); + pub const ELOOP: Self = Error::Wasi(WasiError::ELOOP); + pub const EMFILE: Self = Error::Wasi(WasiError::EMFILE); + pub const EMLINK: Self = Error::Wasi(WasiError::EMLINK); + pub const EMSGSIZE: Self = Error::Wasi(WasiError::EMSGSIZE); + pub const EMULTIHOP: Self = Error::Wasi(WasiError::EMULTIHOP); + pub const ENAMETOOLONG: Self = Error::Wasi(WasiError::ENAMETOOLONG); + pub const ENETDOWN: Self = Error::Wasi(WasiError::ENETDOWN); + pub const ENETRESET: Self = Error::Wasi(WasiError::ENETRESET); + pub const ENETUNREACH: Self = Error::Wasi(WasiError::ENETUNREACH); + pub const ENFILE: Self = Error::Wasi(WasiError::ENFILE); + pub const ENOBUFS: Self = Error::Wasi(WasiError::ENOBUFS); + pub const ENODEV: Self = Error::Wasi(WasiError::ENODEV); + pub const ENOENT: Self = Error::Wasi(WasiError::ENOENT); + pub const ENOEXEC: Self = Error::Wasi(WasiError::ENOEXEC); + pub const ENOLCK: Self = Error::Wasi(WasiError::ENOLCK); + pub const ENOLINK: Self = Error::Wasi(WasiError::ENOLINK); + pub const ENOMEM: Self = Error::Wasi(WasiError::ENOMEM); + pub const ENOMSG: Self = Error::Wasi(WasiError::ENOMSG); + pub const ENOPROTOOPT: Self = Error::Wasi(WasiError::ENOPROTOOPT); + pub const ENOSPC: Self = Error::Wasi(WasiError::ENOSPC); + pub const ENOSYS: Self = Error::Wasi(WasiError::ENOSYS); + pub const ENOTCONN: Self = Error::Wasi(WasiError::ENOTCONN); + pub const ENOTDIR: Self = Error::Wasi(WasiError::ENOTDIR); + pub const ENOTEMPTY: Self = Error::Wasi(WasiError::ENOTEMPTY); + pub const ENOTRECOVERABLE: Self = Error::Wasi(WasiError::ENOTRECOVERABLE); + pub const ENOTSOCK: Self = Error::Wasi(WasiError::ENOTSOCK); + pub const ENOTSUP: Self = Error::Wasi(WasiError::ENOTSUP); + pub const ENOTTY: Self = Error::Wasi(WasiError::ENOTTY); + pub const ENXIO: Self = Error::Wasi(WasiError::ENXIO); + pub const EOVERFLOW: Self = Error::Wasi(WasiError::EOVERFLOW); + pub const EOWNERDEAD: Self = Error::Wasi(WasiError::EOWNERDEAD); + pub const EPERM: Self = Error::Wasi(WasiError::EPERM); + pub const EPIPE: Self = Error::Wasi(WasiError::EPIPE); + pub const EPROTO: Self = Error::Wasi(WasiError::EPROTO); + pub const EPROTONOSUPPORT: Self = Error::Wasi(WasiError::EPROTONOSUPPORT); + pub const EPROTOTYPE: Self = Error::Wasi(WasiError::EPROTOTYPE); + pub const ERANGE: Self = Error::Wasi(WasiError::ERANGE); + pub const EROFS: Self = Error::Wasi(WasiError::EROFS); + pub const ESPIPE: Self = Error::Wasi(WasiError::ESPIPE); + pub const ESRCH: Self = Error::Wasi(WasiError::ESRCH); + pub const ESTALE: Self = Error::Wasi(WasiError::ESTALE); + pub const ETIMEDOUT: Self = Error::Wasi(WasiError::ETIMEDOUT); + pub const ETXTBSY: Self = Error::Wasi(WasiError::ETXTBSY); + pub const EXDEV: Self = Error::Wasi(WasiError::EXDEV); + pub const ENOTCAPABLE: Self = Error::Wasi(WasiError::ENOTCAPABLE); +} diff --git a/src/fdentry.rs b/src/fdentry.rs index 6ca142c236..2d7354778d 100644 --- a/src/fdentry.rs +++ b/src/fdentry.rs @@ -1,5 +1,5 @@ -use crate::sys::{errno_from_ioerror, fdentry_impl}; -use crate::{host, Result}; +use crate::sys::fdentry_impl; +use crate::{host, Error, Result}; use std::mem::ManuallyDrop; use std::path::PathBuf; @@ -17,7 +17,7 @@ impl Descriptor { pub fn as_file(&self) -> Result<&fs::File> { match self { Descriptor::File(f) => Ok(f), - _ => Err(host::__WASI_EBADF), + _ => Err(Error::EBADF), } } @@ -91,9 +91,7 @@ impl FdEntry { } pub fn duplicate(file: &fs::File) -> Result { - file.try_clone() - .map_err(errno_from_ioerror) - .and_then(Self::from) + Self::from(file.try_clone()?) } pub fn duplicate_stdin() -> Result { diff --git a/src/helpers.rs b/src/helpers.rs index 08755b5c15..3e8d7f8e46 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,10 +1,10 @@ -use crate::{host, Result}; +use crate::{Error, Result}; use std::convert::TryInto; use std::time::{SystemTime, UNIX_EPOCH}; pub(crate) fn systemtime_to_timestamp(st: SystemTime) -> Result { st.duration_since(UNIX_EPOCH) - .map_err(|_| host::__WASI_EINVAL)? // date earlier than UNIX_EPOCH + .map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH .as_nanos() .try_into() - .map_err(|_| host::__WASI_EOVERFLOW) // u128 doesn't fit into u64 + .map_err(|_| Error::EOVERFLOW) // u128 doesn't fit into u64 } diff --git a/src/host.rs b/src/host.rs index a45d98555c..ce5a1560e9 100644 --- a/src/host.rs +++ b/src/host.rs @@ -3,7 +3,7 @@ //! still largely reflects that. #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use crate::Result; +use crate::{Error, Result}; use std::{io, slice, str}; pub type void = ::std::os::raw::c_void; @@ -500,7 +500,7 @@ pub unsafe fn iovec_to_host_mut<'a>(iovec: &'a mut __wasi_iovec_t) -> io::IoSlic /// NB WASI spec requires bytes to be valid UTF-8. Otherwise, /// `__WASI_EILSEQ` error is returned. pub fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> { - str::from_utf8(s).map_err(|_| __WASI_EILSEQ) + str::from_utf8(s).map_err(|_| Error::EILSEQ) } /// Creates owned WASI path from byte vector. @@ -508,7 +508,7 @@ pub fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> { /// NB WASI spec requires bytes to be valid UTF-8. Otherwise, /// `__WASI_EILSEQ` error is returned. pub fn path_from_vec>>(s: S) -> Result { - String::from_utf8(s.into()).map_err(|_| __WASI_EILSEQ) + String::from_utf8(s.into()).map_err(|_| Error::EILSEQ) } #[cfg(test)] diff --git a/src/hostcalls_impl/fs.rs b/src/hostcalls_impl/fs.rs index fb69ffb3f7..f18fe4bbee 100644 --- a/src/hostcalls_impl/fs.rs +++ b/src/hostcalls_impl/fs.rs @@ -5,8 +5,8 @@ use crate::fdentry::{Descriptor, FdEntry}; use crate::memory::*; use crate::sys::fdentry_impl::determine_type_rights; use crate::sys::hostcalls_impl::fs_helpers::path_open_rights; -use crate::sys::{errno_from_ioerror, host_impl, hostcalls_impl}; -use crate::{host, wasm32, Result}; +use crate::sys::{host_impl, hostcalls_impl}; +use crate::{host, wasm32, Error, Result}; use filetime::{set_file_handle_times, FileTime}; use log::trace; use std::fs::File; @@ -20,11 +20,11 @@ pub(crate) fn fd_close(wasi_ctx: &mut WasiCtx, fd: wasm32::__wasi_fd_t) -> Resul if let Some(fdent) = wasi_ctx.fds.get(&fd) { // can't close preopened files if fdent.preopen_path.is_some() { - return Err(host::__WASI_ENOTSUP); + return Err(Error::ENOTSUP); } } - let mut fe = wasi_ctx.fds.remove(&fd).ok_or(host::__WASI_EBADF)?; + let mut fe = wasi_ctx.fds.remove(&fd).ok_or(Error::EBADF)?; fe.fd_object.needs_close = true; Ok(()) @@ -38,7 +38,7 @@ pub(crate) fn fd_datasync(wasi_ctx: &WasiCtx, fd: wasm32::__wasi_fd_t) -> Result .get_fd_entry(fd, host::__WASI_RIGHT_FD_DATASYNC, 0) .and_then(|fe| fe.fd_object.descriptor.as_file())?; - fd.sync_data().map_err(errno_from_ioerror) + fd.sync_data().map_err(Into::into) } pub(crate) fn fd_pread( @@ -68,7 +68,7 @@ pub(crate) fn fd_pread( let offset = dec_filesize(offset); if offset > i64::max_value() as u64 { - return Err(host::__WASI_EIO); + return Err(Error::EIO); } let buf_size = iovs.iter().map(|v| v.buf_len).sum(); let mut buf = vec![0; buf_size]; @@ -117,7 +117,7 @@ pub(crate) fn fd_pwrite( let offset = dec_filesize(offset); if offset > i64::max_value() as u64 { - return Err(host::__WASI_EIO); + return Err(Error::EIO); } let buf_size = iovs.iter().map(|v| v.buf_len).sum(); let mut buf = Vec::with_capacity(buf_size); @@ -160,10 +160,10 @@ pub(crate) fn fd_read( let maybe_host_nread = match &mut *fe.fd_object.descriptor { Descriptor::File(f) => f.read_vectored(&mut iovs), Descriptor::Stdin => io::stdin().lock().read_vectored(&mut iovs), - _ => return Err(host::__WASI_EBADF), + _ => return Err(Error::EBADF), }; - let host_nread = maybe_host_nread.map_err(errno_from_ioerror)?; + let host_nread = maybe_host_nread?; trace!(" | *nread={:?}", host_nread); @@ -181,14 +181,14 @@ pub(crate) fn fd_renumber( let to = dec_fd(to); if !wasi_ctx.contains_fd_entry(from) || !wasi_ctx.contains_fd_entry(to) { - return Err(host::__WASI_EBADF); + return Err(Error::EBADF); } // Don't allow renumbering over a pre-opened resource. // TODO: Eventually, we do want to permit this, once libpreopen in // userspace is capable of removing entries from its tables as well. if wasi_ctx.fds[&from].preopen_path.is_some() || wasi_ctx.fds[&to].preopen_path.is_some() { - return Err(host::__WASI_ENOTSUP); + return Err(Error::ENOTSUP); } // check if stdio fds @@ -196,7 +196,7 @@ pub(crate) fn fd_renumber( if !wasi_ctx.fds[&from].fd_object.descriptor.is_file() || !wasi_ctx.fds[&to].fd_object.descriptor.is_file() { - return Err(host::__WASI_EBADF); + return Err(Error::EBADF); } let fe_from_dup = wasi_ctx.fds[&from] @@ -244,9 +244,9 @@ pub(crate) fn fd_seek( host::__WASI_WHENCE_CUR => SeekFrom::Current(offset), host::__WASI_WHENCE_END => SeekFrom::End(offset), host::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64), - _ => return Err(host::__WASI_EINVAL), + _ => return Err(Error::EINVAL), }; - let host_newoffset = fd.seek(pos).map_err(errno_from_ioerror)?; + let host_newoffset = fd.seek(pos)?; trace!(" | *newoffset={:?}", host_newoffset); @@ -266,7 +266,7 @@ pub(crate) fn fd_tell( .get_fd_entry(fd, host::__WASI_RIGHT_FD_TELL, 0) .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let host_offset = fd.seek(SeekFrom::Current(0)).map_err(errno_from_ioerror)?; + let host_offset = fd.seek(SeekFrom::Current(0))?; trace!(" | *newoffset={:?}", host_offset); @@ -328,12 +328,12 @@ pub(crate) fn fd_fdstat_set_rights( ); let fd = dec_fd(fd); - let fe = wasi_ctx.fds.get_mut(&fd).ok_or(host::__WASI_EBADF)?; + let fe = wasi_ctx.fds.get_mut(&fd).ok_or(Error::EBADF)?; if fe.rights_base & fs_rights_base != fs_rights_base || fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting { - return Err(host::__WASI_ENOTCAPABLE); + return Err(Error::ENOTCAPABLE); } fe.rights_base = fs_rights_base; fe.rights_inheriting = fs_rights_inheriting; @@ -348,7 +348,7 @@ pub(crate) fn fd_sync(wasi_ctx: &WasiCtx, fd: wasm32::__wasi_fd_t) -> Result<()> let fd = wasi_ctx .get_fd_entry(fd, host::__WASI_RIGHT_FD_SYNC, 0) .and_then(|fe| fe.fd_object.descriptor.as_file())?; - fd.sync_all().map_err(errno_from_ioerror) + fd.sync_all().map_err(Into::into) } pub(crate) fn fd_write( @@ -377,20 +377,17 @@ pub(crate) fn fd_write( // perform unbuffered writes let host_nwritten = match &mut *fe.fd_object.descriptor { - Descriptor::File(f) => f.write_vectored(&iovs).map_err(errno_from_ioerror)?, - Descriptor::Stdin => return Err(host::__WASI_EBADF), + Descriptor::File(f) => f.write_vectored(&iovs)?, + Descriptor::Stdin => return Err(Error::EBADF), Descriptor::Stdout => { // lock for the duration of the scope let stdout = io::stdout(); let mut stdout = stdout.lock(); - let nwritten = stdout.write_vectored(&iovs).map_err(errno_from_ioerror)?; - stdout.flush().map_err(errno_from_ioerror)?; + let nwritten = stdout.write_vectored(&iovs)?; + stdout.flush()?; nwritten } - Descriptor::Stderr => io::stderr() - .lock() - .write_vectored(&iovs) - .map_err(errno_from_ioerror)?, + Descriptor::Stderr => io::stderr().lock().write_vectored(&iovs)?, }; trace!(" | *nwritten={:?}", host_nwritten); @@ -439,17 +436,17 @@ pub(crate) fn fd_allocate( .get_fd_entry(fd, host::__WASI_RIGHT_FD_ALLOCATE, 0) .and_then(|fe| fe.fd_object.descriptor.as_file())?; - let metadata = fd.metadata().map_err(errno_from_ioerror)?; + let metadata = fd.metadata()?; let current_size = metadata.len(); - let wanted_size = offset.checked_add(len).ok_or(host::__WASI_E2BIG)?; + let wanted_size = offset.checked_add(len).ok_or(Error::E2BIG)?; // This check will be unnecessary when rust-lang/rust#63326 is fixed if wanted_size > i64::max_value() as u64 { - return Err(host::__WASI_E2BIG); + return Err(Error::E2BIG); } if wanted_size > current_size { - fd.set_len(wanted_size).map_err(errno_from_ioerror) + fd.set_len(wanted_size).map_err(Into::into) } else { Ok(()) } @@ -782,7 +779,7 @@ pub(crate) fn fd_filestat_set_times_impl( let set_mtim_now = fst_flags & host::__WASI_FILESTAT_SET_MTIM_NOW != 0; if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } let atim = if set_atim { let time = UNIX_EPOCH + Duration::from_nanos(st_atim); @@ -803,7 +800,7 @@ pub(crate) fn fd_filestat_set_times_impl( } else { None }; - set_file_handle_times(fd, atim, mtim).map_err(errno_from_ioerror) + set_file_handle_times(fd, atim, mtim).map_err(Into::into) } pub(crate) fn fd_filestat_set_size( @@ -821,9 +818,9 @@ pub(crate) fn fd_filestat_set_size( let st_size = dec_filesize(st_size); // This check will be unnecessary when rust-lang/rust#63326 is fixed if st_size > i64::max_value() as u64 { - return Err(host::__WASI_E2BIG); + return Err(Error::E2BIG); } - fd.set_len(st_size).map_err(errno_from_ioerror) + fd.set_len(st_size).map_err(Into::into) } pub(crate) fn path_filestat_get( @@ -1006,9 +1003,9 @@ pub(crate) fn fd_prestat_get( wasi_ctx .get_fd_entry(fd, host::__WASI_RIGHT_PATH_OPEN, 0) .and_then(|fe| { - let po_path = fe.preopen_path.as_ref().ok_or(host::__WASI_ENOTSUP)?; + let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?; if fe.fd_object.file_type != host::__WASI_FILETYPE_DIRECTORY { - return Err(host::__WASI_ENOTDIR); + return Err(Error::ENOTDIR); } let path = host_impl::path_from_host(po_path.as_os_str())?; @@ -1047,15 +1044,15 @@ pub(crate) fn fd_prestat_dir_name( wasi_ctx .get_fd_entry(fd, host::__WASI_RIGHT_PATH_OPEN, 0) .and_then(|fe| { - let po_path = fe.preopen_path.as_ref().ok_or(host::__WASI_ENOTSUP)?; + let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?; if fe.fd_object.file_type != host::__WASI_FILETYPE_DIRECTORY { - return Err(host::__WASI_ENOTDIR); + return Err(Error::ENOTDIR); } let path = host_impl::path_from_host(po_path.as_os_str())?; if path.len() > dec_usize(path_len) { - return Err(host::__WASI_ENAMETOOLONG); + return Err(Error::ENAMETOOLONG); } trace!(" | (path_ptr,path_len)='{}'", path); diff --git a/src/hostcalls_impl/fs_helpers.rs b/src/hostcalls_impl/fs_helpers.rs index ec433aea50..138ac13a4a 100644 --- a/src/hostcalls_impl/fs_helpers.rs +++ b/src/hostcalls_impl/fs_helpers.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] +use crate::sys::host_impl; use crate::sys::hostcalls_impl::fs_helpers::*; -use crate::sys::{errno_from_host, host_impl}; -use crate::{host, Result}; +use crate::{host, Error, Result}; use std::fs::File; use std::path::{Component, Path}; @@ -33,13 +33,10 @@ pub(crate) fn path_get( if path.contains('\0') { // if contains NUL, return EILSEQ - return Err(host::__WASI_EILSEQ); + return Err(Error::EILSEQ); } - let dirfd = dirfd.try_clone().map_err(|err| { - err.raw_os_error() - .map_or(host::__WASI_EBADF, errno_from_host) - })?; + let dirfd = dirfd.try_clone()?; // Stack of directory file descriptors. Index 0 always corresponds with the directory provided // to this function. Entering a directory causes a file descriptor to be pushed, while handling @@ -64,7 +61,7 @@ pub(crate) fn path_get( let ends_with_slash = cur_path.ends_with('/'); let mut components = Path::new(&cur_path).components(); let head = match components.next() { - None => return Err(host::__WASI_ENOENT), + None => return Err(Error::ENOENT), Some(p) => p, }; let tail = components.as_path(); @@ -80,18 +77,18 @@ pub(crate) fn path_get( match head { Component::Prefix(_) | Component::RootDir => { // path is absolute! - return Err(host::__WASI_ENOTCAPABLE); + return Err(Error::ENOTCAPABLE); } Component::CurDir => { // "." so skip } Component::ParentDir => { // ".." so pop a dir - let _ = dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?; + let _ = dir_stack.pop().ok_or(Error::ENOTCAPABLE)?; // we're not allowed to pop past the original directory if dir_stack.is_empty() { - return Err(host::__WASI_ENOTCAPABLE); + return Err(Error::ENOTCAPABLE); } } Component::Normal(head) => { @@ -102,41 +99,44 @@ pub(crate) fn path_get( } if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) { - match openat(dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?, &head) { + match openat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) { Ok(new_dir) => { dir_stack.push(new_dir); } - Err(e) - if e == host::__WASI_ELOOP - || e == host::__WASI_EMLINK - || e == host::__WASI_ENOTDIR => - // Check to see if it was a symlink. Linux indicates - // this with ENOTDIR because of the O_DIRECTORY flag. - { - // attempt symlink expansion - let mut link_path = readlinkat( - dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?, - &head, - )?; - - symlink_expansions += 1; - if symlink_expansions > MAX_SYMLINK_EXPANSIONS { - return Err(host::__WASI_ELOOP); - } - - if head.ends_with('/') { - link_path.push('/'); - } - - log::debug!( - "attempted symlink expansion link_path={:?}", - link_path - ); - - path_stack.push(link_path); - } Err(e) => { - return Err(e); + match e.as_wasi_errno() { + host::__WASI_ELOOP + | host::__WASI_EMLINK + | host::__WASI_ENOTDIR => + // Check to see if it was a symlink. Linux indicates + // this with ENOTDIR because of the O_DIRECTORY flag. + { + // attempt symlink expansion + let mut link_path = readlinkat( + dir_stack.last().ok_or(Error::ENOTCAPABLE)?, + &head, + )?; + + symlink_expansions += 1; + if symlink_expansions > MAX_SYMLINK_EXPANSIONS { + return Err(Error::ELOOP); + } + + if head.ends_with('/') { + link_path.push('/'); + } + + log::debug!( + "attempted symlink expansion link_path={:?}", + link_path + ); + + path_stack.push(link_path); + } + _ => { + return Err(e); + } + } } } @@ -146,14 +146,11 @@ pub(crate) fn path_get( { // if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt // symlink expansion - match readlinkat( - dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?, - &head, - ) { + match readlinkat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) { Ok(mut link_path) => { symlink_expansions += 1; if symlink_expansions > MAX_SYMLINK_EXPANSIONS { - return Err(host::__WASI_ELOOP); + return Err(Error::ELOOP); } if head.ends_with('/') { @@ -169,7 +166,9 @@ pub(crate) fn path_get( continue; } Err(e) => { - if e != host::__WASI_EINVAL && e != host::__WASI_ENOENT { + if e.as_wasi_errno() != host::__WASI_EINVAL + && e.as_wasi_errno() != host::__WASI_ENOENT + { return Err(e); } } @@ -178,7 +177,7 @@ pub(crate) fn path_get( // not a symlink, so we're done; return Ok(PathGet { - dirfd: dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?, + dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?, path: head, }); } @@ -188,7 +187,7 @@ pub(crate) fn path_get( // no further components to process. means we've hit a case like "." or "a/..", or if the // input path has trailing slashes and `needs_final_component` is not set return Ok(PathGet { - dirfd: dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?, + dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?, path: String::from("."), }); } diff --git a/src/hostcalls_impl/misc.rs b/src/hostcalls_impl/misc.rs index 3e4cbfe44b..7a08ac175e 100644 --- a/src/hostcalls_impl/misc.rs +++ b/src/hostcalls_impl/misc.rs @@ -2,7 +2,7 @@ use crate::ctx::WasiCtx; use crate::memory::*; use crate::sys::hostcalls_impl; -use crate::{host, wasm32, Result}; +use crate::{wasm32, Error, Result}; use log::trace; use std::convert::TryFrom; @@ -29,11 +29,8 @@ pub(crate) fn args_get( argv.push(arg_ptr); - let len = - wasm32::uintptr_t::try_from(arg_bytes.len()).map_err(|_| host::__WASI_EOVERFLOW)?; - argv_buf_offset = argv_buf_offset - .checked_add(len) - .ok_or(host::__WASI_EOVERFLOW)?; + let len = wasm32::uintptr_t::try_from(arg_bytes.len()).map_err(|_| Error::EOVERFLOW)?; + argv_buf_offset = argv_buf_offset.checked_add(len).ok_or(Error::EOVERFLOW)?; } enc_slice_of(memory, argv.as_slice(), argv_ptr) @@ -90,11 +87,10 @@ pub(crate) fn environ_get( environ.push(env_ptr); - let len = - wasm32::uintptr_t::try_from(env_bytes.len()).map_err(|_| host::__WASI_EOVERFLOW)?; + let len = wasm32::uintptr_t::try_from(env_bytes.len()).map_err(|_| Error::EOVERFLOW)?; environ_buf_offset = environ_buf_offset .checked_add(len) - .ok_or(host::__WASI_EOVERFLOW)?; + .ok_or(Error::EOVERFLOW)?; } enc_slice_of(memory, environ.as_slice(), environ_ptr) @@ -119,7 +115,7 @@ pub(crate) fn environ_sizes_get( .try_fold(0, |acc: u32, pair| { acc.checked_add(pair.as_bytes_with_nul().len() as u32) }) - .ok_or(host::__WASI_EOVERFLOW)?; + .ok_or(Error::EOVERFLOW)?; trace!(" | *environ_count_ptr={:?}", environ_count); @@ -202,7 +198,7 @@ pub(crate) fn poll_oneoff( ); if nsubscriptions as u64 > wasm32::__wasi_filesize_t::max_value() { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } enc_pointee(memory, nevents, 0)?; diff --git a/src/lib.rs b/src/lib.rs index 23f3760465..3e773ba189 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,7 @@ )] mod ctx; +mod error; mod fdentry; mod helpers; mod hostcalls_impl; @@ -36,4 +37,5 @@ pub mod wasm32; pub use ctx::{WasiCtx, WasiCtxBuilder}; pub use sys::preopen_dir; -pub(crate) type Result = std::result::Result; +pub type Error = error::Error; +pub(crate) type Result = std::result::Result; diff --git a/src/macros.rs b/src/macros.rs index 43a361f5ae..04a3f231d5 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -4,7 +4,7 @@ macro_rules! hostcalls { pub fn $name($($arg: $ty,)*) -> $ret { let ret = match crate::hostcalls_impl::$name($($arg,)*) { Ok(()) => crate::host::__WASI_ESUCCESS, - Err(e) => e, + Err(e) => e.as_wasi_errno(), }; crate::hostcalls::return_enc_errno(ret) diff --git a/src/memory.rs b/src/memory.rs index ef504ac2d5..bb719aa633 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,36 +1,36 @@ //! Functions to go back and forth between WASI types in host and wasm32 representations. #![allow(unused)] -use crate::{host, wasm32, Result}; +use crate::{host, wasm32, Error, Result}; use std::convert::TryFrom; use std::mem::{align_of, size_of}; use std::{ptr, slice}; fn dec_ptr(memory: &[u8], ptr: wasm32::uintptr_t, len: usize) -> Result<*const u8> { // check for overflow - let checked_len = (ptr as usize).checked_add(len).ok_or(host::__WASI_EFAULT)?; + let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?; // translate the pointer memory .get(ptr as usize..checked_len) - .ok_or(host::__WASI_EFAULT) + .ok_or(Error::EFAULT) .map(|mem| mem.as_ptr()) } fn dec_ptr_mut(memory: &mut [u8], ptr: wasm32::uintptr_t, len: usize) -> Result<*mut u8> { // check for overflow - let checked_len = (ptr as usize).checked_add(len).ok_or(host::__WASI_EFAULT)?; + let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?; // translate the pointer memory .get_mut(ptr as usize..checked_len) - .ok_or(host::__WASI_EFAULT) + .ok_or(Error::EFAULT) .map(|mem| mem.as_mut_ptr()) } fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasm32::uintptr_t) -> Result<&'memory T> { // check that the ptr is aligned if ptr as usize % align_of::() != 0 { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } dec_ptr(memory, ptr, size_of::()).map(|p| unsafe { &*(p as *const T) }) @@ -42,7 +42,7 @@ fn dec_ptr_to_mut<'memory, T>( ) -> Result<&'memory mut T> { // check that the ptr is aligned if ptr as usize % align_of::() != 0 { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } dec_ptr_mut(memory, ptr, size_of::()).map(|p| unsafe { &mut *(p as *mut T) }) @@ -59,13 +59,13 @@ pub fn enc_pointee(memory: &mut [u8], ptr: wasm32::uintptr_t, t: T) -> Result fn check_slice_of(ptr: wasm32::uintptr_t, len: wasm32::size_t) -> Result<(usize, usize)> { // check alignment, and that length doesn't overflow if ptr as usize % align_of::() != 0 { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } let len = dec_usize(len); let len_bytes = if let Some(len) = size_of::().checked_mul(len) { len } else { - return Err(host::__WASI_EOVERFLOW); + return Err(Error::EOVERFLOW); }; Ok((len, len_bytes)) @@ -94,13 +94,13 @@ pub fn dec_slice_of_mut<'memory, T>( pub fn enc_slice_of(memory: &mut [u8], slice: &[T], ptr: wasm32::uintptr_t) -> Result<()> { // check alignment if ptr as usize % align_of::() != 0 { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } // check that length doesn't overflow let len_bytes = if let Some(len) = size_of::().checked_mul(slice.len()) { len } else { - return Err(host::__WASI_EOVERFLOW); + return Err(Error::EOVERFLOW); }; // get the pointer into guest memory, and copy the bytes @@ -357,7 +357,7 @@ pub fn dec_prestat(prestat: wasm32::__wasi_prestat_t) -> Result Err(host::__WASI_EINVAL), + _ => Err(Error::EINVAL), } } @@ -381,7 +381,7 @@ pub fn enc_prestat(prestat: host::__wasi_prestat_t) -> Result Err(host::__WASI_EINVAL), + _ => Err(Error::EINVAL), } } @@ -497,7 +497,7 @@ pub fn dec_subscription( fd: dec_fd(unsafe{u_orig.fd_readwrite.fd}) } }, - _ => return Err(wasm32::__WASI_EINVAL) + _ => return Err(Error::EINVAL) }; Ok(host::__wasi_subscription_t { userdata, type_, u }) } diff --git a/src/sys/mod.rs b/src/sys/mod.rs index aad58cd230..17f8d09783 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -8,7 +8,7 @@ cfg_if! { pub use self::unix::preopen_dir; pub(crate) fn errno_from_host(err: i32) -> host::__wasi_errno_t { - host_impl::errno_from_nix(nix::errno::from_i32(err)) + host_impl::errno_from_nix(nix::errno::from_i32(err)).as_wasi_errno() } } else if #[cfg(windows)] { mod windows; @@ -23,7 +23,7 @@ cfg_if! { } } -pub(crate) fn errno_from_ioerror(e: std::io::Error) -> host::__wasi_errno_t { +pub(crate) fn errno_from_ioerror(e: &std::io::Error) -> host::__wasi_errno_t { match e.raw_os_error() { Some(code) => errno_from_host(code), None => { diff --git a/src/sys/unix/fdentry_impl.rs b/src/sys/unix/fdentry_impl.rs index 019f6015c9..4744794768 100644 --- a/src/sys/unix/fdentry_impl.rs +++ b/src/sys/unix/fdentry_impl.rs @@ -1,6 +1,5 @@ use crate::fdentry::Descriptor; -use crate::sys::{errno_from_host, errno_from_ioerror}; -use crate::{host, Result}; +use crate::{host, Error, Result}; use std::io; use std::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd}; @@ -25,10 +24,7 @@ pub(crate) fn determine_type_and_access_rights( let (file_type, mut rights_base, rights_inheriting) = determine_type_rights(fd)?; use nix::fcntl::{fcntl, OFlag, F_GETFL}; - let flags_bits = fcntl(fd.as_raw_fd(), F_GETFL).map_err(|err| { - err.as_errno() - .map_or(host::__WASI_EIO, |e| errno_from_host(e as i32)) - })?; + let flags_bits = fcntl(fd.as_raw_fd(), F_GETFL)?; let flags = OFlag::from_bits_truncate(flags_bits); let accmode = flags & OFlag::O_ACCMODE; if accmode == OFlag::O_RDONLY { @@ -51,7 +47,7 @@ pub(crate) fn determine_type_rights( // we just make a `File` here for convenience; we don't want it to close when it drops let file = std::mem::ManuallyDrop::new(unsafe { std::fs::File::from_raw_fd(fd.as_raw_fd()) }); - let ft = file.metadata().map_err(errno_from_ioerror)?.file_type(); + let ft = file.metadata()?.file_type(); if ft.is_block_device() { ( host::__WASI_FILETYPE_BLOCK_DEVICE, @@ -59,10 +55,7 @@ pub(crate) fn determine_type_rights( host::RIGHTS_BLOCK_DEVICE_INHERITING, ) } else if ft.is_char_device() { - if nix::unistd::isatty(fd.as_raw_fd()).map_err(|err| { - err.as_errno() - .map_or(host::__WASI_EIO, |e| errno_from_host(e as i32)) - })? { + if nix::unistd::isatty(fd.as_raw_fd())? { ( host::__WASI_FILETYPE_CHARACTER_DEVICE, host::RIGHTS_TTY_BASE, @@ -89,10 +82,7 @@ pub(crate) fn determine_type_rights( ) } else if ft.is_socket() { use nix::sys::socket; - match socket::getsockopt(fd.as_raw_fd(), socket::sockopt::SockType).map_err(|err| { - err.as_errno() - .map_or(host::__WASI_EIO, |e| errno_from_host(e as i32)) - })? { + match socket::getsockopt(fd.as_raw_fd(), socket::sockopt::SockType)? { socket::SockType::Datagram => ( host::__WASI_FILETYPE_SOCKET_DGRAM, host::RIGHTS_SOCKET_BASE, @@ -103,7 +93,7 @@ pub(crate) fn determine_type_rights( host::RIGHTS_SOCKET_BASE, host::RIGHTS_SOCKET_INHERITING, ), - _ => return Err(host::__WASI_EINVAL), + _ => return Err(Error::EINVAL), } } else if ft.is_fifo() { ( @@ -112,7 +102,7 @@ pub(crate) fn determine_type_rights( host::RIGHTS_REGULAR_FILE_INHERITING, ) } else { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } }; diff --git a/src/sys/unix/host_impl.rs b/src/sys/unix/host_impl.rs index 9402b8b550..1294c49455 100644 --- a/src/sys/unix/host_impl.rs +++ b/src/sys/unix/host_impl.rs @@ -2,87 +2,91 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(dead_code)] -use crate::{host, memory, Result}; +use crate::{host, memory, Error, Result}; +use log::warn; use std::ffi::OsStr; use std::os::unix::prelude::OsStrExt; -pub(crate) fn errno_from_nix(errno: nix::errno::Errno) -> host::__wasi_errno_t { +pub(crate) fn errno_from_nix(errno: nix::errno::Errno) -> Error { match errno { - nix::errno::Errno::EPERM => host::__WASI_EPERM, - nix::errno::Errno::ENOENT => host::__WASI_ENOENT, - nix::errno::Errno::ESRCH => host::__WASI_ESRCH, - nix::errno::Errno::EINTR => host::__WASI_EINTR, - nix::errno::Errno::EIO => host::__WASI_EIO, - nix::errno::Errno::ENXIO => host::__WASI_ENXIO, - nix::errno::Errno::E2BIG => host::__WASI_E2BIG, - nix::errno::Errno::ENOEXEC => host::__WASI_ENOEXEC, - nix::errno::Errno::EBADF => host::__WASI_EBADF, - nix::errno::Errno::ECHILD => host::__WASI_ECHILD, - nix::errno::Errno::EAGAIN => host::__WASI_EAGAIN, - nix::errno::Errno::ENOMEM => host::__WASI_ENOMEM, - nix::errno::Errno::EACCES => host::__WASI_EACCES, - nix::errno::Errno::EFAULT => host::__WASI_EFAULT, - nix::errno::Errno::EBUSY => host::__WASI_EBUSY, - nix::errno::Errno::EEXIST => host::__WASI_EEXIST, - nix::errno::Errno::EXDEV => host::__WASI_EXDEV, - nix::errno::Errno::ENODEV => host::__WASI_ENODEV, - nix::errno::Errno::ENOTDIR => host::__WASI_ENOTDIR, - nix::errno::Errno::EISDIR => host::__WASI_EISDIR, - nix::errno::Errno::EINVAL => host::__WASI_EINVAL, - nix::errno::Errno::ENFILE => host::__WASI_ENFILE, - nix::errno::Errno::EMFILE => host::__WASI_EMFILE, - nix::errno::Errno::ENOTTY => host::__WASI_ENOTTY, - nix::errno::Errno::ETXTBSY => host::__WASI_ETXTBSY, - nix::errno::Errno::EFBIG => host::__WASI_EFBIG, - nix::errno::Errno::ENOSPC => host::__WASI_ENOSPC, - nix::errno::Errno::ESPIPE => host::__WASI_ESPIPE, - nix::errno::Errno::EROFS => host::__WASI_EROFS, - nix::errno::Errno::EMLINK => host::__WASI_EMLINK, - nix::errno::Errno::EPIPE => host::__WASI_EPIPE, - nix::errno::Errno::EDOM => host::__WASI_EDOM, - nix::errno::Errno::ERANGE => host::__WASI_ERANGE, - nix::errno::Errno::EDEADLK => host::__WASI_EDEADLK, - nix::errno::Errno::ENAMETOOLONG => host::__WASI_ENAMETOOLONG, - nix::errno::Errno::ENOLCK => host::__WASI_ENOLCK, - nix::errno::Errno::ENOSYS => host::__WASI_ENOSYS, - nix::errno::Errno::ENOTEMPTY => host::__WASI_ENOTEMPTY, - nix::errno::Errno::ELOOP => host::__WASI_ELOOP, - nix::errno::Errno::ENOMSG => host::__WASI_ENOMSG, - nix::errno::Errno::EIDRM => host::__WASI_EIDRM, - nix::errno::Errno::ENOLINK => host::__WASI_ENOLINK, - nix::errno::Errno::EPROTO => host::__WASI_EPROTO, - nix::errno::Errno::EMULTIHOP => host::__WASI_EMULTIHOP, - nix::errno::Errno::EBADMSG => host::__WASI_EBADMSG, - nix::errno::Errno::EOVERFLOW => host::__WASI_EOVERFLOW, - nix::errno::Errno::EILSEQ => host::__WASI_EILSEQ, - nix::errno::Errno::ENOTSOCK => host::__WASI_ENOTSOCK, - nix::errno::Errno::EDESTADDRREQ => host::__WASI_EDESTADDRREQ, - nix::errno::Errno::EMSGSIZE => host::__WASI_EMSGSIZE, - nix::errno::Errno::EPROTOTYPE => host::__WASI_EPROTOTYPE, - nix::errno::Errno::ENOPROTOOPT => host::__WASI_ENOPROTOOPT, - nix::errno::Errno::EPROTONOSUPPORT => host::__WASI_EPROTONOSUPPORT, - nix::errno::Errno::EAFNOSUPPORT => host::__WASI_EAFNOSUPPORT, - nix::errno::Errno::EADDRINUSE => host::__WASI_EADDRINUSE, - nix::errno::Errno::EADDRNOTAVAIL => host::__WASI_EADDRNOTAVAIL, - nix::errno::Errno::ENETDOWN => host::__WASI_ENETDOWN, - nix::errno::Errno::ENETUNREACH => host::__WASI_ENETUNREACH, - nix::errno::Errno::ENETRESET => host::__WASI_ENETRESET, - nix::errno::Errno::ECONNABORTED => host::__WASI_ECONNABORTED, - nix::errno::Errno::ECONNRESET => host::__WASI_ECONNRESET, - nix::errno::Errno::ENOBUFS => host::__WASI_ENOBUFS, - nix::errno::Errno::EISCONN => host::__WASI_EISCONN, - nix::errno::Errno::ENOTCONN => host::__WASI_ENOTCONN, - nix::errno::Errno::ETIMEDOUT => host::__WASI_ETIMEDOUT, - nix::errno::Errno::ECONNREFUSED => host::__WASI_ECONNREFUSED, - nix::errno::Errno::EHOSTUNREACH => host::__WASI_EHOSTUNREACH, - nix::errno::Errno::EALREADY => host::__WASI_EALREADY, - nix::errno::Errno::EINPROGRESS => host::__WASI_EINPROGRESS, - nix::errno::Errno::ESTALE => host::__WASI_ESTALE, - nix::errno::Errno::EDQUOT => host::__WASI_EDQUOT, - nix::errno::Errno::ECANCELED => host::__WASI_ECANCELED, - nix::errno::Errno::EOWNERDEAD => host::__WASI_EOWNERDEAD, - nix::errno::Errno::ENOTRECOVERABLE => host::__WASI_ENOTRECOVERABLE, - _ => host::__WASI_ENOSYS, + nix::errno::Errno::EPERM => Error::EPERM, + nix::errno::Errno::ENOENT => Error::ENOENT, + nix::errno::Errno::ESRCH => Error::ESRCH, + nix::errno::Errno::EINTR => Error::EINTR, + nix::errno::Errno::EIO => Error::EIO, + nix::errno::Errno::ENXIO => Error::ENXIO, + nix::errno::Errno::E2BIG => Error::E2BIG, + nix::errno::Errno::ENOEXEC => Error::ENOEXEC, + nix::errno::Errno::EBADF => Error::EBADF, + nix::errno::Errno::ECHILD => Error::ECHILD, + nix::errno::Errno::EAGAIN => Error::EAGAIN, + nix::errno::Errno::ENOMEM => Error::ENOMEM, + nix::errno::Errno::EACCES => Error::EACCES, + nix::errno::Errno::EFAULT => Error::EFAULT, + nix::errno::Errno::EBUSY => Error::EBUSY, + nix::errno::Errno::EEXIST => Error::EEXIST, + nix::errno::Errno::EXDEV => Error::EXDEV, + nix::errno::Errno::ENODEV => Error::ENODEV, + nix::errno::Errno::ENOTDIR => Error::ENOTDIR, + nix::errno::Errno::EISDIR => Error::EISDIR, + nix::errno::Errno::EINVAL => Error::EINVAL, + nix::errno::Errno::ENFILE => Error::ENFILE, + nix::errno::Errno::EMFILE => Error::EMFILE, + nix::errno::Errno::ENOTTY => Error::ENOTTY, + nix::errno::Errno::ETXTBSY => Error::ETXTBSY, + nix::errno::Errno::EFBIG => Error::EFBIG, + nix::errno::Errno::ENOSPC => Error::ENOSPC, + nix::errno::Errno::ESPIPE => Error::ESPIPE, + nix::errno::Errno::EROFS => Error::EROFS, + nix::errno::Errno::EMLINK => Error::EMLINK, + nix::errno::Errno::EPIPE => Error::EPIPE, + nix::errno::Errno::EDOM => Error::EDOM, + nix::errno::Errno::ERANGE => Error::ERANGE, + nix::errno::Errno::EDEADLK => Error::EDEADLK, + nix::errno::Errno::ENAMETOOLONG => Error::ENAMETOOLONG, + nix::errno::Errno::ENOLCK => Error::ENOLCK, + nix::errno::Errno::ENOSYS => Error::ENOSYS, + nix::errno::Errno::ENOTEMPTY => Error::ENOTEMPTY, + nix::errno::Errno::ELOOP => Error::ELOOP, + nix::errno::Errno::ENOMSG => Error::ENOMSG, + nix::errno::Errno::EIDRM => Error::EIDRM, + nix::errno::Errno::ENOLINK => Error::ENOLINK, + nix::errno::Errno::EPROTO => Error::EPROTO, + nix::errno::Errno::EMULTIHOP => Error::EMULTIHOP, + nix::errno::Errno::EBADMSG => Error::EBADMSG, + nix::errno::Errno::EOVERFLOW => Error::EOVERFLOW, + nix::errno::Errno::EILSEQ => Error::EILSEQ, + nix::errno::Errno::ENOTSOCK => Error::ENOTSOCK, + nix::errno::Errno::EDESTADDRREQ => Error::EDESTADDRREQ, + nix::errno::Errno::EMSGSIZE => Error::EMSGSIZE, + nix::errno::Errno::EPROTOTYPE => Error::EPROTOTYPE, + nix::errno::Errno::ENOPROTOOPT => Error::ENOPROTOOPT, + nix::errno::Errno::EPROTONOSUPPORT => Error::EPROTONOSUPPORT, + nix::errno::Errno::EAFNOSUPPORT => Error::EAFNOSUPPORT, + nix::errno::Errno::EADDRINUSE => Error::EADDRINUSE, + nix::errno::Errno::EADDRNOTAVAIL => Error::EADDRNOTAVAIL, + nix::errno::Errno::ENETDOWN => Error::ENETDOWN, + nix::errno::Errno::ENETUNREACH => Error::ENETUNREACH, + nix::errno::Errno::ENETRESET => Error::ENETRESET, + nix::errno::Errno::ECONNABORTED => Error::ECONNABORTED, + nix::errno::Errno::ECONNRESET => Error::ECONNRESET, + nix::errno::Errno::ENOBUFS => Error::ENOBUFS, + nix::errno::Errno::EISCONN => Error::EISCONN, + nix::errno::Errno::ENOTCONN => Error::ENOTCONN, + nix::errno::Errno::ETIMEDOUT => Error::ETIMEDOUT, + nix::errno::Errno::ECONNREFUSED => Error::ECONNREFUSED, + nix::errno::Errno::EHOSTUNREACH => Error::EHOSTUNREACH, + nix::errno::Errno::EALREADY => Error::EALREADY, + nix::errno::Errno::EINPROGRESS => Error::EINPROGRESS, + nix::errno::Errno::ESTALE => Error::ESTALE, + nix::errno::Errno::EDQUOT => Error::EDQUOT, + nix::errno::Errno::ECANCELED => Error::ECANCELED, + nix::errno::Errno::EOWNERDEAD => Error::EOWNERDEAD, + nix::errno::Errno::ENOTRECOVERABLE => Error::ENOTRECOVERABLE, + other => { + warn!("Unknown error from nix: {}", other); + Error::ENOSYS + } } } @@ -179,14 +183,12 @@ pub(crate) fn filestat_from_nix( fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result { secs.checked_mul(1_000_000_000) .and_then(|sec_nsec| sec_nsec.checked_add(nsecs)) - .ok_or(host::__WASI_EOVERFLOW) + .ok_or(Error::EOVERFLOW) } let filetype = nix::sys::stat::SFlag::from_bits_truncate(filestat.st_mode); - let dev = - host::__wasi_device_t::try_from(filestat.st_dev).map_err(|_| host::__WASI_EOVERFLOW)?; - let ino = - host::__wasi_inode_t::try_from(filestat.st_ino).map_err(|_| host::__WASI_EOVERFLOW)?; + let dev = host::__wasi_device_t::try_from(filestat.st_dev).map_err(|_| Error::EOVERFLOW)?; + let ino = host::__wasi_inode_t::try_from(filestat.st_ino).map_err(|_| Error::EOVERFLOW)?; let st_atim = filestat_to_timestamp(filestat.st_atime as u64, filestat.st_atime_nsec as u64)?; let st_ctim = filestat_to_timestamp(filestat.st_ctime as u64, filestat.st_ctime_nsec as u64)?; let st_mtim = filestat_to_timestamp(filestat.st_mtime as u64, filestat.st_mtime_nsec as u64)?; @@ -222,7 +224,7 @@ pub(crate) fn dirent_filetype_from_host( Ok(host::__WASI_FILETYPE_UNKNOWN) } libc::DT_UNKNOWN => Ok(host::__WASI_FILETYPE_UNKNOWN), - _ => Err(host::__WASI_EINVAL), + _ => Err(Error::EINVAL), } } @@ -233,7 +235,7 @@ pub(crate) fn dirent_from_host(host_entry: &nix::libc::dirent) -> Result u32::max_value() as usize { - return Err(host::__WASI_EIO); + return Err(Error::EIO); } let d_type = dirent_filetype_from_host(host_entry)?; entry.d_ino = memory::enc_inode(host_entry.d_ino); diff --git a/src/sys/unix/hostcalls_impl/fs.rs b/src/sys/unix/hostcalls_impl/fs.rs index 380cfb6a53..0771910749 100644 --- a/src/sys/unix/hostcalls_impl/fs.rs +++ b/src/sys/unix/hostcalls_impl/fs.rs @@ -3,9 +3,8 @@ use super::fs_helpers::*; use crate::helpers::systemtime_to_timestamp; use crate::hostcalls_impl::PathGet; -use crate::sys::errno_from_ioerror; use crate::sys::host_impl::{self, errno_from_nix}; -use crate::{host, Result}; +use crate::{host, Result, Error}; use nix::libc::{self, c_long, c_void}; use std::convert::TryInto; use std::ffi::CString; @@ -18,11 +17,11 @@ pub(crate) fn fd_pread( buf: &mut [u8], offset: host::__wasi_filesize_t, ) -> Result { - file.read_at(buf, offset).map_err(errno_from_ioerror) + file.read_at(buf, offset).map_err(Into::into) } pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: host::__wasi_filesize_t) -> Result { - file.write_at(buf, offset).map_err(errno_from_ioerror) + file.write_at(buf, offset).map_err(Into::into) } pub(crate) fn fd_fdstat_get(fd: &File) -> Result { @@ -52,8 +51,8 @@ pub(crate) fn fd_advise( { use nix::fcntl::{posix_fadvise, PosixFadviseAdvice}; - let offset = offset.try_into().map_err(|_| host::__WASI_EOVERFLOW)?; - let len = len.try_into().map_err(|_| host::__WASI_EOVERFLOW)?; + let offset = offset.try_into().map_err(|_| Error::EOVERFLOW)?; + let len = len.try_into().map_err(|_| Error::EOVERFLOW)?; let host_advice = match advice { host::__WASI_ADVICE_DONTNEED => PosixFadviseAdvice::POSIX_FADV_DONTNEED, host::__WASI_ADVICE_SEQUENTIAL => PosixFadviseAdvice::POSIX_FADV_SEQUENTIAL, @@ -61,7 +60,7 @@ pub(crate) fn fd_advise( host::__WASI_ADVICE_NOREUSE => PosixFadviseAdvice::POSIX_FADV_NOREUSE, host::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::POSIX_FADV_RANDOM, host::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::POSIX_FADV_NORMAL, - _ => return Err(host::__WASI_EINVAL), + _ => return Err(Error::EINVAL), }; posix_fadvise(file.as_raw_fd(), offset, len, host_advice) @@ -85,7 +84,7 @@ pub(crate) fn fd_advise( | host::__WASI_ADVICE_NOREUSE | host::__WASI_ADVICE_RANDOM | host::__WASI_ADVICE_NORMAL => {} - _ => return Err(host::__WASI_EINVAL), + _ => return Err(Error::EINVAL), } Ok(()) @@ -93,7 +92,7 @@ pub(crate) fn fd_advise( pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> { use nix::libc::mkdirat; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; // nix doesn't expose mkdirat() yet match unsafe { mkdirat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0o777) } { 0 => Ok(()), @@ -104,9 +103,9 @@ pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> { pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { use nix::libc::linkat; let old_path_cstr = - CString::new(resolved_old.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + CString::new(resolved_old.path().as_bytes()).map_err(|_| Error::EILSEQ)?; let new_path_cstr = - CString::new(resolved_new.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + CString::new(resolved_new.path().as_bytes()).map_err(|_| Error::EILSEQ)?; // Not setting AT_SYMLINK_FOLLOW fails on most filesystems let atflags = libc::AT_SYMLINK_FOLLOW; @@ -174,12 +173,12 @@ pub(crate) fn path_open( AtFlags::AT_SYMLINK_NOFOLLOW, ) { if SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFSOCK) { - return Err(host::__WASI_ENOTSUP); + return Err(Error::ENOTSUP); } else { - return Err(host::__WASI_ENXIO); + return Err(Error::ENXIO); } } else { - return Err(host::__WASI_ENXIO); + return Err(Error::ENXIO); } } // Linux returns ENOTDIR instead of ELOOP when using O_NOFOLLOW|O_DIRECTORY @@ -193,18 +192,18 @@ pub(crate) fn path_open( AtFlags::AT_SYMLINK_NOFOLLOW, ) { if SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFLNK) { - return Err(host::__WASI_ELOOP); + return Err(Error::ELOOP); } } - return Err(host::__WASI_ENOTDIR); + return Err(Error::ENOTDIR); } // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on // a symlink. Some(Errno::EMLINK) if !(nix_all_oflags & OFlag::O_NOFOLLOW).is_empty() => { - return Err(host::__WASI_ELOOP); + return Err(Error::ELOOP); } Some(e) => return Err(host_impl::errno_from_nix(e)), - None => return Err(host::__WASI_ENOSYS), + None => return Err(Error::ENOSYS), } } }; @@ -275,7 +274,7 @@ pub(crate) fn fd_readdir( pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result { use nix::errno::Errno; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; // Linux requires that the buffer size is positive, whereas POSIX does not. // Use a fake buffer to store the results if the size is zero. @@ -307,9 +306,9 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { use nix::libc::renameat; let old_path_cstr = - CString::new(resolved_old.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + CString::new(resolved_old.path().as_bytes()).map_err(|_| Error::EILSEQ)?; let new_path_cstr = - CString::new(resolved_new.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + CString::new(resolved_new.path().as_bytes()).map_err(|_| Error::EILSEQ)?; let res = unsafe { renameat( @@ -329,27 +328,19 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result { use std::os::unix::fs::MetadataExt; - let metadata = file.metadata().map_err(errno_from_ioerror)?; + let metadata = file.metadata()?; Ok(host::__wasi_filestat_t { st_dev: metadata.dev(), st_ino: metadata.ino(), st_nlink: metadata .nlink() - .try_into() - .map_err(|_| host::__WASI_EOVERFLOW)?, // u64 doesn't fit into u32 + .try_into()?, // u64 doesn't fit into u32 st_size: metadata.len(), - st_atim: metadata - .accessed() - .map_err(errno_from_ioerror) - .and_then(systemtime_to_timestamp)?, + st_atim: systemtime_to_timestamp(metadata.accessed()?)?, st_ctim: metadata .ctime() - .try_into() - .map_err(|_| host::__WASI_EOVERFLOW)?, // i64 doesn't fit into u64 - st_mtim: metadata - .modified() - .map_err(errno_from_ioerror) - .and_then(systemtime_to_timestamp)?, + .try_into()?, // i64 doesn't fit into u64 + st_mtim: systemtime_to_timestamp(metadata.modified()?)?, st_filetype: filetype(file, &metadata)?, }) } @@ -432,7 +423,7 @@ pub(crate) fn path_filestat_set_times( let set_mtim_now = fst_flags & host::__WASI_FILESTAT_SET_MTIM_NOW != 0; if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } let atflags = match dirflags { @@ -441,7 +432,7 @@ pub(crate) fn path_filestat_set_times( }; let atim = if set_atim_now { - let st_atim = st_atim.try_into().map_err(|_| host::__WASI_EOVERFLOW)?; + let st_atim = st_atim.try_into().map_err(|_| Error::EOVERFLOW)?; TimeSpec::nanoseconds(st_atim) } else if set_atim_now { timespec_now() @@ -450,7 +441,7 @@ pub(crate) fn path_filestat_set_times( }; let mtim = if set_mtim { - let st_mtim = st_mtim.try_into().map_err(|_| host::__WASI_EOVERFLOW)?; + let st_mtim = st_mtim.try_into().map_err(|_| Error::EOVERFLOW)?; TimeSpec::nanoseconds(st_mtim) } else if set_atim_now { timespec_now() @@ -466,9 +457,9 @@ pub(crate) fn path_filestat_set_times( pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { use nix::libc::symlinkat; - let old_path_cstr = CString::new(old_path.as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + let old_path_cstr = CString::new(old_path.as_bytes()).map_err(|_| Error::EILSEQ)?; let new_path_cstr = - CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; let res = unsafe { symlinkat( @@ -488,7 +479,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { use nix::errno; use nix::libc::unlinkat; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; // nix doesn't expose unlinkat() yet match unsafe { unlinkat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0) } { @@ -532,7 +523,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { use nix::errno; use nix::libc::{unlinkat, AT_REMOVEDIR}; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| host::__WASI_EILSEQ)?; + let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; // nix doesn't expose unlinkat() yet match unsafe { diff --git a/src/sys/unix/hostcalls_impl/misc.rs b/src/sys/unix/hostcalls_impl/misc.rs index b724a002ab..f21290c921 100644 --- a/src/sys/unix/hostcalls_impl/misc.rs +++ b/src/sys/unix/hostcalls_impl/misc.rs @@ -2,7 +2,7 @@ #![allow(unused_unsafe)] use crate::memory::*; use crate::sys::host_impl; -use crate::{host, wasm32, Result}; +use crate::{host, wasm32, Result, Error}; use nix::libc::{self, c_int}; use std::cmp; use std::time::SystemTime; @@ -14,7 +14,7 @@ pub(crate) fn clock_res_get(clock_id: host::__wasi_clockid_t) -> Result libc::CLOCK_MONOTONIC, host::__WASI_CLOCK_PROCESS_CPUTIME_ID => libc::CLOCK_PROCESS_CPUTIME_ID, host::__WASI_CLOCK_THREAD_CPUTIME_ID => libc::CLOCK_THREAD_CPUTIME_ID, - _ => return Err(host::__WASI_EINVAL), + _ => return Err(Error::EINVAL), }; // no `nix` wrapper for clock_getres, so we do it ourselves @@ -30,11 +30,11 @@ pub(crate) fn clock_res_get(clock_id: host::__wasi_clockid_t) -> Result Result libc::CLOCK_MONOTONIC, host::__WASI_CLOCK_PROCESS_CPUTIME_ID => libc::CLOCK_PROCESS_CPUTIME_ID, host::__WASI_CLOCK_THREAD_CPUTIME_ID => libc::CLOCK_THREAD_CPUTIME_ID, - _ => return Err(host::__WASI_EINVAL), + _ => return Err(Error::EINVAL), }; // no `nix` wrapper for clock_getres, so we do it ourselves @@ -63,7 +63,7 @@ pub(crate) fn clock_time_get(clock_id: host::__wasi_clockid_t) -> Result Result { - File::open("/dev/null").map_err(errno_from_ioerror) + File::open("/dev/null").map_err(Into::into) } pub fn preopen_dir>(path: P) -> Result { - File::open(path).map_err(errno_from_ioerror) + File::open(path).map_err(Into::into) } diff --git a/src/sys/windows/fdentry_impl.rs b/src/sys/windows/fdentry_impl.rs index 3d68f8ed96..9c4d1209d7 100644 --- a/src/sys/windows/fdentry_impl.rs +++ b/src/sys/windows/fdentry_impl.rs @@ -1,6 +1,5 @@ -use super::host_impl; use crate::fdentry::Descriptor; -use crate::{host, Result}; +use crate::{host, Error, Result}; use std::fs::File; use std::io; use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle}; @@ -29,8 +28,7 @@ pub(crate) fn determine_type_and_access_rights( match file_type { host::__WASI_FILETYPE_DIRECTORY | host::__WASI_FILETYPE_REGULAR_FILE => { - let mode = - get_file_access_mode(handle.as_raw_handle()).map_err(host_impl::errno_from_win)?; + let mode = get_file_access_mode(handle.as_raw_handle())?; if mode.contains(AccessMode::FILE_GENERIC_READ) { rights_base |= host::__WASI_RIGHT_FD_READ; } @@ -55,8 +53,7 @@ pub(crate) fn determine_type_rights( host::__wasi_rights_t, )> { let (file_type, rights_base, rights_inheriting) = { - let file_type = - winx::file::get_file_type(handle.as_raw_handle()).map_err(host_impl::errno_from_win)?; + let file_type = winx::file::get_file_type(handle.as_raw_handle())?; if file_type.is_char() { // character file: LPT device or console // TODO: rule out LPT device @@ -70,7 +67,7 @@ pub(crate) fn determine_type_rights( let file = std::mem::ManuallyDrop::new(unsafe { File::from_raw_handle(handle.as_raw_handle()) }); - let meta = file.metadata().map_err(|_| host::__WASI_EINVAL)?; + let meta = file.metadata().map_err(|_| Error::EINVAL)?; if meta.is_dir() { ( host::__WASI_FILETYPE_DIRECTORY, @@ -84,7 +81,7 @@ pub(crate) fn determine_type_rights( host::RIGHTS_REGULAR_FILE_INHERITING, ) } else { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } } else if file_type.is_pipe() { // pipe object: socket, named pipe or anonymous pipe @@ -95,7 +92,7 @@ pub(crate) fn determine_type_rights( host::RIGHTS_SOCKET_INHERITING, ) } else { - return Err(host::__WASI_EINVAL); + return Err(Error::EINVAL); } }; Ok((file_type, rights_base, rights_inheriting)) diff --git a/src/sys/windows/host_impl.rs b/src/sys/windows/host_impl.rs index c53f29bc25..df6991f1c5 100644 --- a/src/sys/windows/host_impl.rs +++ b/src/sys/windows/host_impl.rs @@ -2,7 +2,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(unused)] -use crate::{host, Result}; +use crate::{host, Result, Error}; use std::ffi::OsStr; use std::fs::OpenOptions; use std::os::windows::ffi::OsStrExt; @@ -102,5 +102,5 @@ pub(crate) fn win_from_oflags(oflags: host::__wasi_oflags_t) -> CreationDisposit /// `__WASI_EILSEQ` error is returned. pub(crate) fn path_from_host>(s: S) -> Result { let vec: Vec = s.as_ref().encode_wide().collect(); - String::from_utf16(&vec).map_err(|_| host::__WASI_EILSEQ) + String::from_utf16(&vec).map_err(|_| Error::EILSEQ) } diff --git a/src/sys/windows/hostcalls_impl/fs.rs b/src/sys/windows/hostcalls_impl/fs.rs index c8e1da9b24..93b04c144e 100644 --- a/src/sys/windows/hostcalls_impl/fs.rs +++ b/src/sys/windows/hostcalls_impl/fs.rs @@ -8,8 +8,7 @@ use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet}; use crate::sys::fdentry_impl::determine_type_rights; use crate::sys::host_impl; use crate::sys::hostcalls_impl::fs_helpers::PathGetExt; -use crate::sys::{errno_from_host, errno_from_ioerror}; -use crate::{host, Result}; +use crate::{host, Error, Result}; use std::convert::TryInto; use std::fs::{File, Metadata, OpenOptions}; use std::io::{self, Seek, SeekFrom}; @@ -37,23 +36,25 @@ fn write_at(mut file: &File, buf: &[u8], offset: u64) -> io::Result { Ok(nwritten) } +// TODO refactor common code with unix pub(crate) fn fd_pread( file: &File, buf: &mut [u8], offset: host::__wasi_filesize_t, ) -> Result { - read_at(file, buf, offset).map_err(errno_from_ioerror) + read_at(file, buf, offset).map_err(Into::into) } +// TODO refactor common code with unix pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: host::__wasi_filesize_t) -> Result { - write_at(file, buf, offset).map_err(errno_from_ioerror) + write_at(file, buf, offset).map_err(Into::into) } pub(crate) fn fd_fdstat_get(fd: &File) -> Result { use winx::file::AccessMode; winx::file::get_file_access_mode(fd.as_raw_handle()) .map(host_impl::fdflags_from_win) - .map_err(host_impl::errno_from_win) + .map_err(Into::into) } pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: host::__wasi_fdflags_t) -> Result<()> { @@ -81,7 +82,7 @@ pub(crate) fn fd_advise( pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> { let path = resolved.concatenate()?; - std::fs::create_dir(&path).map_err(errno_from_ioerror) + std::fs::create_dir(&path).map_err(Into::into) } pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { @@ -133,11 +134,11 @@ pub(crate) fn path_open( Ok(file_type) => { // check if we are trying to open a symlink if file_type.is_symlink() { - return Err(host::__WASI_ELOOP); + return Err(Error::ELOOP); } // check if we are trying to open a file as a dir if file_type.is_file() && oflags & host::__WASI_O_DIRECTORY != 0 { - return Err(host::__WASI_ENOTDIR); + return Err(Error::ENOTDIR); } } Err(e) => match e.raw_os_error() { @@ -147,14 +148,14 @@ pub(crate) fn path_open( let e = WinError::from_u32(e as u32); if e != WinError::ERROR_FILE_NOT_FOUND { - return Err(host_impl::errno_from_win(e)); + return Err(e.into()); } // file not found, let it proceed to actually // trying to open it } None => { log::debug!("Inconvertible OS error: {}", e); - return Err(host::__WASI_EIO); + return Err(Error::EIO); } }, } @@ -162,7 +163,7 @@ pub(crate) fn path_open( opts.access_mode(access_mode.bits()) .custom_flags(flags.bits()) .open(&path) - .map_err(errno_from_ioerror) + .map_err(Into::into) } pub(crate) fn fd_readdir( @@ -177,19 +178,18 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result use winx::file::get_path_by_handle; let path = resolved.concatenate()?; - let target_path = path.read_link().map_err(errno_from_ioerror)?; + let target_path = path.read_link()?; // since on Windows we are effectively emulating 'at' syscalls // we need to strip the prefix from the absolute path // as otherwise we will error out since WASI is not capable // of dealing with absolute paths - let dir_path = - get_path_by_handle(resolved.dirfd().as_raw_handle()).map_err(host_impl::errno_from_win)?; + let dir_path = get_path_by_handle(resolved.dirfd().as_raw_handle())?; let dir_path = PathBuf::from(strip_extended_prefix(dir_path)); let target_path = target_path .strip_prefix(dir_path) - .map_err(|_| host::__WASI_ENOTCAPABLE) - .and_then(|path| path.to_str().map(String::from).ok_or(host::__WASI_EILSEQ))?; + .map_err(|_| Error::ENOTCAPABLE) + .and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?; if buf.len() > 0 { let mut chars = target_path.chars(); @@ -222,7 +222,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul // // [std::fs::rename]: https://doc.rust-lang.org/std/fs/fn.rename.html if old_path.is_dir() && new_path.is_file() { - return Err(host::__WASI_ENOTDIR); + return Err(Error::ENOTDIR); } // TODO handle symlinks @@ -237,21 +237,21 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul // So most likely dealing with new_path == dir. // Eliminate case old_path == file first. if old_path.is_file() { - Err(host::__WASI_EISDIR) + Err(Error::EISDIR) } else { // Ok, let's try removing an empty dir at new_path if it exists // and is a nonempty dir. fs::remove_dir(&new_path) .and_then(|()| fs::rename(old_path, new_path)) - .map_err(errno_from_ioerror) + .map_err(Into::into) } } - e => Err(host_impl::errno_from_win(e)), + e => Err(e.into()), } } None => { log::debug!("Inconvertible OS error: {}", e); - Err(host::__WASI_EIO) + Err(Error::EIO) } }) } @@ -277,27 +277,15 @@ pub(crate) fn change_time(file: &File, _metadata: &Metadata) -> io::Result } pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result { - let metadata = file.metadata().map_err(errno_from_ioerror)?; + let metadata = file.metadata()?; Ok(host::__wasi_filestat_t { - st_dev: device_id(file, &metadata).map_err(errno_from_ioerror)?, - st_ino: file_serial_no(file, &metadata).map_err(errno_from_ioerror)?, - st_nlink: num_hardlinks(file, &metadata) - .map_err(errno_from_ioerror)? - .try_into() - .map_err(|_| host::__WASI_EOVERFLOW)?, // u64 doesn't fit into u32 + st_dev: device_id(file, &metadata)?, + st_ino: file_serial_no(file, &metadata)?, + st_nlink: num_hardlinks(file, &metadata)?.try_into()?, // u64 doesn't fit into u32 st_size: metadata.len(), - st_atim: metadata - .accessed() - .map_err(errno_from_ioerror) - .and_then(systemtime_to_timestamp)?, - st_ctim: change_time(file, &metadata) - .map_err(errno_from_ioerror)? - .try_into() - .map_err(|_| host::__WASI_EOVERFLOW)?, // i64 doesn't fit into u64 - st_mtim: metadata - .modified() - .map_err(errno_from_ioerror) - .and_then(systemtime_to_timestamp)?, + st_atim: systemtime_to_timestamp(metadata.accessed()?)?, + st_ctim: change_time(file, &metadata)?.try_into()?, // i64 doesn't fit into u64 + st_mtim: systemtime_to_timestamp(metadata.modified()?)?, st_filetype: filetype(file, &metadata)?, }) } @@ -322,7 +310,7 @@ pub(crate) fn path_filestat_get( dirflags: host::__wasi_lookupflags_t, ) -> Result { let path = resolved.concatenate()?; - let file = File::open(path).map_err(errno_from_ioerror)?; + let file = File::open(path)?; fd_filestat_get_impl(&file) } @@ -337,8 +325,7 @@ pub(crate) fn path_filestat_set_times( let path = resolved.concatenate()?; let file = OpenOptions::new() .access_mode(AccessMode::FILE_WRITE_ATTRIBUTES.bits()) - .open(path) - .map_err(errno_from_ioerror)?; + .open(path)?; fd_filestat_set_times_impl(&file, st_atim, st_mtim, fst_flags) } @@ -357,14 +344,14 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { match WinError::from_u32(e as u32) { WinError::ERROR_NOT_A_REPARSE_POINT => { // try creating a dir symlink instead - symlink_dir(old_path, new_path).map_err(errno_from_ioerror) + symlink_dir(old_path, new_path).map_err(Into::into) } - e => Err(host_impl::errno_from_win(e)), + e => Err(e.into()), } } None => { log::debug!("Inconvertible OS error: {}", e); - Err(host::__WASI_EIO) + Err(Error::EIO) } } }) @@ -377,8 +364,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { let path = resolved.concatenate()?; let file_type = path .symlink_metadata() - .map(|metadata| metadata.file_type()) - .map_err(errno_from_ioerror)?; + .map(|metadata| metadata.file_type())?; // check if we're unlinking a symlink // NB this will get cleaned up a lot when [std::os::windows::fs::FileTypeExt] @@ -393,27 +379,27 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { match WinError::from_u32(e as u32) { WinError::ERROR_ACCESS_DENIED => { // try unlinking a dir symlink instead - fs::remove_dir(path).map_err(errno_from_ioerror) + fs::remove_dir(path).map_err(Into::into) } - e => Err(host_impl::errno_from_win(e)), + e => Err(e.into()), } } None => { log::debug!("Inconvertible OS error: {}", e); - Err(host::__WASI_EIO) + Err(Error::EIO) } } }) } else if file_type.is_dir() { - Err(host::__WASI_EISDIR) + Err(Error::EISDIR) } else if file_type.is_file() { - fs::remove_file(path).map_err(errno_from_ioerror) + fs::remove_file(path).map_err(Into::into) } else { - Err(host::__WASI_EINVAL) + Err(Error::EINVAL) } } pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { let path = resolved.concatenate()?; - std::fs::remove_dir(&path).map_err(errno_from_ioerror) + std::fs::remove_dir(&path).map_err(Into::into) } diff --git a/src/sys/windows/hostcalls_impl/fs_helpers.rs b/src/sys/windows/hostcalls_impl/fs_helpers.rs index 6b1621358f..4b59e4bbf9 100644 --- a/src/sys/windows/hostcalls_impl/fs_helpers.rs +++ b/src/sys/windows/hostcalls_impl/fs_helpers.rs @@ -1,7 +1,6 @@ #![allow(non_camel_case_types)] -use crate::sys::host_impl; -use crate::{host, Result}; use crate::hostcalls_impl::PathGet; +use crate::{host, Error, Result}; use std::ffi::{OsStr, OsString}; use std::fs::File; use std::os::windows::ffi::{OsStrExt, OsStringExt}; @@ -62,13 +61,13 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result { Some(e) => { log::debug!("openat error={:?}", e); match WinError::from_u32(e as u32) { - WinError::ERROR_INVALID_NAME => host::__WASI_ENOTDIR, - e => host_impl::errno_from_win(e), + WinError::ERROR_INVALID_NAME => Error::ENOTDIR, + e => e.into(), } } None => { log::debug!("Inconvertible OS error: {}", e); - host::__WASI_EIO + Error::EIO } }) } @@ -84,13 +83,12 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result { // we need to strip the prefix from the absolute path // as otherwise we will error out since WASI is not capable // of dealing with absolute paths - let dir_path = - get_path_by_handle(dirfd.as_raw_handle()).map_err(host_impl::errno_from_win)?; + let dir_path = get_path_by_handle(dirfd.as_raw_handle())?; let dir_path = PathBuf::from(strip_extended_prefix(dir_path)); target_path .strip_prefix(dir_path) - .map_err(|_| host::__WASI_ENOTCAPABLE) - .and_then(|path| path.to_str().map(String::from).ok_or(host::__WASI_EILSEQ)) + .map_err(|_| Error::ENOTCAPABLE) + .and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ)) } Err(e) => match e.raw_os_error() { Some(e) => { @@ -101,20 +99,20 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result { // strip "/" and check if exists let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?; if path.exists() && !path.is_dir() { - Err(host::__WASI_ENOTDIR) + Err(Error::ENOTDIR) } else { - Err(host::__WASI_ENOENT) + Err(Error::ENOENT) } } else { - Err(host::__WASI_ENOENT) + Err(Error::ENOENT) } } - e => Err(host_impl::errno_from_win(e)), + e => Err(e.into()), } } None => { log::debug!("Inconvertible OS error: {}", e); - Err(host::__WASI_EIO) + Err(Error::EIO) } }, } @@ -135,10 +133,10 @@ pub(crate) fn concatenate>(dirfd: &File, path: P) -> Result Result { - File::open("NUL").map_err(errno_from_ioerror) + File::open("NUL").map_err(Into::into) } pub fn preopen_dir>(path: P) -> Result { @@ -25,5 +24,5 @@ pub fn preopen_dir>(path: P) -> Result { .read(true) .attributes(FILE_FLAG_BACKUP_SEMANTICS) .open(path) - .map_err(errno_from_ioerror) + .map_err(Into::into) }