diff --git a/crates/wasi-common/src/ctx.rs b/crates/wasi-common/src/ctx.rs index 981007c515..899e272c0f 100644 --- a/crates/wasi-common/src/ctx.rs +++ b/crates/wasi-common/src/ctx.rs @@ -1,16 +1,44 @@ use crate::fdentry::{Descriptor, FdEntry}; use crate::sys::fdentry_impl::OsHandle; use crate::virtfs::{VirtualDir, VirtualDirEntry}; -use crate::{wasi, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; use std::borrow::Borrow; use std::collections::HashMap; -use std::env; -use std::ffi::{CString, OsString}; +use std::ffi::{self, CString, OsString}; use std::fs::File; use std::path::{Path, PathBuf}; +use std::{env, io, string}; + +/// Possible errors when `WasiCtxBuilder` fails building +/// `WasiCtx`. +#[derive(Debug, thiserror::Error)] +pub enum WasiCtxBuilderError { + /// General I/O error was encountered. + #[error("general I/O error encountered: {0}")] + Io(#[from] io::Error), + /// Provided sequence of bytes was not a valid UTF-8. + #[error("provided sequence is not valid UTF-8: {0}")] + InvalidUtf8(#[from] string::FromUtf8Error), + /// Provided sequence of bytes was not a valid UTF-16. + /// + /// This error is expected to only occur on Windows hosts. + #[error("provided sequence is not valid UTF-16: {0}")] + InvalidUtf16(#[from] string::FromUtf16Error), + /// Provided sequence of bytes contained an unexpected NUL byte. + #[error("provided sequence contained an unexpected NUL byte")] + UnexpectedNul(#[from] ffi::NulError), + /// Provided `File` is not a directory. + #[error("preopened directory path {} is not a directory", .0.display())] + NotADirectory(PathBuf), + /// `WasiCtx` has too many opened files. + #[error("context object has too many opened files")] + TooManyFilesOpen, +} + +type WasiCtxBuilderResult = std::result::Result; enum PendingFdEntry { - Thunk(fn() -> Result), + Thunk(fn() -> io::Result), File(File), } @@ -20,7 +48,7 @@ impl std::fmt::Debug for PendingFdEntry { Self::Thunk(f) => write!( fmt, "PendingFdEntry::Thunk({:p})", - f as *const fn() -> Result + f as *const fn() -> io::Result ), Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f), } @@ -46,17 +74,29 @@ impl From for PendingCString { } impl PendingCString { - fn into_string(self) -> Result { - match self { - Self::Bytes(v) => String::from_utf8(v).map_err(|_| Error::EILSEQ), - Self::OsString(s) => s.into_string().map_err(|_| Error::EILSEQ), - } + fn into_string(self) -> WasiCtxBuilderResult { + let res = match self { + Self::Bytes(v) => String::from_utf8(v)?, + #[cfg(unix)] + Self::OsString(s) => { + use std::os::unix::ffi::OsStringExt; + String::from_utf8(s.into_vec())? + } + #[cfg(windows)] + Self::OsString(s) => { + use std::os::windows::ffi::OsStrExt; + let bytes: Vec = s.encode_wide().collect(); + String::from_utf16(&bytes)? + } + }; + Ok(res) } - /// Create a `CString` containing valid UTF-8, or fail with `Error::EILSEQ`. - fn into_utf8_cstring(self) -> Result { - self.into_string() - .and_then(|s| CString::new(s).map_err(|_| Error::EILSEQ)) + /// Create a `CString` containing valid UTF-8. + fn into_utf8_cstring(self) -> WasiCtxBuilderResult { + let s = self.into_string()?; + let s = CString::new(s)?; + Ok(s) } } @@ -87,8 +127,7 @@ impl WasiCtxBuilder { /// Add arguments to the command-line arguments list. /// - /// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail - /// with `Error::EILSEQ`. + /// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail. pub fn args>(&mut self, args: impl IntoIterator) -> &mut Self { self.args .as_mut() @@ -99,8 +138,7 @@ impl WasiCtxBuilder { /// Add an argument to the command-line arguments list. /// - /// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail - /// with `Error::EILSEQ`. + /// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail. pub fn arg>(&mut self, arg: S) -> &mut Self { self.args .as_mut() @@ -112,7 +150,7 @@ impl WasiCtxBuilder { /// Inherit the command-line arguments from the host process. /// /// If any arguments from the host process contain invalid UTF-8, `WasiCtxBuilder::build()` will - /// fail with `Error::EILSEQ`. + /// fail. pub fn inherit_args(&mut self) -> &mut Self { let args = self.args.as_mut().unwrap(); args.clear(); @@ -159,8 +197,7 @@ impl WasiCtxBuilder { /// Inherit the environment variables from the host process. /// /// If any environment variables from the host process contain invalid Unicode (UTF-16 for - /// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail with - /// `Error::EILSEQ`. + /// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail. pub fn inherit_env(&mut self) -> &mut Self { let env = self.env.as_mut().unwrap(); env.clear(); @@ -171,7 +208,7 @@ impl WasiCtxBuilder { /// Add an entry to the environment. /// /// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else - /// `WasiCtxBuilder::build()` will fail with `Error::EILSEQ`. + /// `WasiCtxBuilder::build()` will fail. pub fn env>(&mut self, k: S, v: S) -> &mut Self { self.env .as_mut() @@ -183,7 +220,7 @@ impl WasiCtxBuilder { /// Add entries to the environment. /// /// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else - /// `WasiCtxBuilder::build()` will fail with `Error::EILSEQ`. + /// `WasiCtxBuilder::build()` will fail. pub fn envs, T: Borrow<(S, S)>>( &mut self, envs: impl IntoIterator, @@ -270,22 +307,22 @@ impl WasiCtxBuilder { /// Build a `WasiCtx`, consuming this `WasiCtxBuilder`. /// /// If any of the arguments or environment variables in this builder cannot be converted into - /// `CString`s, either due to NUL bytes or Unicode conversions, this returns `Error::EILSEQ`. - pub fn build(&mut self) -> Result { + /// `CString`s, either due to NUL bytes or Unicode conversions, this will fail. + pub fn build(&mut self) -> WasiCtxBuilderResult { // Process arguments and environment variables into `CString`s, failing quickly if they // contain any NUL bytes, or if conversion from `OsString` fails. let args = self .args .take() - .ok_or(Error::EINVAL)? + .unwrap() .into_iter() .map(|arg| arg.into_utf8_cstring()) - .collect::>>()?; + .collect::>>()?; let env = self .env .take() - .ok_or(Error::EINVAL)? + .unwrap() .into_iter() .map(|(k, v)| { k.into_string().and_then(|mut pair| { @@ -294,15 +331,16 @@ impl WasiCtxBuilder { pair.push_str(v.as_str()); // We have valid UTF-8, but the keys and values have not yet been checked // for NULs, so we do a final check here. - CString::new(pair).map_err(|_| Error::EILSEQ) + let s = CString::new(pair)?; + Ok(s) }) }) }) - .collect::>>()?; + .collect::>>()?; let mut fds: HashMap = HashMap::new(); // Populate the non-preopen fds. - for (fd, pending) in self.fds.take().ok_or(Error::EINVAL)? { + for (fd, pending) in self.fds.take().unwrap() { log::debug!("WasiCtx inserting ({:?}, {:?})", fd, pending); match pending { PendingFdEntry::Thunk(f) => { @@ -317,20 +355,22 @@ impl WasiCtxBuilder { // so we start from there. This variable is initially 2, though, because the loop // immediately does the increment and check for overflow. let mut preopen_fd: wasi::__wasi_fd_t = 2; - for (guest_path, dir) in self.preopens.take().ok_or(Error::EINVAL)? { + for (guest_path, dir) in self.preopens.take().unwrap() { // We do the increment at the beginning of the loop body, so that we don't overflow // unnecessarily if we have exactly the maximum number of file descriptors. - preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?; + preopen_fd = preopen_fd + .checked_add(1) + .ok_or(WasiCtxBuilderError::TooManyFilesOpen)?; match &dir { Descriptor::OsHandle(handle) => { if !handle.metadata()?.is_dir() { - return Err(Error::EBADF); + return Err(WasiCtxBuilderError::NotADirectory(guest_path)); } } Descriptor::VirtualFile(virt) => { if virt.get_file_type() != wasi::__WASI_FILETYPE_DIRECTORY { - return Err(Error::EBADF); + return Err(WasiCtxBuilderError::NotADirectory(guest_path)); } } Descriptor::Stdin | Descriptor::Stdout | Descriptor::Stderr => { @@ -341,7 +381,9 @@ impl WasiCtxBuilder { // We don't currently allow setting file descriptors other than 0-2, but this will avoid // collisions if we restore that functionality in the future. while fds.contains_key(&preopen_fd) { - preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?; + preopen_fd = preopen_fd + .checked_add(1) + .ok_or(WasiCtxBuilderError::TooManyFilesOpen)?; } let mut fe = FdEntry::from(dir)?; fe.preopen_path = Some(guest_path); @@ -369,7 +411,7 @@ impl WasiCtx { /// - Environment variables are inherited from the host process. /// /// To override these behaviors, use `WasiCtxBuilder`. - pub fn new>(args: impl IntoIterator) -> Result { + pub fn new>(args: impl IntoIterator) -> WasiCtxBuilderResult { WasiCtxBuilder::new() .args(args) .inherit_stdio() @@ -383,30 +425,30 @@ impl WasiCtx { } /// Get an immutable `FdEntry` corresponding to the specified raw WASI `fd`. - pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> Result<&FdEntry> { - self.fds.get(&fd).ok_or(Error::EBADF) + pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> WasiResult<&FdEntry> { + self.fds.get(&fd).ok_or(WasiError::EBADF) } /// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`. pub(crate) unsafe fn get_fd_entry_mut( &mut self, fd: wasi::__wasi_fd_t, - ) -> Result<&mut FdEntry> { - self.fds.get_mut(&fd).ok_or(Error::EBADF) + ) -> WasiResult<&mut FdEntry> { + self.fds.get_mut(&fd).ok_or(WasiError::EBADF) } /// Insert the specified `FdEntry` into the `WasiCtx` object. /// /// The `FdEntry` will automatically get another free raw WASI `fd` assigned. Note that /// the two subsequent free raw WASI `fd`s do not have to be stored contiguously. - pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> Result { + pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> WasiResult { // Never insert where stdio handles are expected to be. let mut fd = 3; while self.fds.contains_key(&fd) { if let Some(next_fd) = fd.checked_add(1) { fd = next_fd; } else { - return Err(Error::EMFILE); + return Err(WasiError::EMFILE); } } self.fds.insert(fd, fe); @@ -424,7 +466,7 @@ impl WasiCtx { } /// Remove `FdEntry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object. - pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> Result { - self.fds.remove(&fd).ok_or(Error::EBADF) + pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult { + self.fds.remove(&fd).ok_or(WasiError::EBADF) } } diff --git a/crates/wasi-common/src/error.rs b/crates/wasi-common/src/error.rs deleted file mode 100644 index 3da299f91b..0000000000 --- a/crates/wasi-common/src/error.rs +++ /dev/null @@ -1,249 +0,0 @@ -// Due to https://github.com/rust-lang/rust/issues/64247 -#![allow(clippy::use_self)] -use crate::wasi; -use std::convert::Infallible; -use std::num::TryFromIntError; -use std::{ffi, str}; -use thiserror::Error; - -#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)] -#[repr(u16)] -#[error("{:?} ({})", self, wasi::strerror(*self as wasi::__wasi_errno_t))] -pub enum WasiError { - ESUCCESS = wasi::__WASI_ERRNO_SUCCESS, - E2BIG = wasi::__WASI_ERRNO_2BIG, - EACCES = wasi::__WASI_ERRNO_ACCES, - EADDRINUSE = wasi::__WASI_ERRNO_ADDRINUSE, - EADDRNOTAVAIL = wasi::__WASI_ERRNO_ADDRNOTAVAIL, - EAFNOSUPPORT = wasi::__WASI_ERRNO_AFNOSUPPORT, - EAGAIN = wasi::__WASI_ERRNO_AGAIN, - EALREADY = wasi::__WASI_ERRNO_ALREADY, - EBADF = wasi::__WASI_ERRNO_BADF, - EBADMSG = wasi::__WASI_ERRNO_BADMSG, - EBUSY = wasi::__WASI_ERRNO_BUSY, - ECANCELED = wasi::__WASI_ERRNO_CANCELED, - ECHILD = wasi::__WASI_ERRNO_CHILD, - ECONNABORTED = wasi::__WASI_ERRNO_CONNABORTED, - ECONNREFUSED = wasi::__WASI_ERRNO_CONNREFUSED, - ECONNRESET = wasi::__WASI_ERRNO_CONNRESET, - EDEADLK = wasi::__WASI_ERRNO_DEADLK, - EDESTADDRREQ = wasi::__WASI_ERRNO_DESTADDRREQ, - EDOM = wasi::__WASI_ERRNO_DOM, - EDQUOT = wasi::__WASI_ERRNO_DQUOT, - EEXIST = wasi::__WASI_ERRNO_EXIST, - EFAULT = wasi::__WASI_ERRNO_FAULT, - EFBIG = wasi::__WASI_ERRNO_FBIG, - EHOSTUNREACH = wasi::__WASI_ERRNO_HOSTUNREACH, - EIDRM = wasi::__WASI_ERRNO_IDRM, - EILSEQ = wasi::__WASI_ERRNO_ILSEQ, - EINPROGRESS = wasi::__WASI_ERRNO_INPROGRESS, - EINTR = wasi::__WASI_ERRNO_INTR, - EINVAL = wasi::__WASI_ERRNO_INVAL, - EIO = wasi::__WASI_ERRNO_IO, - EISCONN = wasi::__WASI_ERRNO_ISCONN, - EISDIR = wasi::__WASI_ERRNO_ISDIR, - ELOOP = wasi::__WASI_ERRNO_LOOP, - EMFILE = wasi::__WASI_ERRNO_MFILE, - EMLINK = wasi::__WASI_ERRNO_MLINK, - EMSGSIZE = wasi::__WASI_ERRNO_MSGSIZE, - EMULTIHOP = wasi::__WASI_ERRNO_MULTIHOP, - ENAMETOOLONG = wasi::__WASI_ERRNO_NAMETOOLONG, - ENETDOWN = wasi::__WASI_ERRNO_NETDOWN, - ENETRESET = wasi::__WASI_ERRNO_NETRESET, - ENETUNREACH = wasi::__WASI_ERRNO_NETUNREACH, - ENFILE = wasi::__WASI_ERRNO_NFILE, - ENOBUFS = wasi::__WASI_ERRNO_NOBUFS, - ENODEV = wasi::__WASI_ERRNO_NODEV, - ENOENT = wasi::__WASI_ERRNO_NOENT, - ENOEXEC = wasi::__WASI_ERRNO_NOEXEC, - ENOLCK = wasi::__WASI_ERRNO_NOLCK, - ENOLINK = wasi::__WASI_ERRNO_NOLINK, - ENOMEM = wasi::__WASI_ERRNO_NOMEM, - ENOMSG = wasi::__WASI_ERRNO_NOMSG, - ENOPROTOOPT = wasi::__WASI_ERRNO_NOPROTOOPT, - ENOSPC = wasi::__WASI_ERRNO_NOSPC, - ENOSYS = wasi::__WASI_ERRNO_NOSYS, - ENOTCONN = wasi::__WASI_ERRNO_NOTCONN, - ENOTDIR = wasi::__WASI_ERRNO_NOTDIR, - ENOTEMPTY = wasi::__WASI_ERRNO_NOTEMPTY, - ENOTRECOVERABLE = wasi::__WASI_ERRNO_NOTRECOVERABLE, - ENOTSOCK = wasi::__WASI_ERRNO_NOTSOCK, - ENOTSUP = wasi::__WASI_ERRNO_NOTSUP, - ENOTTY = wasi::__WASI_ERRNO_NOTTY, - ENXIO = wasi::__WASI_ERRNO_NXIO, - EOVERFLOW = wasi::__WASI_ERRNO_OVERFLOW, - EOWNERDEAD = wasi::__WASI_ERRNO_OWNERDEAD, - EPERM = wasi::__WASI_ERRNO_PERM, - EPIPE = wasi::__WASI_ERRNO_PIPE, - EPROTO = wasi::__WASI_ERRNO_PROTO, - EPROTONOSUPPORT = wasi::__WASI_ERRNO_PROTONOSUPPORT, - EPROTOTYPE = wasi::__WASI_ERRNO_PROTOTYPE, - ERANGE = wasi::__WASI_ERRNO_RANGE, - EROFS = wasi::__WASI_ERRNO_ROFS, - ESPIPE = wasi::__WASI_ERRNO_SPIPE, - ESRCH = wasi::__WASI_ERRNO_SRCH, - ESTALE = wasi::__WASI_ERRNO_STALE, - ETIMEDOUT = wasi::__WASI_ERRNO_TIMEDOUT, - ETXTBSY = wasi::__WASI_ERRNO_TXTBSY, - EXDEV = wasi::__WASI_ERRNO_XDEV, - ENOTCAPABLE = wasi::__WASI_ERRNO_NOTCAPABLE, -} - -impl WasiError { - pub fn as_raw_errno(self) -> wasi::__wasi_errno_t { - self as wasi::__wasi_errno_t - } -} - -#[derive(Debug, Error)] -pub enum Error { - #[error("WASI error code: {0}")] - Wasi(#[from] WasiError), - #[error("IO error: {0}")] - Io(#[from] std::io::Error), -} - -impl From for Error { - fn from(_: TryFromIntError) -> Self { - Self::EOVERFLOW - } -} - -impl From for Error { - fn from(_: Infallible) -> Self { - unreachable!() - } -} - -impl From for Error { - fn from(_: str::Utf8Error) -> Self { - Self::EILSEQ - } -} - -impl From for Error { - fn from(_: ffi::NulError) -> Self { - Self::EILSEQ - } -} - -impl From<&ffi::NulError> for Error { - fn from(_: &ffi::NulError) -> Self { - Self::EILSEQ - } -} - -impl Error { - pub(crate) fn as_wasi_error(&self) -> WasiError { - match self { - Self::Wasi(err) => *err, - Self::Io(err) => { - let err = match err.raw_os_error() { - Some(code) => Self::from_raw_os_error(code), - None => { - log::debug!("Inconvertible OS error: {}", err); - Self::EIO - } - }; - err.as_wasi_error() - } - } - } - - 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); -} - -pub(crate) trait FromRawOsError { - fn from_raw_os_error(code: i32) -> Self; -} - -pub(crate) type Result = std::result::Result; - -pub(crate) trait AsWasiError { - fn as_wasi_error(&self) -> WasiError; -} - -impl AsWasiError for Result { - fn as_wasi_error(&self) -> WasiError { - self.as_ref() - .err() - .unwrap_or(&Error::ESUCCESS) - .as_wasi_error() - } -} diff --git a/crates/wasi-common/src/fdentry.rs b/crates/wasi-common/src/fdentry.rs index c2c9a719da..56ab57e5e7 100644 --- a/crates/wasi-common/src/fdentry.rs +++ b/crates/wasi-common/src/fdentry.rs @@ -3,7 +3,7 @@ use crate::sys::fdentry_impl::{ descriptor_as_oshandle, determine_type_and_access_rights, OsHandle, }; use crate::virtfs::VirtualFile; -use crate::{wasi, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; @@ -56,22 +56,22 @@ impl Descriptor { /// Return a reference to the `OsHandle` or `VirtualFile` treating it as an /// actual file/dir, and allowing operations which require an actual file and /// not just a stream or socket file descriptor. - pub(crate) fn as_file<'descriptor>(&'descriptor self) -> Result<&'descriptor Descriptor> { + pub(crate) fn as_file<'descriptor>(&'descriptor self) -> WasiResult<&'descriptor Descriptor> { match self { Self::OsHandle(_) => Ok(self), Self::VirtualFile(_) => Ok(self), - _ => Err(Error::EBADF), + _ => Err(WasiError::EBADF), } } /// Like `as_file`, but return a mutable reference. pub(crate) fn as_file_mut<'descriptor>( &'descriptor mut self, - ) -> Result<&'descriptor mut Descriptor> { + ) -> WasiResult<&'descriptor mut Descriptor> { match self { Self::OsHandle(_) => Ok(self), Self::VirtualFile(_) => Ok(self), - _ => Err(Error::EBADF), + _ => Err(WasiError::EBADF), } } @@ -100,7 +100,7 @@ pub(crate) struct FdEntry { } impl FdEntry { - pub(crate) fn from(file: Descriptor) -> Result { + pub(crate) fn from(file: Descriptor) -> io::Result { match file { Descriptor::OsHandle(handle) => unsafe { determine_type_and_access_rights(&handle) } .map(|(file_type, rights_base, rights_inheriting)| Self { @@ -129,7 +129,7 @@ impl FdEntry { } } - pub(crate) fn duplicate_stdin() -> Result { + pub(crate) fn duplicate_stdin() -> io::Result { unsafe { determine_type_and_access_rights(&io::stdin()) }.map( |(file_type, rights_base, rights_inheriting)| Self { file_type, @@ -141,7 +141,7 @@ impl FdEntry { ) } - pub(crate) fn duplicate_stdout() -> Result { + pub(crate) fn duplicate_stdout() -> io::Result { unsafe { determine_type_and_access_rights(&io::stdout()) }.map( |(file_type, rights_base, rights_inheriting)| Self { file_type, @@ -153,7 +153,7 @@ impl FdEntry { ) } - pub(crate) fn duplicate_stderr() -> Result { + pub(crate) fn duplicate_stderr() -> io::Result { unsafe { determine_type_and_access_rights(&io::stderr()) }.map( |(file_type, rights_base, rights_inheriting)| Self { file_type, @@ -165,7 +165,7 @@ impl FdEntry { ) } - pub(crate) fn null() -> Result { + pub(crate) fn null() -> io::Result { Self::from(OsHandle::from(dev_null()?).into()) } @@ -175,12 +175,12 @@ impl FdEntry { /// The `FdEntry` can only be converted into a valid `Descriptor` object if /// the specified set of base rights `rights_base`, and inheriting rights `rights_inheriting` /// is a subset of rights attached to this `FdEntry`. The check is performed using - /// `FdEntry::validate_rights` method. If the check fails, `Error::ENOTCAPABLE` is returned. + /// `FdEntry::validate_rights` method. If the check fails, `WasiError::ENOTCAPABLE` is returned. pub(crate) fn as_descriptor( &self, rights_base: wasi::__wasi_rights_t, rights_inheriting: wasi::__wasi_rights_t, - ) -> Result<&Descriptor> { + ) -> WasiResult<&Descriptor> { self.validate_rights(rights_base, rights_inheriting)?; Ok(&self.descriptor) } @@ -191,12 +191,12 @@ impl FdEntry { /// The `FdEntry` can only be converted into a valid `Descriptor` object if /// the specified set of base rights `rights_base`, and inheriting rights `rights_inheriting` /// is a subset of rights attached to this `FdEntry`. The check is performed using - /// `FdEntry::validate_rights` method. If the check fails, `Error::ENOTCAPABLE` is returned. + /// `FdEntry::validate_rights` method. If the check fails, `WasiError::ENOTCAPABLE` is returned. pub(crate) fn as_descriptor_mut( &mut self, rights_base: wasi::__wasi_rights_t, rights_inheriting: wasi::__wasi_rights_t, - ) -> Result<&mut Descriptor> { + ) -> WasiResult<&mut Descriptor> { self.validate_rights(rights_base, rights_inheriting)?; Ok(&mut self.descriptor) } @@ -205,12 +205,12 @@ impl FdEntry { /// inheriting rights `rights_inheriting`; i.e., if rights attached to this `FdEntry` object /// are a superset. /// - /// Upon unsuccessful check, `Error::ENOTCAPABLE` is returned. + /// Upon unsuccessful check, `WasiError::ENOTCAPABLE` is returned. fn validate_rights( &self, rights_base: wasi::__wasi_rights_t, rights_inheriting: wasi::__wasi_rights_t, - ) -> Result<()> { + ) -> WasiResult<()> { let missing_base = !self.rights_base & rights_base; let missing_inheriting = !self.rights_inheriting & rights_inheriting; if missing_base != 0 || missing_inheriting != 0 { @@ -226,7 +226,7 @@ impl FdEntry { missing_base, missing_inheriting ); - Err(Error::ENOTCAPABLE) + Err(WasiError::ENOTCAPABLE) } else { Ok(()) } diff --git a/crates/wasi-common/src/fs/file.rs b/crates/wasi-common/src/fs/file.rs index f87c6acfb9..d8b0dbf717 100644 --- a/crates/wasi-common/src/fs/file.rs +++ b/crates/wasi-common/src/fs/file.rs @@ -1,5 +1,6 @@ use crate::fs::Metadata; -use crate::{host, hostcalls, hostcalls_impl, wasi, Result, WasiCtx}; +use crate::wasi::{self, WasiResult}; +use crate::{host, hostcalls, hostcalls_impl, WasiCtx}; use std::io; /// A reference to an open file on the filesystem. @@ -34,7 +35,7 @@ impl<'ctx> File<'ctx> { /// 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) -> Result<()> { + pub fn sync_all(&self) -> WasiResult<()> { unsafe { hostcalls_impl::fd_sync(self.ctx, &mut [], self.fd)?; } @@ -47,7 +48,7 @@ impl<'ctx> File<'ctx> { /// 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) -> Result<()> { + pub fn sync_data(&self) -> WasiResult<()> { unsafe { hostcalls_impl::fd_datasync(self.ctx, &mut [], self.fd)?; } @@ -60,7 +61,7 @@ impl<'ctx> File<'ctx> { /// 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) -> Result<()> { + pub fn set_len(&self, size: u64) -> WasiResult<()> { unsafe { hostcalls_impl::fd_filestat_set_size(self.ctx, &mut [], self.fd, size)?; } @@ -72,7 +73,7 @@ impl<'ctx> File<'ctx> { /// 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) -> Result { + pub fn metadata(&self) -> WasiResult { Ok(Metadata {}) } } diff --git a/crates/wasi-common/src/helpers.rs b/crates/wasi-common/src/helpers.rs index f176b8d1fe..4fb365882b 100644 --- a/crates/wasi-common/src/helpers.rs +++ b/crates/wasi-common/src/helpers.rs @@ -1,10 +1,11 @@ -use crate::{Error, Result}; +use crate::wasi::WasiResult; use std::str; /// Creates not-owned WASI path from byte slice. /// /// NB WASI spec requires bytes to be valid UTF-8. Otherwise, /// `__WASI_ERRNO_ILSEQ` error is returned. -pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> { - str::from_utf8(s).map_err(|_| Error::EILSEQ) +pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> WasiResult<&'a str> { + let s = str::from_utf8(s)?; + Ok(s) } diff --git a/crates/wasi-common/src/host.rs b/crates/wasi-common/src/host.rs index 47221e2763..56598b17a2 100644 --- a/crates/wasi-common/src/host.rs +++ b/crates/wasi-common/src/host.rs @@ -5,7 +5,6 @@ #![allow(non_snake_case)] use crate::wasi::*; -use crate::{Error, Result}; use std::{convert::TryInto, io, mem, slice}; use wig::witx_host_types; @@ -67,11 +66,13 @@ pub struct Dirent { impl Dirent { /// Serialize the directory entry to the format define by `__wasi_fd_readdir`, /// so that the serialized entries can be concatenated by the implementation. - pub fn to_wasi_raw(&self) -> Result> { + pub fn to_wasi_raw(&self) -> WasiResult> { let name = self.name.as_bytes(); let namlen = name.len(); let dirent_size = mem::size_of::<__wasi_dirent_t>(); - let offset = dirent_size.checked_add(namlen).ok_or(Error::EOVERFLOW)?; + let offset = dirent_size + .checked_add(namlen) + .ok_or(WasiError::EOVERFLOW)?; let mut raw = Vec::::with_capacity(offset); raw.resize(offset, 0); diff --git a/crates/wasi-common/src/hostcalls_impl/fs.rs b/crates/wasi-common/src/hostcalls_impl/fs.rs index e10009242e..a9706d741b 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/hostcalls_impl/fs.rs @@ -8,7 +8,8 @@ use crate::memory::*; use crate::sandboxed_tty_writer::SandboxedTTYWriter; use crate::sys::hostcalls_impl::fs_helpers::path_open_rights; use crate::sys::{host_impl, hostcalls_impl}; -use crate::{helpers, host, wasi, wasi32, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; +use crate::{helpers, host, wasi32}; use filetime::{set_file_handle_times, FileTime}; use log::trace; use std::convert::TryInto; @@ -20,13 +21,13 @@ pub(crate) unsafe fn fd_close( wasi_ctx: &mut WasiCtx, _memory: &mut [u8], fd: wasi::__wasi_fd_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_close(fd={:?})", fd); if let Ok(fe) = wasi_ctx.get_fd_entry(fd) { // can't close preopened files if fe.preopen_path.is_some() { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } } @@ -38,7 +39,7 @@ pub(crate) unsafe fn fd_datasync( wasi_ctx: &WasiCtx, _memory: &mut [u8], fd: wasi::__wasi_fd_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_datasync(fd={:?})", fd); let file = wasi_ctx @@ -60,7 +61,7 @@ pub(crate) unsafe fn fd_pread( iovs_len: wasi32::size_t, offset: wasi::__wasi_filesize_t, nread: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_pread(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})", fd, @@ -78,7 +79,7 @@ pub(crate) unsafe fn fd_pread( let iovs = dec_iovec_slice(memory, iovs_ptr, iovs_len)?; if offset > i64::max_value() as u64 { - return Err(Error::EIO); + return Err(WasiError::EIO); } let buf_size = iovs .iter() @@ -90,7 +91,7 @@ pub(crate) unsafe fn fd_pread( cast_iovlen }) .fold(Some(0u32), |len, iov| len.and_then(|x| x.checked_add(iov))) - .ok_or(Error::EINVAL)?; + .ok_or(WasiError::EINVAL)?; let mut buf = vec![0; buf_size as usize]; let host_nread = match file { Descriptor::OsHandle(fd) => hostcalls_impl::fd_pread(&fd, &mut buf, offset)?, @@ -128,7 +129,7 @@ pub(crate) unsafe fn fd_pwrite( iovs_len: wasi32::size_t, offset: wasi::__wasi_filesize_t, nwritten: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_pwrite(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})", fd, @@ -148,7 +149,7 @@ pub(crate) unsafe fn fd_pwrite( let iovs = dec_ciovec_slice(memory, iovs_ptr, iovs_len)?; if offset > i64::max_value() as u64 { - return Err(Error::EIO); + return Err(WasiError::EIO); } let buf_size = iovs .iter() @@ -160,7 +161,7 @@ pub(crate) unsafe fn fd_pwrite( cast_iovlen }) .fold(Some(0u32), |len, iov| len.and_then(|x| x.checked_add(iov))) - .ok_or(Error::EINVAL)?; + .ok_or(WasiError::EINVAL)?; let mut buf = Vec::with_capacity(buf_size as usize); for iov in &iovs { buf.extend_from_slice(std::slice::from_raw_parts( @@ -190,7 +191,7 @@ pub(crate) unsafe fn fd_read( iovs_ptr: wasi32::uintptr_t, iovs_len: wasi32::size_t, nread: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_read(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nread={:#x?})", fd, @@ -212,7 +213,7 @@ pub(crate) unsafe fn fd_read( Descriptor::OsHandle(file) => file.read_vectored(&mut iovs).map_err(Into::into), Descriptor::VirtualFile(virt) => virt.read_vectored(&mut iovs), Descriptor::Stdin => io::stdin().read_vectored(&mut iovs).map_err(Into::into), - _ => return Err(Error::EBADF), + _ => return Err(WasiError::EBADF), }; let host_nread = maybe_host_nread?; @@ -227,11 +228,11 @@ pub(crate) unsafe fn fd_renumber( _memory: &mut [u8], from: wasi::__wasi_fd_t, to: wasi::__wasi_fd_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_renumber(from={:?}, to={:?})", from, to); if !wasi_ctx.contains_fd_entry(from) { - return Err(Error::EBADF); + return Err(WasiError::EBADF); } // Don't allow renumbering over a pre-opened resource. @@ -239,11 +240,11 @@ pub(crate) unsafe fn fd_renumber( // userspace is capable of removing entries from its tables as well. let from_fe = wasi_ctx.get_fd_entry(from)?; if from_fe.preopen_path.is_some() { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } if let Ok(to_fe) = wasi_ctx.get_fd_entry(to) { if to_fe.preopen_path.is_some() { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } } @@ -260,7 +261,7 @@ pub(crate) unsafe fn fd_seek( offset: wasi::__wasi_filedelta_t, whence: wasi::__wasi_whence_t, newoffset: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})", fd, @@ -283,7 +284,7 @@ pub(crate) unsafe fn fd_seek( wasi::__WASI_WHENCE_CUR => SeekFrom::Current(offset), wasi::__WASI_WHENCE_END => SeekFrom::End(offset), wasi::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64), - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }; let host_newoffset = match file { Descriptor::OsHandle(fd) => fd.seek(pos)?, @@ -305,7 +306,7 @@ pub(crate) unsafe fn fd_tell( memory: &mut [u8], fd: wasi::__wasi_fd_t, newoffset: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset); let file = wasi_ctx @@ -333,7 +334,7 @@ pub(crate) unsafe fn fd_fdstat_get( memory: &mut [u8], fd: wasi::__wasi_fd_t, fdstat_ptr: wasi32::uintptr_t, // *mut wasi::__wasi_fdstat_t -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr); let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?; @@ -361,7 +362,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags( _memory: &mut [u8], fd: wasi::__wasi_fd_t, fdflags: wasi::__wasi_fdflags_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags); let descriptor = wasi_ctx @@ -400,7 +401,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights( fd: wasi::__wasi_fd_t, fs_rights_base: wasi::__wasi_rights_t, fs_rights_inheriting: wasi::__wasi_rights_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})", fd, @@ -412,7 +413,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights( if fe.rights_base & fs_rights_base != fs_rights_base || fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting { - return Err(Error::ENOTCAPABLE); + return Err(WasiError::ENOTCAPABLE); } fe.rights_base = fs_rights_base; fe.rights_inheriting = fs_rights_inheriting; @@ -424,7 +425,7 @@ pub(crate) unsafe fn fd_sync( wasi_ctx: &WasiCtx, _memory: &mut [u8], fd: wasi::__wasi_fd_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_sync(fd={:?})", fd); let file = wasi_ctx @@ -449,7 +450,7 @@ pub(crate) unsafe fn fd_write( iovs_ptr: wasi32::uintptr_t, iovs_len: wasi32::size_t, nwritten: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_write(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nwritten={:#x?})", fd, @@ -480,7 +481,7 @@ pub(crate) unsafe fn fd_write( virt.write_vectored(&iovs)? } } - Descriptor::Stdin => return Err(Error::EBADF), + Descriptor::Stdin => return Err(WasiError::EBADF), Descriptor::Stdout => { // lock for the duration of the scope let stdout = io::stdout(); @@ -512,7 +513,7 @@ pub(crate) unsafe fn fd_advise( offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, advice: wasi::__wasi_advice_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_advise(fd={:?}, offset={}, len={}, advice={:?})", fd, @@ -543,7 +544,7 @@ pub(crate) unsafe fn fd_allocate( fd: wasi::__wasi_fd_t, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len); let file = wasi_ctx @@ -556,10 +557,10 @@ pub(crate) unsafe fn fd_allocate( let metadata = fd.metadata()?; let current_size = metadata.len(); - let wanted_size = offset.checked_add(len).ok_or(Error::E2BIG)?; + let wanted_size = offset.checked_add(len).ok_or(WasiError::E2BIG)?; // This check will be unnecessary when rust-lang/rust#63326 is fixed if wanted_size > i64::max_value() as u64 { - return Err(Error::E2BIG); + return Err(WasiError::E2BIG); } if wanted_size > current_size { @@ -583,7 +584,7 @@ pub(crate) unsafe fn path_create_directory( dirfd: wasi::__wasi_fd_t, path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_create_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})", dirfd, @@ -612,7 +613,7 @@ pub(crate) unsafe fn path_link( new_dirfd: wasi::__wasi_fd_t, new_path_ptr: wasi32::uintptr_t, new_path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_link(old_dirfd={:?}, old_flags={:?}, old_path_ptr={:#x?}, old_path_len={}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})", old_dirfd, @@ -664,7 +665,7 @@ pub(crate) unsafe fn path_open( fs_rights_inheriting: wasi::__wasi_rights_t, fs_flags: wasi::__wasi_fdflags_t, fd_out_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_open(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={:?}, oflags={:#x?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?}, fs_flags={:#x?}, fd_out_ptr={:#x?})", dirfd, @@ -739,7 +740,7 @@ pub(crate) unsafe fn path_readlink( buf_ptr: wasi32::uintptr_t, buf_len: wasi32::size_t, buf_used: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_readlink(dirfd={:?}, path_ptr={:#x?}, path_len={:?}, buf_ptr={:#x?}, buf_len={}, buf_used={:#x?})", dirfd, @@ -783,7 +784,7 @@ pub(crate) unsafe fn path_rename( new_dirfd: wasi::__wasi_fd_t, new_path_ptr: wasi32::uintptr_t, new_path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_rename(old_dirfd={:?}, old_path_ptr={:#x?}, old_path_len={:?}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={:?})", old_dirfd, @@ -838,7 +839,7 @@ pub(crate) unsafe fn fd_filestat_get( memory: &mut [u8], fd: wasi::__wasi_fd_t, filestat_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_filestat_get(fd={:?}, filestat_ptr={:#x?})", fd, @@ -871,7 +872,7 @@ pub(crate) unsafe fn fd_filestat_set_times( st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fst_flags={:#x?})", fd, @@ -893,14 +894,14 @@ pub(crate) fn fd_filestat_set_times_impl( st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { let set_atim = fst_flags & wasi::__WASI_FSTFLAGS_ATIM != 0; let set_atim_now = fst_flags & wasi::__WASI_FSTFLAGS_ATIM_NOW != 0; let set_mtim = fst_flags & wasi::__WASI_FSTFLAGS_MTIM != 0; let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0; if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } let atim = if set_atim { let time = UNIX_EPOCH + Duration::from_nanos(st_atim); @@ -937,7 +938,7 @@ pub(crate) unsafe fn fd_filestat_set_size( _memory: &mut [u8], fd: wasi::__wasi_fd_t, st_size: wasi::__wasi_filesize_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size); let file = wasi_ctx @@ -947,7 +948,7 @@ pub(crate) unsafe fn fd_filestat_set_size( // This check will be unnecessary when rust-lang/rust#63326 is fixed if st_size > i64::max_value() as u64 { - return Err(Error::E2BIG); + return Err(WasiError::E2BIG); } match file { Descriptor::OsHandle(fd) => fd.set_len(st_size).map_err(Into::into), @@ -968,7 +969,7 @@ pub(crate) unsafe fn path_filestat_get( path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, filestat_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_filestat_get(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, filestat_ptr={:#x?})", dirfd, @@ -1013,7 +1014,7 @@ pub(crate) unsafe fn path_filestat_set_times( st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_filestat_set_times(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, st_atim={}, st_mtim={}, fst_flags={:#x?})", dirfd, @@ -1056,7 +1057,7 @@ pub(crate) unsafe fn path_symlink( dirfd: wasi::__wasi_fd_t, new_path_ptr: wasi32::uintptr_t, new_path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_symlink(old_path_ptr={:#x?}, old_path_len={}, dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})", old_path_ptr, @@ -1089,7 +1090,7 @@ pub(crate) unsafe fn path_unlink_file( dirfd: wasi::__wasi_fd_t, path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_unlink_file(dirfd={:?}, path_ptr={:#x?}, path_len={})", dirfd, @@ -1116,7 +1117,7 @@ pub(crate) unsafe fn path_remove_directory( dirfd: wasi::__wasi_fd_t, path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_remove_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})", dirfd, @@ -1151,7 +1152,7 @@ pub(crate) unsafe fn fd_prestat_get( memory: &mut [u8], fd: wasi::__wasi_fd_t, prestat_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_prestat_get(fd={:?}, prestat_ptr={:#x?})", fd, @@ -1160,9 +1161,9 @@ pub(crate) unsafe fn fd_prestat_get( // TODO: should we validate any rights here? let fe = wasi_ctx.get_fd_entry(fd)?; - let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?; + let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?; if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } let path = host_impl::path_from_host(po_path.as_os_str())?; @@ -1187,7 +1188,7 @@ pub(crate) unsafe fn fd_prestat_dir_name( fd: wasi::__wasi_fd_t, path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_prestat_dir_name(fd={:?}, path_ptr={:#x?}, path_len={})", fd, @@ -1197,15 +1198,15 @@ pub(crate) unsafe fn fd_prestat_dir_name( // TODO: should we validate any rights here? let fe = wasi_ctx.get_fd_entry(fd)?; - let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?; + let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?; if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } let path = host_impl::path_from_host(po_path.as_os_str())?; if path.len() > dec_usize(path_len) { - return Err(Error::ENAMETOOLONG); + return Err(WasiError::ENAMETOOLONG); } trace!(" | (path_ptr,path_len)='{}'", path); @@ -1221,7 +1222,7 @@ pub(crate) unsafe fn fd_readdir( buf_len: wasi32::size_t, cookie: wasi::__wasi_dircookie_t, buf_used: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})", fd, @@ -1241,10 +1242,10 @@ pub(crate) unsafe fn fd_readdir( trace!(" | (buf,buf_len)={:?}", host_buf); - fn copy_entities>>( + fn copy_entities>>( iter: T, mut host_buf: &mut [u8], - ) -> Result { + ) -> WasiResult { let mut host_bufused = 0; for dirent in iter { let dirent_raw = dirent?.to_wasi_raw()?; diff --git a/crates/wasi-common/src/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/hostcalls_impl/fs_helpers.rs index 0a72552e27..b1a8e555a2 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs_helpers.rs +++ b/crates/wasi-common/src/hostcalls_impl/fs_helpers.rs @@ -2,7 +2,8 @@ use crate::sys::fdentry_impl::OsHandle; use crate::sys::host_impl; use crate::sys::hostcalls_impl::fs_helpers::*; -use crate::{error::WasiError, fdentry::Descriptor, fdentry::FdEntry, wasi, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; +use crate::{fdentry::Descriptor, fdentry::FdEntry}; use std::path::{Component, Path}; #[derive(Debug)] @@ -20,7 +21,7 @@ impl PathGet { &self.path } - pub(crate) fn path_create_directory(self) -> Result<()> { + pub(crate) fn path_create_directory(self) -> WasiResult<()> { match &self.dirfd { Descriptor::OsHandle(file) => { crate::sys::hostcalls_impl::path_create_directory(&file, &self.path) @@ -38,7 +39,7 @@ impl PathGet { write: bool, oflags: u16, fs_flags: u16, - ) -> Result { + ) -> WasiResult { match &self.dirfd { Descriptor::OsHandle(_) => { crate::sys::hostcalls_impl::path_open(self, read, write, oflags, fs_flags) @@ -64,7 +65,7 @@ impl<'a, 'b> PathRef<'a, 'b> { PathRef { dirfd, path } } - fn open(&self) -> Result { + fn open(&self) -> WasiResult { match self.dirfd { Descriptor::OsHandle(file) => Ok(Descriptor::OsHandle(OsHandle::from(openat( &file, &self.path, @@ -84,7 +85,7 @@ impl<'a, 'b> PathRef<'a, 'b> { } } - fn readlink(&self) -> Result { + fn readlink(&self) -> WasiResult { match self.dirfd { Descriptor::OsHandle(file) => readlinkat(file, self.path), Descriptor::VirtualFile(virt) => { @@ -107,17 +108,17 @@ pub(crate) fn path_get( dirflags: wasi::__wasi_lookupflags_t, path: &str, needs_final_component: bool, -) -> Result { +) -> WasiResult { const MAX_SYMLINK_EXPANSIONS: usize = 128; if path.contains('\0') { // if contains NUL, return EILSEQ - return Err(Error::EILSEQ); + return Err(WasiError::EILSEQ); } if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY { // if `dirfd` doesn't refer to a directory, return `ENOTDIR`. - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } let dirfd = fe @@ -148,7 +149,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(Error::ENOENT), + None => return Err(WasiError::ENOENT), Some(p) => p, }; let tail = components.as_path(); @@ -166,18 +167,18 @@ pub(crate) fn path_get( match head { Component::Prefix(_) | Component::RootDir => { // path is absolute! - return Err(Error::ENOTCAPABLE); + return Err(WasiError::ENOTCAPABLE); } Component::CurDir => { // "." so skip } Component::ParentDir => { // ".." so pop a dir - let _ = dir_stack.pop().ok_or(Error::ENOTCAPABLE)?; + let _ = dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?; // we're not allowed to pop past the original directory if dir_stack.is_empty() { - return Err(Error::ENOTCAPABLE); + return Err(WasiError::ENOTCAPABLE); } } Component::Normal(head) => { @@ -188,14 +189,17 @@ pub(crate) fn path_get( } if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) { - match PathRef::new(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) - .open() + match PathRef::new( + dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?, + &head, + ) + .open() { Ok(new_dir) => { dir_stack.push(new_dir); } Err(e) => { - match e.as_wasi_error() { + match e { WasiError::ELOOP | WasiError::EMLINK | WasiError::ENOTDIR => @@ -204,14 +208,14 @@ pub(crate) fn path_get( { // attempt symlink expansion let mut link_path = PathRef::new( - dir_stack.last().ok_or(Error::ENOTCAPABLE)?, + dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?, &head, ) .readlink()?; symlink_expansions += 1; if symlink_expansions > MAX_SYMLINK_EXPANSIONS { - return Err(Error::ELOOP); + return Err(WasiError::ELOOP); } if head.ends_with('/') { @@ -238,13 +242,16 @@ pub(crate) fn path_get( { // if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt // symlink expansion - match PathRef::new(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) - .readlink() + match PathRef::new( + dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?, + &head, + ) + .readlink() { Ok(mut link_path) => { symlink_expansions += 1; if symlink_expansions > MAX_SYMLINK_EXPANSIONS { - return Err(Error::ELOOP); + return Err(WasiError::ELOOP); } if head.ends_with('/') { @@ -260,12 +267,12 @@ pub(crate) fn path_get( continue; } Err(e) => { - if e.as_wasi_error() != WasiError::EINVAL - && e.as_wasi_error() != WasiError::ENOENT + if e != WasiError::EINVAL + && e != WasiError::ENOENT // this handles the cases when trying to link to // a destination that already exists, and the target // path contains a slash - && e.as_wasi_error() != WasiError::ENOTDIR + && e != WasiError::ENOTDIR { return Err(e); } @@ -275,7 +282,7 @@ pub(crate) fn path_get( // not a symlink, so we're done; return Ok(PathGet { - dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?, + dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?, path: head, }); } @@ -285,7 +292,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(Error::ENOTCAPABLE)?, + dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?, path: String::from("."), }); } diff --git a/crates/wasi-common/src/hostcalls_impl/misc.rs b/crates/wasi-common/src/hostcalls_impl/misc.rs index ca3225e0a7..456beca24c 100644 --- a/crates/wasi-common/src/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/hostcalls_impl/misc.rs @@ -3,7 +3,8 @@ use crate::ctx::WasiCtx; use crate::fdentry::Descriptor; use crate::memory::*; use crate::sys::hostcalls_impl; -use crate::{wasi, wasi32, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; +use crate::wasi32; use log::{error, trace}; use std::convert::TryFrom; @@ -12,7 +13,7 @@ pub(crate) fn args_get( memory: &mut [u8], argv_ptr: wasi32::uintptr_t, argv_buf: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "args_get(argv_ptr={:#x?}, argv_buf={:#x?})", argv_ptr, @@ -31,7 +32,9 @@ pub(crate) fn args_get( argv.push(arg_ptr); let len = wasi32::uintptr_t::try_from(arg_bytes.len())?; - argv_buf_offset = argv_buf_offset.checked_add(len).ok_or(Error::EOVERFLOW)?; + argv_buf_offset = argv_buf_offset + .checked_add(len) + .ok_or(WasiError::EOVERFLOW)?; } enc_slice_of_wasi32_uintptr(memory, argv.as_slice(), argv_ptr) @@ -42,7 +45,7 @@ pub(crate) fn args_sizes_get( memory: &mut [u8], argc_ptr: wasi32::uintptr_t, argv_buf_size_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "args_sizes_get(argc_ptr={:#x?}, argv_buf_size_ptr={:#x?})", argc_ptr, @@ -70,7 +73,7 @@ pub(crate) fn environ_get( memory: &mut [u8], environ_ptr: wasi32::uintptr_t, environ_buf: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "environ_get(environ_ptr={:#x?}, environ_buf={:#x?})", environ_ptr, @@ -91,7 +94,7 @@ pub(crate) fn environ_get( let len = wasi32::uintptr_t::try_from(env_bytes.len())?; environ_buf_offset = environ_buf_offset .checked_add(len) - .ok_or(Error::EOVERFLOW)?; + .ok_or(WasiError::EOVERFLOW)?; } enc_slice_of_wasi32_uintptr(memory, environ.as_slice(), environ_ptr) @@ -102,7 +105,7 @@ pub(crate) fn environ_sizes_get( memory: &mut [u8], environ_count_ptr: wasi32::uintptr_t, environ_size_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "environ_sizes_get(environ_count_ptr={:#x?}, environ_size_ptr={:#x?})", environ_count_ptr, @@ -116,7 +119,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(Error::EOVERFLOW)?; + .ok_or(WasiError::EOVERFLOW)?; trace!(" | *environ_count_ptr={:?}", environ_count); @@ -132,14 +135,14 @@ pub(crate) fn random_get( memory: &mut [u8], buf_ptr: wasi32::uintptr_t, buf_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("random_get(buf_ptr={:#x?}, buf_len={:?})", buf_ptr, buf_len); let buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?; getrandom::getrandom(buf).map_err(|err| { error!("getrandom failure: {:?}", err); - Error::EIO + WasiError::EIO }) } @@ -148,7 +151,7 @@ pub(crate) fn clock_res_get( memory: &mut [u8], clock_id: wasi::__wasi_clockid_t, resolution_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "clock_res_get(clock_id={:?}, resolution_ptr={:#x?})", clock_id, @@ -168,7 +171,7 @@ pub(crate) fn clock_time_get( clock_id: wasi::__wasi_clockid_t, precision: wasi::__wasi_timestamp_t, time_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "clock_time_get(clock_id={:?}, precision={:?}, time_ptr={:#x?})", clock_id, @@ -183,7 +186,7 @@ pub(crate) fn clock_time_get( enc_timestamp_byref(memory, time_ptr, time) } -pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> Result<()> { +pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> WasiResult<()> { trace!("sched_yield()"); std::thread::yield_now(); @@ -198,7 +201,7 @@ pub(crate) fn poll_oneoff( output: wasi32::uintptr_t, nsubscriptions: wasi32::size_t, nevents: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "poll_oneoff(input={:#x?}, output={:#x?}, nsubscriptions={}, nevents={:#x?})", input, @@ -208,7 +211,7 @@ pub(crate) fn poll_oneoff( ); if u64::from(nsubscriptions) > wasi::__wasi_filesize_t::max_value() { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } enc_int_byref(memory, nevents, 0)?; @@ -222,7 +225,7 @@ pub(crate) fn poll_oneoff( // As mandated by the WASI spec: // > If `nsubscriptions` is 0, returns `errno::inval`. if subscriptions.is_empty() { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } for subscription in subscriptions { match subscription.u.tag { @@ -258,7 +261,7 @@ pub(crate) fn poll_oneoff( Err(err) => { let event = wasi::__wasi_event_t { userdata: subscription.userdata, - error: err.as_wasi_error().as_raw_errno(), + error: err.as_raw_errno(), r#type: wasi::__WASI_EVENTTYPE_FD_READ, fd_readwrite: wasi::__wasi_event_fd_readwrite_t { nbytes: 0, @@ -286,7 +289,7 @@ pub(crate) fn poll_oneoff( Err(err) => { let event = wasi::__wasi_event_t { userdata: subscription.userdata, - error: err.as_wasi_error().as_raw_errno(), + error: err.as_raw_errno(), r#type: wasi::__WASI_EVENTTYPE_FD_WRITE, fd_readwrite: wasi::__wasi_event_fd_readwrite_t { nbytes: 0, @@ -310,7 +313,7 @@ pub(crate) fn poll_oneoff( // events have been filtered out as errors in the code above. hostcalls_impl::poll_oneoff(timeout, fd_events, &mut events)?; - let events_count = u32::try_from(events.len()).map_err(|_| Error::EOVERFLOW)?; + let events_count = u32::try_from(events.len()).map_err(|_| WasiError::EOVERFLOW)?; enc_events(memory, output, nsubscriptions, events)?; @@ -319,7 +322,9 @@ pub(crate) fn poll_oneoff( enc_int_byref(memory, nevents, events_count) } -fn wasi_clock_to_relative_ns_delay(wasi_clock: wasi::__wasi_subscription_clock_t) -> Result { +fn wasi_clock_to_relative_ns_delay( + wasi_clock: wasi::__wasi_subscription_clock_t, +) -> WasiResult { use std::time::SystemTime; if wasi_clock.flags != wasi::__WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME { @@ -327,7 +332,7 @@ fn wasi_clock_to_relative_ns_delay(wasi_clock: wasi::__wasi_subscription_clock_t } let now: u128 = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .map_err(|_| Error::ENOTCAPABLE)? + .map_err(|_| WasiError::ENOTCAPABLE)? .as_nanos(); let deadline = u128::from(wasi_clock.timeout); Ok(deadline.saturating_sub(now)) @@ -357,6 +362,6 @@ pub(crate) fn proc_raise( _wasi_ctx: &WasiCtx, _memory: &mut [u8], _sig: wasi::__wasi_signal_t, -) -> Result<()> { +) -> WasiResult<()> { unimplemented!("proc_raise") } diff --git a/crates/wasi-common/src/hostcalls_impl/sock.rs b/crates/wasi-common/src/hostcalls_impl/sock.rs index 9089e421f9..6e133bb235 100644 --- a/crates/wasi-common/src/hostcalls_impl/sock.rs +++ b/crates/wasi-common/src/hostcalls_impl/sock.rs @@ -1,5 +1,6 @@ use crate::ctx::WasiCtx; -use crate::{wasi, wasi32, Result}; +use crate::wasi::{self, WasiResult}; +use crate::wasi32; pub fn sock_recv( _wasi_ctx: &WasiCtx, @@ -10,7 +11,7 @@ pub fn sock_recv( _ri_flags: wasi::__wasi_riflags_t, _ro_datalen: wasi32::uintptr_t, _ro_flags: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { unimplemented!("sock_recv") } @@ -22,7 +23,7 @@ pub fn sock_send( _si_data_len: wasi32::size_t, _si_flags: wasi::__wasi_siflags_t, _so_datalen: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { unimplemented!("sock_send") } @@ -31,6 +32,6 @@ pub fn sock_shutdown( _memory: &mut [u8], _sock: wasi::__wasi_fd_t, _how: wasi::__wasi_sdflags_t, -) -> Result<()> { +) -> WasiResult<()> { unimplemented!("sock_shutdown") } diff --git a/crates/wasi-common/src/lib.rs b/crates/wasi-common/src/lib.rs index 7e074eba3b..b20066b1cd 100644 --- a/crates/wasi-common/src/lib.rs +++ b/crates/wasi-common/src/lib.rs @@ -22,7 +22,6 @@ )] mod ctx; -mod error; mod fdentry; pub mod fs; mod helpers; @@ -43,6 +42,3 @@ pub mod hostcalls { pub use ctx::{WasiCtx, WasiCtxBuilder}; pub use sys::preopen_dir; - -pub use error::Error; -pub(crate) use error::Result; diff --git a/crates/wasi-common/src/memory.rs b/crates/wasi-common/src/memory.rs index 4c9cb10844..a45dc537ae 100644 --- a/crates/wasi-common/src/memory.rs +++ b/crates/wasi-common/src/memory.rs @@ -8,38 +8,39 @@ //! are not held for long durations. #![allow(unused)] -use crate::{host, wasi, wasi32, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; +use crate::{host, wasi32}; use num::PrimInt; use std::convert::TryFrom; use std::mem::{align_of, size_of}; use std::{ptr, slice}; -fn dec_ptr(memory: &[u8], ptr: wasi32::uintptr_t, len: usize) -> Result<*const u8> { +fn dec_ptr(memory: &[u8], ptr: wasi32::uintptr_t, len: usize) -> WasiResult<*const u8> { // check for overflow - let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?; + let checked_len = (ptr as usize).checked_add(len).ok_or(WasiError::EFAULT)?; // translate the pointer memory .get(ptr as usize..checked_len) - .ok_or(Error::EFAULT) + .ok_or(WasiError::EFAULT) .map(|mem| mem.as_ptr()) } -fn dec_ptr_mut(memory: &mut [u8], ptr: wasi32::uintptr_t, len: usize) -> Result<*mut u8> { +fn dec_ptr_mut(memory: &mut [u8], ptr: wasi32::uintptr_t, len: usize) -> WasiResult<*mut u8> { // check for overflow - let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?; + let checked_len = (ptr as usize).checked_add(len).ok_or(WasiError::EFAULT)?; // translate the pointer memory .get_mut(ptr as usize..checked_len) - .ok_or(Error::EFAULT) + .ok_or(WasiError::EFAULT) .map(|mem| mem.as_mut_ptr()) } -fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> Result<&'memory T> { +fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> WasiResult<&'memory T> { // check that the ptr is aligned if ptr as usize % align_of::() != 0 { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } dec_ptr(memory, ptr, size_of::()).map(|p| unsafe { &*(p as *const T) }) @@ -48,49 +49,49 @@ fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> Resu fn dec_ptr_to_mut<'memory, T>( memory: &'memory mut [u8], ptr: wasi32::uintptr_t, -) -> Result<&'memory mut T> { +) -> WasiResult<&'memory mut T> { // check that the ptr is aligned if ptr as usize % align_of::() != 0 { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } dec_ptr_mut(memory, ptr, size_of::()).map(|p| unsafe { &mut *(p as *mut T) }) } /// This function does not perform endianness conversions! -fn dec_raw_byref(memory: &[u8], ptr: wasi32::uintptr_t) -> Result { +fn dec_raw_byref(memory: &[u8], ptr: wasi32::uintptr_t) -> WasiResult { dec_ptr_to::(memory, ptr).map(|p| unsafe { ptr::read(p) }) } /// This function does not perform endianness conversions! -fn enc_raw_byref(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> Result<()> { +fn enc_raw_byref(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> WasiResult<()> { dec_ptr_to_mut::(memory, ptr).map(|p| unsafe { ptr::write(p, t) }) } -pub(crate) fn dec_int_byref(memory: &[u8], ptr: wasi32::uintptr_t) -> Result +pub(crate) fn dec_int_byref(memory: &[u8], ptr: wasi32::uintptr_t) -> WasiResult where T: PrimInt, { dec_raw_byref::(memory, ptr).map(|i| PrimInt::from_le(i)) } -pub(crate) fn enc_int_byref(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> Result<()> +pub(crate) fn enc_int_byref(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> WasiResult<()> where T: PrimInt, { enc_raw_byref::(memory, ptr, PrimInt::to_le(t)) } -fn check_slice_of(ptr: wasi32::uintptr_t, len: wasi32::size_t) -> Result<(usize, usize)> { +fn check_slice_of(ptr: wasi32::uintptr_t, len: wasi32::size_t) -> WasiResult<(usize, usize)> { // check alignment, and that length doesn't overflow if ptr as usize % align_of::() != 0 { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } let len = dec_usize(len); let len_bytes = if let Some(len) = size_of::().checked_mul(len) { len } else { - return Err(Error::EOVERFLOW); + return Err(WasiError::EOVERFLOW); }; Ok((len, len_bytes)) @@ -100,7 +101,7 @@ fn dec_raw_slice_of<'memory, T>( memory: &'memory [u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result<&'memory [T]> { +) -> WasiResult<&'memory [T]> { let (len, len_bytes) = check_slice_of::(ptr, len)?; let ptr = dec_ptr(memory, ptr, len_bytes)? as *const T; Ok(unsafe { slice::from_raw_parts(ptr, len) }) @@ -110,7 +111,7 @@ fn dec_raw_slice_of_mut<'memory, T>( memory: &'memory mut [u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result<&'memory mut [T]> { +) -> WasiResult<&'memory mut [T]> { let (len, len_bytes) = check_slice_of::(ptr, len)?; let ptr = dec_ptr_mut(memory, ptr, len_bytes)? as *mut T; Ok(unsafe { slice::from_raw_parts_mut(ptr, len) }) @@ -120,16 +121,16 @@ fn raw_slice_for_enc<'memory, T>( memory: &'memory mut [u8], slice: &[T], ptr: wasi32::uintptr_t, -) -> Result<&'memory mut [T]> { +) -> WasiResult<&'memory mut [T]> { // check alignment if ptr as usize % align_of::() != 0 { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } // check that length doesn't overflow let len_bytes = if let Some(len) = size_of::().checked_mul(slice.len()) { len } else { - return Err(Error::EOVERFLOW); + return Err(WasiError::EOVERFLOW); }; // get the pointer into guest memory @@ -142,7 +143,7 @@ pub(crate) fn dec_slice_of_u8<'memory>( memory: &'memory [u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result<&'memory [u8]> { +) -> WasiResult<&'memory [u8]> { dec_raw_slice_of::(memory, ptr, len) } @@ -150,7 +151,7 @@ pub(crate) fn dec_slice_of_mut_u8<'memory>( memory: &'memory mut [u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result<&'memory mut [u8]> { +) -> WasiResult<&'memory mut [u8]> { dec_raw_slice_of_mut::(memory, ptr, len) } @@ -158,7 +159,7 @@ pub(crate) fn enc_slice_of_u8( memory: &mut [u8], slice: &[u8], ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { let output = raw_slice_for_enc::(memory, slice, ptr)?; output.copy_from_slice(slice); @@ -170,7 +171,7 @@ pub(crate) fn enc_slice_of_wasi32_uintptr( memory: &mut [u8], slice: &[wasi32::uintptr_t], ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { let mut output_iter = raw_slice_for_enc::(memory, slice, ptr)?.into_iter(); for p in slice { @@ -182,7 +183,10 @@ pub(crate) fn enc_slice_of_wasi32_uintptr( macro_rules! dec_enc_scalar { ($ty:ident, $dec_byref:ident, $enc_byref:ident) => { - pub(crate) fn $dec_byref(memory: &mut [u8], ptr: wasi32::uintptr_t) -> Result { + pub(crate) fn $dec_byref( + memory: &mut [u8], + ptr: wasi32::uintptr_t, + ) -> WasiResult { dec_int_byref::(memory, ptr) } @@ -190,7 +194,7 @@ macro_rules! dec_enc_scalar { memory: &mut [u8], ptr: wasi32::uintptr_t, x: wasi::$ty, - ) -> Result<()> { + ) -> WasiResult<()> { enc_int_byref::(memory, ptr, x) } }; @@ -200,7 +204,7 @@ pub(crate) fn dec_ciovec_slice( memory: &[u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result> { +) -> WasiResult> { let raw_slice = dec_raw_slice_of::(memory, ptr, len)?; raw_slice @@ -220,7 +224,7 @@ pub(crate) fn dec_iovec_slice( memory: &[u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result> { +) -> WasiResult> { let raw_slice = dec_raw_slice_of::(memory, ptr, len)?; raw_slice @@ -248,7 +252,7 @@ dec_enc_scalar!(__wasi_linkcount_t, dev_linkcount_byref, enc_linkcount_byref); pub(crate) fn dec_filestat_byref( memory: &mut [u8], filestat_ptr: wasi32::uintptr_t, -) -> Result { +) -> WasiResult { let raw = dec_raw_byref::(memory, filestat_ptr)?; Ok(wasi::__wasi_filestat_t { @@ -267,7 +271,7 @@ pub(crate) fn enc_filestat_byref( memory: &mut [u8], filestat_ptr: wasi32::uintptr_t, filestat: wasi::__wasi_filestat_t, -) -> Result<()> { +) -> WasiResult<()> { let raw = wasi::__wasi_filestat_t { dev: PrimInt::to_le(filestat.dev), ino: PrimInt::to_le(filestat.ino), @@ -285,7 +289,7 @@ pub(crate) fn enc_filestat_byref( pub(crate) fn dec_fdstat_byref( memory: &mut [u8], fdstat_ptr: wasi32::uintptr_t, -) -> Result { +) -> WasiResult { let raw = dec_raw_byref::(memory, fdstat_ptr)?; Ok(wasi::__wasi_fdstat_t { @@ -300,7 +304,7 @@ pub(crate) fn enc_fdstat_byref( memory: &mut [u8], fdstat_ptr: wasi32::uintptr_t, fdstat: wasi::__wasi_fdstat_t, -) -> Result<()> { +) -> WasiResult<()> { let raw = wasi::__wasi_fdstat_t { fs_filetype: PrimInt::to_le(fdstat.fs_filetype), fs_flags: PrimInt::to_le(fdstat.fs_flags), @@ -326,7 +330,7 @@ dec_enc_scalar!(__wasi_oflags_t, dec_oflags_byref, enc_oflags_byref); pub(crate) fn dec_prestat_byref( memory: &mut [u8], prestat_ptr: wasi32::uintptr_t, -) -> Result { +) -> WasiResult { let raw = dec_raw_byref::(memory, prestat_ptr)?; match PrimInt::from_le(raw.tag) { @@ -338,7 +342,7 @@ pub(crate) fn dec_prestat_byref( }, }, }), - _ => Err(Error::EINVAL), + _ => Err(WasiError::EINVAL), } } @@ -346,7 +350,7 @@ pub(crate) fn enc_prestat_byref( memory: &mut [u8], prestat_ptr: wasi32::uintptr_t, prestat: host::__wasi_prestat_t, -) -> Result<()> { +) -> WasiResult<()> { let raw = match prestat.tag { wasi::__WASI_PREOPENTYPE_DIR => Ok(wasi32::__wasi_prestat_t { tag: PrimInt::to_le(wasi::__WASI_PREOPENTYPE_DIR), @@ -356,7 +360,7 @@ pub(crate) fn enc_prestat_byref( }, }, }), - _ => Err(Error::EINVAL), + _ => Err(WasiError::EINVAL), }?; enc_raw_byref::(memory, prestat_ptr, raw) @@ -377,7 +381,7 @@ pub(crate) fn enc_usize_byref( memory: &mut [u8], usize_ptr: wasi32::uintptr_t, host_usize: usize, -) -> Result<()> { +) -> WasiResult<()> { enc_int_byref::(memory, usize_ptr, enc_usize(host_usize)) } @@ -402,7 +406,7 @@ pub(crate) fn dec_subscriptions( memory: &mut [u8], input: wasi32::uintptr_t, nsubscriptions: wasi32::size_t, -) -> Result> { +) -> WasiResult> { let raw_input_slice = dec_raw_slice_of::(memory, input, nsubscriptions)?; @@ -435,14 +439,14 @@ pub(crate) fn dec_subscriptions( }), }, }, - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }; Ok(wasi::__wasi_subscription_t { userdata, u: wasi::__wasi_subscription_u_t { tag, u }, }) }) - .collect::>>() + .collect::>>() } pub(crate) fn enc_events( @@ -450,7 +454,7 @@ pub(crate) fn enc_events( output: wasi32::uintptr_t, nsubscriptions: wasi32::size_t, events: Vec, -) -> Result<()> { +) -> WasiResult<()> { let mut raw_output_iter = dec_raw_slice_of_mut::(memory, output, nsubscriptions)?.into_iter(); diff --git a/crates/wasi-common/src/old/snapshot_0/ctx.rs b/crates/wasi-common/src/old/snapshot_0/ctx.rs index d6da885165..e9979bb46e 100644 --- a/crates/wasi-common/src/old/snapshot_0/ctx.rs +++ b/crates/wasi-common/src/old/snapshot_0/ctx.rs @@ -1,14 +1,42 @@ use crate::old::snapshot_0::fdentry::FdEntry; -use crate::old::snapshot_0::{wasi, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; use std::borrow::Borrow; use std::collections::HashMap; -use std::env; -use std::ffi::{CString, OsString}; +use std::ffi::{self, CString, OsString}; use std::fs::File; use std::path::{Path, PathBuf}; +use std::{env, io, string}; + +/// Possible errors when `WasiCtxBuilder` fails building +/// `WasiCtx`. +#[derive(Debug, thiserror::Error)] +pub enum WasiCtxBuilderError { + /// General I/O error was encountered. + #[error("general I/O error encountered: {0}")] + Io(#[from] io::Error), + /// Provided sequence of bytes was not a valid UTF-8. + #[error("provided sequence is not valid UTF-8: {0}")] + InvalidUtf8(#[from] string::FromUtf8Error), + /// Provided sequence of bytes was not a valid UTF-16. + /// + /// This error is expected to only occur on Windows hosts. + #[error("provided sequence is not valid UTF-16: {0}")] + InvalidUtf16(#[from] string::FromUtf16Error), + /// Provided sequence of bytes contained an unexpected NUL byte. + #[error("provided sequence contained an unexpected NUL byte")] + UnexpectedNul(#[from] ffi::NulError), + /// Provided `File` is not a directory. + #[error("preopened directory path {} is not a directory", .0.display())] + NotADirectory(PathBuf), + /// `WasiCtx` has too many opened files. + #[error("context object has too many opened files")] + TooManyFilesOpen, +} + +type WasiCtxBuilderResult = std::result::Result; enum PendingFdEntry { - Thunk(fn() -> Result), + Thunk(fn() -> io::Result), File(File), } @@ -18,7 +46,7 @@ impl std::fmt::Debug for PendingFdEntry { Self::Thunk(f) => write!( fmt, "PendingFdEntry::Thunk({:p})", - f as *const fn() -> Result + f as *const fn() -> io::Result ), Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f), } @@ -44,17 +72,29 @@ impl From for PendingCString { } impl PendingCString { - fn into_string(self) -> Result { - match self { - Self::Bytes(v) => String::from_utf8(v).map_err(|_| Error::EILSEQ), - Self::OsString(s) => s.into_string().map_err(|_| Error::EILSEQ), - } + fn into_string(self) -> WasiCtxBuilderResult { + let res = match self { + Self::Bytes(v) => String::from_utf8(v)?, + #[cfg(unix)] + Self::OsString(s) => { + use std::os::unix::ffi::OsStringExt; + String::from_utf8(s.into_vec())? + } + #[cfg(windows)] + Self::OsString(s) => { + use std::os::windows::ffi::OsStrExt; + let bytes: Vec = s.encode_wide().collect(); + String::from_utf16(&bytes)? + } + }; + Ok(res) } - /// Create a `CString` containing valid UTF-8, or fail with `Error::EILSEQ`. - fn into_utf8_cstring(self) -> Result { - self.into_string() - .and_then(|s| CString::new(s).map_err(|_| Error::EILSEQ)) + /// Create a `CString` containing valid UTF-8, or fail. + fn into_utf8_cstring(self) -> WasiCtxBuilderResult { + let s = self.into_string()?; + let s = CString::new(s)?; + Ok(s) } } @@ -85,8 +125,7 @@ impl WasiCtxBuilder { /// Add arguments to the command-line arguments list. /// - /// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail - /// with `Error::EILSEQ`. + /// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail. pub fn args>(mut self, args: impl IntoIterator) -> Self { self.args = args .into_iter() @@ -97,8 +136,7 @@ impl WasiCtxBuilder { /// Add an argument to the command-line arguments list. /// - /// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail - /// with `Error::EILSEQ`. + /// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail. pub fn arg>(mut self, arg: S) -> Self { self.args.push(arg.as_ref().to_vec().into()); self @@ -107,7 +145,7 @@ impl WasiCtxBuilder { /// Inherit the command-line arguments from the host process. /// /// If any arguments from the host process contain invalid UTF-8, `WasiCtxBuilder::build()` will - /// fail with `Error::EILSEQ`. + /// fail. pub fn inherit_args(mut self) -> Self { self.args = env::args_os().map(PendingCString::OsString).collect(); self @@ -127,8 +165,7 @@ impl WasiCtxBuilder { /// Inherit the environment variables from the host process. /// /// If any environment variables from the host process contain invalid Unicode (UTF-16 for - /// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail with - /// `Error::EILSEQ`. + /// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail. pub fn inherit_env(mut self) -> Self { self.env = std::env::vars_os() .map(|(k, v)| (k.into(), v.into())) @@ -139,7 +176,7 @@ impl WasiCtxBuilder { /// Add an entry to the environment. /// /// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else - /// `WasiCtxBuilder::build()` will fail with `Error::EILSEQ`. + /// `WasiCtxBuilder::build()` will fail. pub fn env>(mut self, k: S, v: S) -> Self { self.env .insert(k.as_ref().to_vec().into(), v.as_ref().to_vec().into()); @@ -149,7 +186,7 @@ impl WasiCtxBuilder { /// Add entries to the environment. /// /// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else - /// `WasiCtxBuilder::build()` will fail with `Error::EILSEQ`. + /// `WasiCtxBuilder::build()` will fail. pub fn envs, T: Borrow<(S, S)>>( mut self, envs: impl IntoIterator, @@ -191,15 +228,15 @@ impl WasiCtxBuilder { /// Build a `WasiCtx`, consuming this `WasiCtxBuilder`. /// /// If any of the arguments or environment variables in this builder cannot be converted into - /// `CString`s, either due to NUL bytes or Unicode conversions, this returns `Error::EILSEQ`. - pub fn build(self) -> Result { + /// `CString`s, either due to NUL bytes or Unicode conversions, this returns an error. + pub fn build(self) -> WasiCtxBuilderResult { // Process arguments and environment variables into `CString`s, failing quickly if they // contain any NUL bytes, or if conversion from `OsString` fails. let args = self .args .into_iter() .map(|arg| arg.into_utf8_cstring()) - .collect::>>()?; + .collect::>>()?; let env = self .env @@ -211,11 +248,12 @@ impl WasiCtxBuilder { pair.push_str(v.as_str()); // We have valid UTF-8, but the keys and values have not yet been checked // for NULs, so we do a final check here. - CString::new(pair).map_err(|_| Error::EILSEQ) + let s = CString::new(pair)?; + Ok(s) }) }) }) - .collect::>>()?; + .collect::>>()?; let mut fds: HashMap = HashMap::new(); // Populate the non-preopen fds. @@ -237,16 +275,20 @@ impl WasiCtxBuilder { for (guest_path, dir) in self.preopens { // We do the increment at the beginning of the loop body, so that we don't overflow // unnecessarily if we have exactly the maximum number of file descriptors. - preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?; + preopen_fd = preopen_fd + .checked_add(1) + .ok_or(WasiCtxBuilderError::TooManyFilesOpen)?; if !dir.metadata()?.is_dir() { - return Err(Error::EBADF); + return Err(WasiCtxBuilderError::NotADirectory(guest_path)); } // We don't currently allow setting file descriptors other than 0-2, but this will avoid // collisions if we restore that functionality in the future. while fds.contains_key(&preopen_fd) { - preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?; + preopen_fd = preopen_fd + .checked_add(1) + .ok_or(WasiCtxBuilderError::TooManyFilesOpen)?; } let mut fe = FdEntry::from(dir)?; fe.preopen_path = Some(guest_path); @@ -274,7 +316,7 @@ impl WasiCtx { /// - Environment variables are inherited from the host process. /// /// To override these behaviors, use `WasiCtxBuilder`. - pub fn new>(args: impl IntoIterator) -> Result { + pub fn new>(args: impl IntoIterator) -> WasiCtxBuilderResult { WasiCtxBuilder::new() .args(args) .inherit_stdio() @@ -288,30 +330,30 @@ impl WasiCtx { } /// Get an immutable `FdEntry` corresponding to the specified raw WASI `fd`. - pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> Result<&FdEntry> { - self.fds.get(&fd).ok_or(Error::EBADF) + pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> WasiResult<&FdEntry> { + self.fds.get(&fd).ok_or(WasiError::EBADF) } /// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`. pub(crate) unsafe fn get_fd_entry_mut( &mut self, fd: wasi::__wasi_fd_t, - ) -> Result<&mut FdEntry> { - self.fds.get_mut(&fd).ok_or(Error::EBADF) + ) -> WasiResult<&mut FdEntry> { + self.fds.get_mut(&fd).ok_or(WasiError::EBADF) } /// Insert the specified `FdEntry` into the `WasiCtx` object. /// /// The `FdEntry` will automatically get another free raw WASI `fd` assigned. Note that /// the two subsequent free raw WASI `fd`s do not have to be stored contiguously. - pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> Result { + pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> WasiResult { // Never insert where stdio handles are expected to be. let mut fd = 3; while self.fds.contains_key(&fd) { if let Some(next_fd) = fd.checked_add(1) { fd = next_fd; } else { - return Err(Error::EMFILE); + return Err(WasiError::EMFILE); } } self.fds.insert(fd, fe); @@ -329,7 +371,7 @@ impl WasiCtx { } /// Remove `FdEntry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object. - pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> Result { - self.fds.remove(&fd).ok_or(Error::EBADF) + pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult { + self.fds.remove(&fd).ok_or(WasiError::EBADF) } } diff --git a/crates/wasi-common/src/old/snapshot_0/error.rs b/crates/wasi-common/src/old/snapshot_0/error.rs deleted file mode 100644 index 83f137e03c..0000000000 --- a/crates/wasi-common/src/old/snapshot_0/error.rs +++ /dev/null @@ -1,234 +0,0 @@ -// Due to https://github.com/rust-lang/rust/issues/64247 -#![allow(clippy::use_self)] -use crate::old::snapshot_0::wasi; -use std::convert::Infallible; -use std::num::TryFromIntError; -use std::{ffi, str}; -use thiserror::Error; - -#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)] -#[repr(u16)] -#[error("{:?} ({})", self, wasi::strerror(*self as wasi::__wasi_errno_t))] -pub enum WasiError { - ESUCCESS = wasi::__WASI_ERRNO_SUCCESS, - E2BIG = wasi::__WASI_ERRNO_2BIG, - EACCES = wasi::__WASI_ERRNO_ACCES, - EADDRINUSE = wasi::__WASI_ERRNO_ADDRINUSE, - EADDRNOTAVAIL = wasi::__WASI_ERRNO_ADDRNOTAVAIL, - EAFNOSUPPORT = wasi::__WASI_ERRNO_AFNOSUPPORT, - EAGAIN = wasi::__WASI_ERRNO_AGAIN, - EALREADY = wasi::__WASI_ERRNO_ALREADY, - EBADF = wasi::__WASI_ERRNO_BADF, - EBADMSG = wasi::__WASI_ERRNO_BADMSG, - EBUSY = wasi::__WASI_ERRNO_BUSY, - ECANCELED = wasi::__WASI_ERRNO_CANCELED, - ECHILD = wasi::__WASI_ERRNO_CHILD, - ECONNABORTED = wasi::__WASI_ERRNO_CONNABORTED, - ECONNREFUSED = wasi::__WASI_ERRNO_CONNREFUSED, - ECONNRESET = wasi::__WASI_ERRNO_CONNRESET, - EDEADLK = wasi::__WASI_ERRNO_DEADLK, - EDESTADDRREQ = wasi::__WASI_ERRNO_DESTADDRREQ, - EDOM = wasi::__WASI_ERRNO_DOM, - EDQUOT = wasi::__WASI_ERRNO_DQUOT, - EEXIST = wasi::__WASI_ERRNO_EXIST, - EFAULT = wasi::__WASI_ERRNO_FAULT, - EFBIG = wasi::__WASI_ERRNO_FBIG, - EHOSTUNREACH = wasi::__WASI_ERRNO_HOSTUNREACH, - EIDRM = wasi::__WASI_ERRNO_IDRM, - EILSEQ = wasi::__WASI_ERRNO_ILSEQ, - EINPROGRESS = wasi::__WASI_ERRNO_INPROGRESS, - EINTR = wasi::__WASI_ERRNO_INTR, - EINVAL = wasi::__WASI_ERRNO_INVAL, - EIO = wasi::__WASI_ERRNO_IO, - EISCONN = wasi::__WASI_ERRNO_ISCONN, - EISDIR = wasi::__WASI_ERRNO_ISDIR, - ELOOP = wasi::__WASI_ERRNO_LOOP, - EMFILE = wasi::__WASI_ERRNO_MFILE, - EMLINK = wasi::__WASI_ERRNO_MLINK, - EMSGSIZE = wasi::__WASI_ERRNO_MSGSIZE, - EMULTIHOP = wasi::__WASI_ERRNO_MULTIHOP, - ENAMETOOLONG = wasi::__WASI_ERRNO_NAMETOOLONG, - ENETDOWN = wasi::__WASI_ERRNO_NETDOWN, - ENETRESET = wasi::__WASI_ERRNO_NETRESET, - ENETUNREACH = wasi::__WASI_ERRNO_NETUNREACH, - ENFILE = wasi::__WASI_ERRNO_NFILE, - ENOBUFS = wasi::__WASI_ERRNO_NOBUFS, - ENODEV = wasi::__WASI_ERRNO_NODEV, - ENOENT = wasi::__WASI_ERRNO_NOENT, - ENOEXEC = wasi::__WASI_ERRNO_NOEXEC, - ENOLCK = wasi::__WASI_ERRNO_NOLCK, - ENOLINK = wasi::__WASI_ERRNO_NOLINK, - ENOMEM = wasi::__WASI_ERRNO_NOMEM, - ENOMSG = wasi::__WASI_ERRNO_NOMSG, - ENOPROTOOPT = wasi::__WASI_ERRNO_NOPROTOOPT, - ENOSPC = wasi::__WASI_ERRNO_NOSPC, - ENOSYS = wasi::__WASI_ERRNO_NOSYS, - ENOTCONN = wasi::__WASI_ERRNO_NOTCONN, - ENOTDIR = wasi::__WASI_ERRNO_NOTDIR, - ENOTEMPTY = wasi::__WASI_ERRNO_NOTEMPTY, - ENOTRECOVERABLE = wasi::__WASI_ERRNO_NOTRECOVERABLE, - ENOTSOCK = wasi::__WASI_ERRNO_NOTSOCK, - ENOTSUP = wasi::__WASI_ERRNO_NOTSUP, - ENOTTY = wasi::__WASI_ERRNO_NOTTY, - ENXIO = wasi::__WASI_ERRNO_NXIO, - EOVERFLOW = wasi::__WASI_ERRNO_OVERFLOW, - EOWNERDEAD = wasi::__WASI_ERRNO_OWNERDEAD, - EPERM = wasi::__WASI_ERRNO_PERM, - EPIPE = wasi::__WASI_ERRNO_PIPE, - EPROTO = wasi::__WASI_ERRNO_PROTO, - EPROTONOSUPPORT = wasi::__WASI_ERRNO_PROTONOSUPPORT, - EPROTOTYPE = wasi::__WASI_ERRNO_PROTOTYPE, - ERANGE = wasi::__WASI_ERRNO_RANGE, - EROFS = wasi::__WASI_ERRNO_ROFS, - ESPIPE = wasi::__WASI_ERRNO_SPIPE, - ESRCH = wasi::__WASI_ERRNO_SRCH, - ESTALE = wasi::__WASI_ERRNO_STALE, - ETIMEDOUT = wasi::__WASI_ERRNO_TIMEDOUT, - ETXTBSY = wasi::__WASI_ERRNO_TXTBSY, - EXDEV = wasi::__WASI_ERRNO_XDEV, - ENOTCAPABLE = wasi::__WASI_ERRNO_NOTCAPABLE, -} - -impl WasiError { - pub fn as_raw_errno(self) -> wasi::__wasi_errno_t { - self as wasi::__wasi_errno_t - } -} - -#[derive(Debug, Error)] -pub enum Error { - #[error("WASI error code: {0}")] - Wasi(#[from] WasiError), - #[error("IO error: {0}")] - Io(#[from] std::io::Error), -} - -impl From for Error { - fn from(_: TryFromIntError) -> Self { - Self::EOVERFLOW - } -} - -impl From for Error { - fn from(_: Infallible) -> Self { - unreachable!() - } -} - -impl From for Error { - fn from(_: str::Utf8Error) -> Self { - Self::EILSEQ - } -} - -impl From for Error { - fn from(_: ffi::NulError) -> Self { - Self::EILSEQ - } -} - -impl From<&ffi::NulError> for Error { - fn from(_: &ffi::NulError) -> Self { - Self::EILSEQ - } -} - -impl Error { - pub(crate) fn as_wasi_error(&self) -> WasiError { - match self { - Self::Wasi(err) => *err, - Self::Io(err) => { - let err = match err.raw_os_error() { - Some(code) => Self::from_raw_os_error(code), - None => { - log::debug!("Inconvertible OS error: {}", err); - Self::EIO - } - }; - err.as_wasi_error() - } - } - } - - 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); -} - -pub(crate) trait FromRawOsError { - fn from_raw_os_error(code: i32) -> Self; -} diff --git a/crates/wasi-common/src/old/snapshot_0/fdentry.rs b/crates/wasi-common/src/old/snapshot_0/fdentry.rs index aab0178b93..cf248277f1 100644 --- a/crates/wasi-common/src/old/snapshot_0/fdentry.rs +++ b/crates/wasi-common/src/old/snapshot_0/fdentry.rs @@ -2,7 +2,7 @@ use crate::old::snapshot_0::sys::dev_null; use crate::old::snapshot_0::sys::fdentry_impl::{ descriptor_as_oshandle, determine_type_and_access_rights, OsHandle, }; -use crate::old::snapshot_0::{wasi, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; @@ -21,18 +21,18 @@ impl Descriptor { /// Return a reference to the `OsHandle` treating it as an actual file/dir, and /// allowing operations which require an actual file and not just a stream or /// socket file descriptor. - pub(crate) fn as_file(&self) -> Result<&OsHandle> { + pub(crate) fn as_file(&self) -> WasiResult<&OsHandle> { match self { Self::OsHandle(file) => Ok(file), - _ => Err(Error::EBADF), + _ => Err(WasiError::EBADF), } } /// Like `as_file`, but return a mutable reference. - pub(crate) fn as_file_mut(&mut self) -> Result<&mut OsHandle> { + pub(crate) fn as_file_mut(&mut self) -> WasiResult<&mut OsHandle> { match self { Self::OsHandle(file) => Ok(file), - _ => Err(Error::EBADF), + _ => Err(WasiError::EBADF), } } @@ -64,7 +64,7 @@ impl FdEntry { /// Create an FdEntry with *maximal* possible rights from a given `File`. /// If this is not desired, the rights of the resulting `FdEntry` should /// be manually restricted. - pub(crate) fn from(file: fs::File) -> Result { + pub(crate) fn from(file: fs::File) -> io::Result { unsafe { determine_type_and_access_rights(&file) }.map( |(file_type, rights_base, rights_inheriting)| Self { file_type, @@ -76,7 +76,7 @@ impl FdEntry { ) } - pub(crate) fn duplicate_stdin() -> Result { + pub(crate) fn duplicate_stdin() -> io::Result { unsafe { determine_type_and_access_rights(&io::stdin()) }.map( |(file_type, rights_base, rights_inheriting)| Self { file_type, @@ -88,7 +88,7 @@ impl FdEntry { ) } - pub(crate) fn duplicate_stdout() -> Result { + pub(crate) fn duplicate_stdout() -> io::Result { unsafe { determine_type_and_access_rights(&io::stdout()) }.map( |(file_type, rights_base, rights_inheriting)| Self { file_type, @@ -100,7 +100,7 @@ impl FdEntry { ) } - pub(crate) fn duplicate_stderr() -> Result { + pub(crate) fn duplicate_stderr() -> io::Result { unsafe { determine_type_and_access_rights(&io::stderr()) }.map( |(file_type, rights_base, rights_inheriting)| Self { file_type, @@ -112,7 +112,7 @@ impl FdEntry { ) } - pub(crate) fn null() -> Result { + pub(crate) fn null() -> io::Result { Self::from(dev_null()?) } @@ -127,7 +127,7 @@ impl FdEntry { &self, rights_base: wasi::__wasi_rights_t, rights_inheriting: wasi::__wasi_rights_t, - ) -> Result<&Descriptor> { + ) -> WasiResult<&Descriptor> { self.validate_rights(rights_base, rights_inheriting)?; Ok(&self.descriptor) } @@ -143,7 +143,7 @@ impl FdEntry { &mut self, rights_base: wasi::__wasi_rights_t, rights_inheriting: wasi::__wasi_rights_t, - ) -> Result<&mut Descriptor> { + ) -> WasiResult<&mut Descriptor> { self.validate_rights(rights_base, rights_inheriting)?; Ok(&mut self.descriptor) } @@ -157,10 +157,10 @@ impl FdEntry { &self, rights_base: wasi::__wasi_rights_t, rights_inheriting: wasi::__wasi_rights_t, - ) -> Result<()> { + ) -> WasiResult<()> { if !self.rights_base & rights_base != 0 || !self.rights_inheriting & rights_inheriting != 0 { - Err(Error::ENOTCAPABLE) + Err(WasiError::ENOTCAPABLE) } else { Ok(()) } diff --git a/crates/wasi-common/src/old/snapshot_0/helpers.rs b/crates/wasi-common/src/old/snapshot_0/helpers.rs index f540eb8f12..e4426ffc2e 100644 --- a/crates/wasi-common/src/old/snapshot_0/helpers.rs +++ b/crates/wasi-common/src/old/snapshot_0/helpers.rs @@ -1,10 +1,11 @@ -use crate::old::snapshot_0::{Error, Result}; +use crate::old::snapshot_0::wasi::WasiResult; use std::str; /// Creates not-owned WASI path from byte slice. /// /// NB WASI spec requires bytes to be valid UTF-8. Otherwise, /// `__WASI_ERRNO_ILSEQ` error is returned. -pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> { - str::from_utf8(s).map_err(|_| Error::EILSEQ) +pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> WasiResult<&'a str> { + let s = str::from_utf8(s)?; + Ok(s) } diff --git a/crates/wasi-common/src/old/snapshot_0/host.rs b/crates/wasi-common/src/old/snapshot_0/host.rs index b029fcf10e..e9cef3b750 100644 --- a/crates/wasi-common/src/old/snapshot_0/host.rs +++ b/crates/wasi-common/src/old/snapshot_0/host.rs @@ -5,7 +5,6 @@ #![allow(non_snake_case)] use crate::old::snapshot_0::wasi::*; -use crate::old::snapshot_0::{Error, Result}; use std::{convert::TryInto, io, mem, slice}; use wig::witx_host_types; @@ -52,11 +51,13 @@ pub(crate) struct Dirent { impl Dirent { /// Serialize the directory entry to the format define by `__wasi_fd_readdir`, /// so that the serialized entries can be concatenated by the implementation. - pub fn to_wasi_raw(&self) -> Result> { + pub fn to_wasi_raw(&self) -> WasiResult> { let name = self.name.as_bytes(); let namlen = name.len(); let dirent_size = mem::size_of::<__wasi_dirent_t>(); - let offset = dirent_size.checked_add(namlen).ok_or(Error::EOVERFLOW)?; + let offset = dirent_size + .checked_add(namlen) + .ok_or(WasiError::EOVERFLOW)?; let mut raw = Vec::::with_capacity(offset); raw.resize(offset, 0); diff --git a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs index ff23ae0a5e..a038ad4bf8 100644 --- a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs @@ -7,7 +7,8 @@ use crate::old::snapshot_0::memory::*; use crate::old::snapshot_0::sys::fdentry_impl::determine_type_rights; use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::path_open_rights; use crate::old::snapshot_0::sys::{host_impl, hostcalls_impl}; -use crate::old::snapshot_0::{helpers, host, wasi, wasi32, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; +use crate::old::snapshot_0::{helpers, host, wasi32}; use crate::sandboxed_tty_writer::SandboxedTTYWriter; use filetime::{set_file_handle_times, FileTime}; use log::trace; @@ -20,13 +21,13 @@ pub(crate) unsafe fn fd_close( wasi_ctx: &mut WasiCtx, _mem: &mut [u8], fd: wasi::__wasi_fd_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_close(fd={:?})", fd); if let Ok(fe) = wasi_ctx.get_fd_entry(fd) { // can't close preopened files if fe.preopen_path.is_some() { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } } @@ -38,7 +39,7 @@ pub(crate) unsafe fn fd_datasync( wasi_ctx: &WasiCtx, _mem: &mut [u8], fd: wasi::__wasi_fd_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_datasync(fd={:?})", fd); let fd = wasi_ctx @@ -57,7 +58,7 @@ pub(crate) unsafe fn fd_pread( iovs_len: wasi32::size_t, offset: wasi::__wasi_filesize_t, nread: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_pread(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})", fd, @@ -75,7 +76,7 @@ pub(crate) unsafe fn fd_pread( let iovs = dec_iovec_slice(memory, iovs_ptr, iovs_len)?; if offset > i64::max_value() as u64 { - return Err(Error::EIO); + return Err(WasiError::EIO); } let buf_size = iovs.iter().map(|v| v.buf_len).sum(); let mut buf = vec![0; buf_size]; @@ -106,7 +107,7 @@ pub(crate) unsafe fn fd_pwrite( iovs_len: wasi32::size_t, offset: wasi::__wasi_filesize_t, nwritten: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_pwrite(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})", fd, @@ -126,7 +127,7 @@ pub(crate) unsafe fn fd_pwrite( let iovs = dec_ciovec_slice(memory, iovs_ptr, iovs_len)?; if offset > i64::max_value() as u64 { - return Err(Error::EIO); + return Err(WasiError::EIO); } let buf_size = iovs.iter().map(|v| v.buf_len).sum(); let mut buf = Vec::with_capacity(buf_size); @@ -150,7 +151,7 @@ pub(crate) unsafe fn fd_read( iovs_ptr: wasi32::uintptr_t, iovs_len: wasi32::size_t, nread: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_read(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nread={:#x?})", fd, @@ -171,7 +172,7 @@ pub(crate) unsafe fn fd_read( { Descriptor::OsHandle(file) => file.read_vectored(&mut iovs), Descriptor::Stdin => io::stdin().read_vectored(&mut iovs), - _ => return Err(Error::EBADF), + _ => return Err(WasiError::EBADF), }; let host_nread = maybe_host_nread?; @@ -186,11 +187,11 @@ pub(crate) unsafe fn fd_renumber( _mem: &mut [u8], from: wasi::__wasi_fd_t, to: wasi::__wasi_fd_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_renumber(from={:?}, to={:?})", from, to); if !wasi_ctx.contains_fd_entry(from) { - return Err(Error::EBADF); + return Err(WasiError::EBADF); } // Don't allow renumbering over a pre-opened resource. @@ -198,11 +199,11 @@ pub(crate) unsafe fn fd_renumber( // userspace is capable of removing entries from its tables as well. let from_fe = wasi_ctx.get_fd_entry(from)?; if from_fe.preopen_path.is_some() { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } if let Ok(to_fe) = wasi_ctx.get_fd_entry(to) { if to_fe.preopen_path.is_some() { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } } @@ -219,7 +220,7 @@ pub(crate) unsafe fn fd_seek( offset: wasi::__wasi_filedelta_t, whence: wasi::__wasi_whence_t, newoffset: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})", fd, @@ -242,7 +243,7 @@ pub(crate) unsafe fn fd_seek( wasi::__WASI_WHENCE_CUR => SeekFrom::Current(offset), wasi::__WASI_WHENCE_END => SeekFrom::End(offset), wasi::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64), - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }; let host_newoffset = fd.seek(pos)?; @@ -256,7 +257,7 @@ pub(crate) unsafe fn fd_tell( memory: &mut [u8], fd: wasi::__wasi_fd_t, newoffset: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset); let fd = wasi_ctx @@ -276,7 +277,7 @@ pub(crate) unsafe fn fd_fdstat_get( memory: &mut [u8], fd: wasi::__wasi_fd_t, fdstat_ptr: wasi32::uintptr_t, // *mut wasi::__wasi_fdstat_t -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr); let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?; @@ -303,7 +304,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags( _mem: &mut [u8], fd: wasi::__wasi_fd_t, fdflags: wasi::__wasi_fdflags_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags); let fd = wasi_ctx @@ -320,7 +321,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights( fd: wasi::__wasi_fd_t, fs_rights_base: wasi::__wasi_rights_t, fs_rights_inheriting: wasi::__wasi_rights_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})", fd, @@ -332,7 +333,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights( if fe.rights_base & fs_rights_base != fs_rights_base || fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting { - return Err(Error::ENOTCAPABLE); + return Err(WasiError::ENOTCAPABLE); } fe.rights_base = fs_rights_base; fe.rights_inheriting = fs_rights_inheriting; @@ -344,7 +345,7 @@ pub(crate) unsafe fn fd_sync( wasi_ctx: &WasiCtx, _mem: &mut [u8], fd: wasi::__wasi_fd_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_sync(fd={:?})", fd); let fd = wasi_ctx @@ -361,7 +362,7 @@ pub(crate) unsafe fn fd_write( iovs_ptr: wasi32::uintptr_t, iovs_len: wasi32::size_t, nwritten: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_write(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nwritten={:#x?})", fd, @@ -385,7 +386,7 @@ pub(crate) unsafe fn fd_write( file.write_vectored(&iovs)? } } - Descriptor::Stdin => return Err(Error::EBADF), + Descriptor::Stdin => return Err(WasiError::EBADF), Descriptor::Stdout => { // lock for the duration of the scope let stdout = io::stdout(); @@ -417,7 +418,7 @@ pub(crate) unsafe fn fd_advise( offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, advice: wasi::__wasi_advice_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_advise(fd={:?}, offset={}, len={}, advice={:?})", fd, @@ -440,7 +441,7 @@ pub(crate) unsafe fn fd_allocate( fd: wasi::__wasi_fd_t, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len); let fd = wasi_ctx @@ -451,10 +452,10 @@ pub(crate) unsafe fn fd_allocate( let metadata = fd.metadata()?; let current_size = metadata.len(); - let wanted_size = offset.checked_add(len).ok_or(Error::E2BIG)?; + let wanted_size = offset.checked_add(len).ok_or(WasiError::E2BIG)?; // This check will be unnecessary when rust-lang/rust#63326 is fixed if wanted_size > i64::max_value() as u64 { - return Err(Error::E2BIG); + return Err(WasiError::E2BIG); } if wanted_size > current_size { @@ -470,7 +471,7 @@ pub(crate) unsafe fn path_create_directory( dirfd: wasi::__wasi_fd_t, path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_create_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})", dirfd, @@ -499,7 +500,7 @@ pub(crate) unsafe fn path_link( new_dirfd: wasi::__wasi_fd_t, new_path_ptr: wasi32::uintptr_t, new_path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_link(old_dirfd={:?}, old_flags={:?}, old_path_ptr={:#x?}, old_path_len={}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})", old_dirfd, @@ -551,7 +552,7 @@ pub(crate) unsafe fn path_open( fs_rights_inheriting: wasi::__wasi_rights_t, fs_flags: wasi::__wasi_fdflags_t, fd_out_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_open(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={:?}, oflags={:#x?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?}, fs_flags={:#x?}, fd_out_ptr={:#x?})", dirfd, @@ -616,7 +617,7 @@ pub(crate) unsafe fn path_readlink( buf_ptr: wasi32::uintptr_t, buf_len: wasi32::size_t, buf_used: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_readlink(dirfd={:?}, path_ptr={:#x?}, path_len={:?}, buf_ptr={:#x?}, buf_len={}, buf_used={:#x?})", dirfd, @@ -655,7 +656,7 @@ pub(crate) unsafe fn path_rename( new_dirfd: wasi::__wasi_fd_t, new_path_ptr: wasi32::uintptr_t, new_path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_rename(old_dirfd={:?}, old_path_ptr={:#x?}, old_path_len={:?}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={:?})", old_dirfd, @@ -702,7 +703,7 @@ pub(crate) unsafe fn fd_filestat_get( memory: &mut [u8], fd: wasi::__wasi_fd_t, filestat_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_filestat_get(fd={:?}, filestat_ptr={:#x?})", fd, @@ -724,7 +725,7 @@ pub(crate) unsafe fn fd_filestat_set_times( st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fst_flags={:#x?})", fd, @@ -746,14 +747,14 @@ pub(crate) fn fd_filestat_set_times_impl( st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { let set_atim = fst_flags & wasi::__WASI_FSTFLAGS_ATIM != 0; let set_atim_now = fst_flags & wasi::__WASI_FSTFLAGS_ATIM_NOW != 0; let set_mtim = fst_flags & wasi::__WASI_FSTFLAGS_MTIM != 0; let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0; if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } let atim = if set_atim { let time = UNIX_EPOCH + Duration::from_nanos(st_atim); @@ -782,7 +783,7 @@ pub(crate) unsafe fn fd_filestat_set_size( _mem: &mut [u8], fd: wasi::__wasi_fd_t, st_size: wasi::__wasi_filesize_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size); let fd = wasi_ctx @@ -792,7 +793,7 @@ pub(crate) unsafe fn fd_filestat_set_size( // This check will be unnecessary when rust-lang/rust#63326 is fixed if st_size > i64::max_value() as u64 { - return Err(Error::E2BIG); + return Err(WasiError::E2BIG); } fd.set_len(st_size).map_err(Into::into) } @@ -805,7 +806,7 @@ pub(crate) unsafe fn path_filestat_get( path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, filestat_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_filestat_get(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, filestat_ptr={:#x?})", dirfd, @@ -845,7 +846,7 @@ pub(crate) unsafe fn path_filestat_set_times( st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_filestat_set_times(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, st_atim={}, st_mtim={}, fst_flags={:#x?})", dirfd, @@ -881,7 +882,7 @@ pub(crate) unsafe fn path_symlink( dirfd: wasi::__wasi_fd_t, new_path_ptr: wasi32::uintptr_t, new_path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_symlink(old_path_ptr={:#x?}, old_path_len={}, dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})", old_path_ptr, @@ -909,7 +910,7 @@ pub(crate) unsafe fn path_unlink_file( dirfd: wasi::__wasi_fd_t, path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_unlink_file(dirfd={:?}, path_ptr={:#x?}, path_len={})", dirfd, @@ -933,7 +934,7 @@ pub(crate) unsafe fn path_remove_directory( dirfd: wasi::__wasi_fd_t, path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "path_remove_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})", dirfd, @@ -965,7 +966,7 @@ pub(crate) unsafe fn fd_prestat_get( memory: &mut [u8], fd: wasi::__wasi_fd_t, prestat_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_prestat_get(fd={:?}, prestat_ptr={:#x?})", fd, @@ -974,9 +975,9 @@ pub(crate) unsafe fn fd_prestat_get( // TODO: should we validate any rights here? let fe = wasi_ctx.get_fd_entry(fd)?; - let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?; + let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?; if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } let path = host_impl::path_from_host(po_path.as_os_str())?; @@ -1001,7 +1002,7 @@ pub(crate) unsafe fn fd_prestat_dir_name( fd: wasi::__wasi_fd_t, path_ptr: wasi32::uintptr_t, path_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_prestat_dir_name(fd={:?}, path_ptr={:#x?}, path_len={})", fd, @@ -1011,15 +1012,15 @@ pub(crate) unsafe fn fd_prestat_dir_name( // TODO: should we validate any rights here? let fe = wasi_ctx.get_fd_entry(fd)?; - let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?; + let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?; if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } let path = host_impl::path_from_host(po_path.as_os_str())?; if path.len() > dec_usize(path_len) { - return Err(Error::ENAMETOOLONG); + return Err(WasiError::ENAMETOOLONG); } trace!(" | (path_ptr,path_len)='{}'", path); @@ -1035,7 +1036,7 @@ pub(crate) unsafe fn fd_readdir( buf_len: wasi32::size_t, cookie: wasi::__wasi_dircookie_t, buf_used: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})", fd, diff --git a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs index ff41bbc3a9..c646cc895e 100644 --- a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs +++ b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs @@ -1,7 +1,8 @@ #![allow(non_camel_case_types)] +use crate::old::snapshot_0::fdentry::FdEntry; use crate::old::snapshot_0::sys::host_impl; use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::*; -use crate::old::snapshot_0::{error::WasiError, fdentry::FdEntry, wasi, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; use std::fs::File; use std::path::{Component, Path}; @@ -31,17 +32,17 @@ pub(crate) fn path_get( dirflags: wasi::__wasi_lookupflags_t, path: &str, needs_final_component: bool, -) -> Result { +) -> WasiResult { const MAX_SYMLINK_EXPANSIONS: usize = 128; if path.contains('\0') { // if contains NUL, return EILSEQ - return Err(Error::EILSEQ); + return Err(WasiError::EILSEQ); } if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY { // if `dirfd` doesn't refer to a directory, return `ENOTDIR`. - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } let dirfd = fe @@ -72,7 +73,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(Error::ENOENT), + None => return Err(WasiError::ENOENT), Some(p) => p, }; let tail = components.as_path(); @@ -90,18 +91,18 @@ pub(crate) fn path_get( match head { Component::Prefix(_) | Component::RootDir => { // path is absolute! - return Err(Error::ENOTCAPABLE); + return Err(WasiError::ENOTCAPABLE); } Component::CurDir => { // "." so skip } Component::ParentDir => { // ".." so pop a dir - let _ = dir_stack.pop().ok_or(Error::ENOTCAPABLE)?; + let _ = dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?; // we're not allowed to pop past the original directory if dir_stack.is_empty() { - return Err(Error::ENOTCAPABLE); + return Err(WasiError::ENOTCAPABLE); } } Component::Normal(head) => { @@ -112,12 +113,12 @@ pub(crate) fn path_get( } if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) { - match openat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) { + match openat(dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?, &head) { Ok(new_dir) => { dir_stack.push(new_dir); } Err(e) => { - match e.as_wasi_error() { + match e { WasiError::ELOOP | WasiError::EMLINK | WasiError::ENOTDIR => @@ -126,13 +127,13 @@ pub(crate) fn path_get( { // attempt symlink expansion let mut link_path = readlinkat( - dir_stack.last().ok_or(Error::ENOTCAPABLE)?, + dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?, &head, )?; symlink_expansions += 1; if symlink_expansions > MAX_SYMLINK_EXPANSIONS { - return Err(Error::ELOOP); + return Err(WasiError::ELOOP); } if head.ends_with('/') { @@ -159,11 +160,12 @@ 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(Error::ENOTCAPABLE)?, &head) { + match readlinkat(dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?, &head) + { Ok(mut link_path) => { symlink_expansions += 1; if symlink_expansions > MAX_SYMLINK_EXPANSIONS { - return Err(Error::ELOOP); + return Err(WasiError::ELOOP); } if head.ends_with('/') { @@ -179,12 +181,12 @@ pub(crate) fn path_get( continue; } Err(e) => { - if e.as_wasi_error() != WasiError::EINVAL - && e.as_wasi_error() != WasiError::ENOENT + if e != WasiError::EINVAL + && e != WasiError::ENOENT // this handles the cases when trying to link to // a destination that already exists, and the target // path contains a slash - && e.as_wasi_error() != WasiError::ENOTDIR + && e != WasiError::ENOTDIR { return Err(e); } @@ -194,7 +196,7 @@ pub(crate) fn path_get( // not a symlink, so we're done; return Ok(PathGet { - dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?, + dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?, path: head, }); } @@ -204,7 +206,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(Error::ENOTCAPABLE)?, + dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?, path: String::from("."), }); } diff --git a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs index 14820a3e66..d577533bce 100644 --- a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs @@ -3,7 +3,8 @@ use crate::old::snapshot_0::ctx::WasiCtx; use crate::old::snapshot_0::fdentry::Descriptor; use crate::old::snapshot_0::memory::*; use crate::old::snapshot_0::sys::hostcalls_impl; -use crate::old::snapshot_0::{wasi, wasi32, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; +use crate::old::snapshot_0::wasi32; use log::{error, trace}; use std::convert::TryFrom; @@ -12,7 +13,7 @@ pub(crate) fn args_get( memory: &mut [u8], argv_ptr: wasi32::uintptr_t, argv_buf: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "args_get(argv_ptr={:#x?}, argv_buf={:#x?})", argv_ptr, @@ -31,7 +32,9 @@ pub(crate) fn args_get( argv.push(arg_ptr); let len = wasi32::uintptr_t::try_from(arg_bytes.len())?; - argv_buf_offset = argv_buf_offset.checked_add(len).ok_or(Error::EOVERFLOW)?; + argv_buf_offset = argv_buf_offset + .checked_add(len) + .ok_or(WasiError::EOVERFLOW)?; } enc_slice_of_wasi32_uintptr(memory, argv.as_slice(), argv_ptr) @@ -42,7 +45,7 @@ pub(crate) fn args_sizes_get( memory: &mut [u8], argc_ptr: wasi32::uintptr_t, argv_buf_size_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "args_sizes_get(argc_ptr={:#x?}, argv_buf_size_ptr={:#x?})", argc_ptr, @@ -70,7 +73,7 @@ pub(crate) fn environ_get( memory: &mut [u8], environ_ptr: wasi32::uintptr_t, environ_buf: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "environ_get(environ_ptr={:#x?}, environ_buf={:#x?})", environ_ptr, @@ -91,7 +94,7 @@ pub(crate) fn environ_get( let len = wasi32::uintptr_t::try_from(env_bytes.len())?; environ_buf_offset = environ_buf_offset .checked_add(len) - .ok_or(Error::EOVERFLOW)?; + .ok_or(WasiError::EOVERFLOW)?; } enc_slice_of_wasi32_uintptr(memory, environ.as_slice(), environ_ptr) @@ -102,7 +105,7 @@ pub(crate) fn environ_sizes_get( memory: &mut [u8], environ_count_ptr: wasi32::uintptr_t, environ_size_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "environ_sizes_get(environ_count_ptr={:#x?}, environ_size_ptr={:#x?})", environ_count_ptr, @@ -116,7 +119,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(Error::EOVERFLOW)?; + .ok_or(WasiError::EOVERFLOW)?; trace!(" | *environ_count_ptr={:?}", environ_count); @@ -132,14 +135,14 @@ pub(crate) fn random_get( memory: &mut [u8], buf_ptr: wasi32::uintptr_t, buf_len: wasi32::size_t, -) -> Result<()> { +) -> WasiResult<()> { trace!("random_get(buf_ptr={:#x?}, buf_len={:?})", buf_ptr, buf_len); let buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?; getrandom::getrandom(buf).map_err(|err| { error!("getrandom failure: {:?}", err); - Error::EIO + WasiError::EIO }) } @@ -148,7 +151,7 @@ pub(crate) fn clock_res_get( memory: &mut [u8], clock_id: wasi::__wasi_clockid_t, resolution_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "clock_res_get(clock_id={:?}, resolution_ptr={:#x?})", clock_id, @@ -168,7 +171,7 @@ pub(crate) fn clock_time_get( clock_id: wasi::__wasi_clockid_t, precision: wasi::__wasi_timestamp_t, time_ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "clock_time_get(clock_id={:?}, precision={:?}, time_ptr={:#x?})", clock_id, @@ -183,7 +186,7 @@ pub(crate) fn clock_time_get( enc_timestamp_byref(memory, time_ptr, time) } -pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> Result<()> { +pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> WasiResult<()> { trace!("sched_yield()"); std::thread::yield_now(); @@ -198,7 +201,7 @@ pub(crate) fn poll_oneoff( output: wasi32::uintptr_t, nsubscriptions: wasi32::size_t, nevents: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { trace!( "poll_oneoff(input={:#x?}, output={:#x?}, nsubscriptions={}, nevents={:#x?})", input, @@ -208,7 +211,7 @@ pub(crate) fn poll_oneoff( ); if u64::from(nsubscriptions) > wasi::__wasi_filesize_t::max_value() { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } enc_int_byref(memory, nevents, 0)?; @@ -253,7 +256,7 @@ pub(crate) fn poll_oneoff( Err(err) => { let event = wasi::__wasi_event_t { userdata: subscription.userdata, - error: err.as_wasi_error().as_raw_errno(), + error: err.as_raw_errno(), r#type: wasi::__WASI_EVENTTYPE_FD_READ, fd_readwrite: wasi::__wasi_event_fd_readwrite_t { nbytes: 0, @@ -281,7 +284,7 @@ pub(crate) fn poll_oneoff( Err(err) => { let event = wasi::__wasi_event_t { userdata: subscription.userdata, - error: err.as_wasi_error().as_raw_errno(), + error: err.as_raw_errno(), r#type: wasi::__WASI_EVENTTYPE_FD_WRITE, fd_readwrite: wasi::__wasi_event_fd_readwrite_t { nbytes: 0, @@ -301,7 +304,7 @@ pub(crate) fn poll_oneoff( hostcalls_impl::poll_oneoff(timeout, fd_events, &mut events)?; - let events_count = u32::try_from(events.len()).map_err(|_| Error::EOVERFLOW)?; + let events_count = u32::try_from(events.len()).map_err(|_| WasiError::EOVERFLOW)?; enc_events(memory, output, nsubscriptions, events)?; @@ -310,7 +313,9 @@ pub(crate) fn poll_oneoff( enc_int_byref(memory, nevents, events_count) } -fn wasi_clock_to_relative_ns_delay(wasi_clock: wasi::__wasi_subscription_clock_t) -> Result { +fn wasi_clock_to_relative_ns_delay( + wasi_clock: wasi::__wasi_subscription_clock_t, +) -> WasiResult { use std::time::SystemTime; if wasi_clock.flags != wasi::__WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME { @@ -318,7 +323,7 @@ fn wasi_clock_to_relative_ns_delay(wasi_clock: wasi::__wasi_subscription_clock_t } let now: u128 = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .map_err(|_| Error::ENOTCAPABLE)? + .map_err(|_| WasiError::ENOTCAPABLE)? .as_nanos(); let deadline = u128::from(wasi_clock.timeout); Ok(deadline.saturating_sub(now)) @@ -348,6 +353,6 @@ pub(crate) fn proc_raise( _wasi_ctx: &WasiCtx, _memory: &mut [u8], _sig: wasi::__wasi_signal_t, -) -> Result<()> { +) -> WasiResult<()> { unimplemented!("proc_raise") } diff --git a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/sock.rs b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/sock.rs index ac485413ad..0e92ce4e21 100644 --- a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/sock.rs +++ b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/sock.rs @@ -1,4 +1,5 @@ -use crate::old::snapshot_0::{wasi, wasi32, Result, WasiCtx}; +use crate::old::snapshot_0::wasi::{self, WasiResult}; +use crate::old::snapshot_0::{wasi32, WasiCtx}; pub fn sock_recv( _wasi_ctx: &WasiCtx, @@ -9,7 +10,7 @@ pub fn sock_recv( _ri_flags: wasi::__wasi_riflags_t, _ro_datalen: wasi32::uintptr_t, _ro_flags: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { unimplemented!("sock_recv") } @@ -21,7 +22,7 @@ pub fn sock_send( _si_data_len: wasi32::size_t, _si_flags: wasi::__wasi_siflags_t, _so_datalen: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { unimplemented!("sock_send") } @@ -30,6 +31,6 @@ pub fn sock_shutdown( _memory: &mut [u8], _sock: wasi::__wasi_fd_t, _how: wasi::__wasi_sdflags_t, -) -> Result<()> { +) -> WasiResult<()> { unimplemented!("sock_shutdown") } diff --git a/crates/wasi-common/src/old/snapshot_0/memory.rs b/crates/wasi-common/src/old/snapshot_0/memory.rs index c4f1d007ec..7f46db6c1e 100644 --- a/crates/wasi-common/src/old/snapshot_0/memory.rs +++ b/crates/wasi-common/src/old/snapshot_0/memory.rs @@ -8,38 +8,39 @@ //! are not held for long durations. #![allow(unused)] -use crate::old::snapshot_0::{host, wasi, wasi32, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; +use crate::old::snapshot_0::{host, wasi32}; use num::PrimInt; use std::convert::TryFrom; use std::mem::{align_of, size_of}; use std::{ptr, slice}; -fn dec_ptr(memory: &[u8], ptr: wasi32::uintptr_t, len: usize) -> Result<*const u8> { +fn dec_ptr(memory: &[u8], ptr: wasi32::uintptr_t, len: usize) -> WasiResult<*const u8> { // check for overflow - let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?; + let checked_len = (ptr as usize).checked_add(len).ok_or(WasiError::EFAULT)?; // translate the pointer memory .get(ptr as usize..checked_len) - .ok_or(Error::EFAULT) + .ok_or(WasiError::EFAULT) .map(|mem| mem.as_ptr()) } -fn dec_ptr_mut(memory: &mut [u8], ptr: wasi32::uintptr_t, len: usize) -> Result<*mut u8> { +fn dec_ptr_mut(memory: &mut [u8], ptr: wasi32::uintptr_t, len: usize) -> WasiResult<*mut u8> { // check for overflow - let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?; + let checked_len = (ptr as usize).checked_add(len).ok_or(WasiError::EFAULT)?; // translate the pointer memory .get_mut(ptr as usize..checked_len) - .ok_or(Error::EFAULT) + .ok_or(WasiError::EFAULT) .map(|mem| mem.as_mut_ptr()) } -fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> Result<&'memory T> { +fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> WasiResult<&'memory T> { // check that the ptr is aligned if ptr as usize % align_of::() != 0 { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } dec_ptr(memory, ptr, size_of::()).map(|p| unsafe { &*(p as *const T) }) @@ -48,49 +49,49 @@ fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> Resu fn dec_ptr_to_mut<'memory, T>( memory: &'memory mut [u8], ptr: wasi32::uintptr_t, -) -> Result<&'memory mut T> { +) -> WasiResult<&'memory mut T> { // check that the ptr is aligned if ptr as usize % align_of::() != 0 { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } dec_ptr_mut(memory, ptr, size_of::()).map(|p| unsafe { &mut *(p as *mut T) }) } /// This function does not perform endianness conversions! -fn dec_raw_byref(memory: &[u8], ptr: wasi32::uintptr_t) -> Result { +fn dec_raw_byref(memory: &[u8], ptr: wasi32::uintptr_t) -> WasiResult { dec_ptr_to::(memory, ptr).map(|p| unsafe { ptr::read(p) }) } /// This function does not perform endianness conversions! -fn enc_raw_byref(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> Result<()> { +fn enc_raw_byref(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> WasiResult<()> { dec_ptr_to_mut::(memory, ptr).map(|p| unsafe { ptr::write(p, t) }) } -pub(crate) fn dec_int_byref(memory: &[u8], ptr: wasi32::uintptr_t) -> Result +pub(crate) fn dec_int_byref(memory: &[u8], ptr: wasi32::uintptr_t) -> WasiResult where T: PrimInt, { dec_raw_byref::(memory, ptr).map(|i| PrimInt::from_le(i)) } -pub(crate) fn enc_int_byref(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> Result<()> +pub(crate) fn enc_int_byref(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> WasiResult<()> where T: PrimInt, { enc_raw_byref::(memory, ptr, PrimInt::to_le(t)) } -fn check_slice_of(ptr: wasi32::uintptr_t, len: wasi32::size_t) -> Result<(usize, usize)> { +fn check_slice_of(ptr: wasi32::uintptr_t, len: wasi32::size_t) -> WasiResult<(usize, usize)> { // check alignment, and that length doesn't overflow if ptr as usize % align_of::() != 0 { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } let len = dec_usize(len); let len_bytes = if let Some(len) = size_of::().checked_mul(len) { len } else { - return Err(Error::EOVERFLOW); + return Err(WasiError::EOVERFLOW); }; Ok((len, len_bytes)) @@ -100,7 +101,7 @@ fn dec_raw_slice_of<'memory, T>( memory: &'memory [u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result<&'memory [T]> { +) -> WasiResult<&'memory [T]> { let (len, len_bytes) = check_slice_of::(ptr, len)?; let ptr = dec_ptr(memory, ptr, len_bytes)? as *const T; Ok(unsafe { slice::from_raw_parts(ptr, len) }) @@ -110,7 +111,7 @@ fn dec_raw_slice_of_mut<'memory, T>( memory: &'memory mut [u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result<&'memory mut [T]> { +) -> WasiResult<&'memory mut [T]> { let (len, len_bytes) = check_slice_of::(ptr, len)?; let ptr = dec_ptr_mut(memory, ptr, len_bytes)? as *mut T; Ok(unsafe { slice::from_raw_parts_mut(ptr, len) }) @@ -120,16 +121,16 @@ fn raw_slice_for_enc<'memory, T>( memory: &'memory mut [u8], slice: &[T], ptr: wasi32::uintptr_t, -) -> Result<&'memory mut [T]> { +) -> WasiResult<&'memory mut [T]> { // check alignment if ptr as usize % align_of::() != 0 { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } // check that length doesn't overflow let len_bytes = if let Some(len) = size_of::().checked_mul(slice.len()) { len } else { - return Err(Error::EOVERFLOW); + return Err(WasiError::EOVERFLOW); }; // get the pointer into guest memory @@ -142,7 +143,7 @@ pub(crate) fn dec_slice_of_u8<'memory>( memory: &'memory [u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result<&'memory [u8]> { +) -> WasiResult<&'memory [u8]> { dec_raw_slice_of::(memory, ptr, len) } @@ -150,7 +151,7 @@ pub(crate) fn dec_slice_of_mut_u8<'memory>( memory: &'memory mut [u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result<&'memory mut [u8]> { +) -> WasiResult<&'memory mut [u8]> { dec_raw_slice_of_mut::(memory, ptr, len) } @@ -158,7 +159,7 @@ pub(crate) fn enc_slice_of_u8( memory: &mut [u8], slice: &[u8], ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { let output = raw_slice_for_enc::(memory, slice, ptr)?; output.copy_from_slice(slice); @@ -170,7 +171,7 @@ pub(crate) fn enc_slice_of_wasi32_uintptr( memory: &mut [u8], slice: &[wasi32::uintptr_t], ptr: wasi32::uintptr_t, -) -> Result<()> { +) -> WasiResult<()> { let mut output_iter = raw_slice_for_enc::(memory, slice, ptr)?.into_iter(); for p in slice { @@ -182,7 +183,10 @@ pub(crate) fn enc_slice_of_wasi32_uintptr( macro_rules! dec_enc_scalar { ($ty:ident, $dec_byref:ident, $enc_byref:ident) => { - pub(crate) fn $dec_byref(memory: &mut [u8], ptr: wasi32::uintptr_t) -> Result { + pub(crate) fn $dec_byref( + memory: &mut [u8], + ptr: wasi32::uintptr_t, + ) -> WasiResult { dec_int_byref::(memory, ptr) } @@ -190,7 +194,7 @@ macro_rules! dec_enc_scalar { memory: &mut [u8], ptr: wasi32::uintptr_t, x: wasi::$ty, - ) -> Result<()> { + ) -> WasiResult<()> { enc_int_byref::(memory, ptr, x) } }; @@ -200,7 +204,7 @@ pub(crate) fn dec_ciovec_slice( memory: &[u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result> { +) -> WasiResult> { let raw_slice = dec_raw_slice_of::(memory, ptr, len)?; raw_slice @@ -220,7 +224,7 @@ pub(crate) fn dec_iovec_slice( memory: &[u8], ptr: wasi32::uintptr_t, len: wasi32::size_t, -) -> Result> { +) -> WasiResult> { let raw_slice = dec_raw_slice_of::(memory, ptr, len)?; raw_slice @@ -248,7 +252,7 @@ dec_enc_scalar!(__wasi_linkcount_t, dev_linkcount_byref, enc_linkcount_byref); pub(crate) fn dec_filestat_byref( memory: &mut [u8], filestat_ptr: wasi32::uintptr_t, -) -> Result { +) -> WasiResult { let raw = dec_raw_byref::(memory, filestat_ptr)?; Ok(wasi::__wasi_filestat_t { @@ -267,7 +271,7 @@ pub(crate) fn enc_filestat_byref( memory: &mut [u8], filestat_ptr: wasi32::uintptr_t, filestat: wasi::__wasi_filestat_t, -) -> Result<()> { +) -> WasiResult<()> { let raw = wasi::__wasi_filestat_t { dev: PrimInt::to_le(filestat.dev), ino: PrimInt::to_le(filestat.ino), @@ -285,7 +289,7 @@ pub(crate) fn enc_filestat_byref( pub(crate) fn dec_fdstat_byref( memory: &mut [u8], fdstat_ptr: wasi32::uintptr_t, -) -> Result { +) -> WasiResult { let raw = dec_raw_byref::(memory, fdstat_ptr)?; Ok(wasi::__wasi_fdstat_t { @@ -300,7 +304,7 @@ pub(crate) fn enc_fdstat_byref( memory: &mut [u8], fdstat_ptr: wasi32::uintptr_t, fdstat: wasi::__wasi_fdstat_t, -) -> Result<()> { +) -> WasiResult<()> { let raw = wasi::__wasi_fdstat_t { fs_filetype: PrimInt::to_le(fdstat.fs_filetype), fs_flags: PrimInt::to_le(fdstat.fs_flags), @@ -326,7 +330,7 @@ dec_enc_scalar!(__wasi_oflags_t, dec_oflags_byref, enc_oflags_byref); pub(crate) fn dec_prestat_byref( memory: &mut [u8], prestat_ptr: wasi32::uintptr_t, -) -> Result { +) -> WasiResult { let raw = dec_raw_byref::(memory, prestat_ptr)?; match PrimInt::from_le(raw.tag) { @@ -338,7 +342,7 @@ pub(crate) fn dec_prestat_byref( }, }, }), - _ => Err(Error::EINVAL), + _ => Err(WasiError::EINVAL), } } @@ -346,7 +350,7 @@ pub(crate) fn enc_prestat_byref( memory: &mut [u8], prestat_ptr: wasi32::uintptr_t, prestat: host::__wasi_prestat_t, -) -> Result<()> { +) -> WasiResult<()> { let raw = match prestat.tag { wasi::__WASI_PREOPENTYPE_DIR => Ok(wasi32::__wasi_prestat_t { tag: PrimInt::to_le(wasi::__WASI_PREOPENTYPE_DIR), @@ -356,7 +360,7 @@ pub(crate) fn enc_prestat_byref( }, }, }), - _ => Err(Error::EINVAL), + _ => Err(WasiError::EINVAL), }?; enc_raw_byref::(memory, prestat_ptr, raw) @@ -377,7 +381,7 @@ pub(crate) fn enc_usize_byref( memory: &mut [u8], usize_ptr: wasi32::uintptr_t, host_usize: usize, -) -> Result<()> { +) -> WasiResult<()> { enc_int_byref::(memory, usize_ptr, enc_usize(host_usize)) } @@ -402,7 +406,7 @@ pub(crate) fn dec_subscriptions( memory: &mut [u8], input: wasi32::uintptr_t, nsubscriptions: wasi32::size_t, -) -> Result> { +) -> WasiResult> { let raw_input_slice = dec_raw_slice_of::(memory, input, nsubscriptions)?; @@ -436,14 +440,14 @@ pub(crate) fn dec_subscriptions( }), }, }, - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }; Ok(wasi::__wasi_subscription_t { userdata, u: wasi::__wasi_subscription_u_t { tag, u }, }) }) - .collect::>>() + .collect::>>() } pub(crate) fn enc_events( @@ -451,7 +455,7 @@ pub(crate) fn enc_events( output: wasi32::uintptr_t, nsubscriptions: wasi32::size_t, events: Vec, -) -> Result<()> { +) -> WasiResult<()> { let mut raw_output_iter = dec_raw_slice_of_mut::(memory, output, nsubscriptions)?.into_iter(); diff --git a/crates/wasi-common/src/old/snapshot_0/mod.rs b/crates/wasi-common/src/old/snapshot_0/mod.rs index 8226d731b0..d17e3035ce 100644 --- a/crates/wasi-common/src/old/snapshot_0/mod.rs +++ b/crates/wasi-common/src/old/snapshot_0/mod.rs @@ -1,5 +1,4 @@ mod ctx; -mod error; mod fdentry; mod helpers; mod host; @@ -14,6 +13,3 @@ pub mod hostcalls { } pub use ctx::{WasiCtx, WasiCtxBuilder}; - -pub type Error = error::Error; -pub type Result = std::result::Result; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/host_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/host_impl.rs index b151e703e1..ea14861f10 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/host_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/host_impl.rs @@ -1,16 +1,16 @@ -use crate::old::snapshot_0::{wasi, Result}; +use crate::old::snapshot_0::wasi::{self, WasiResult}; use std::convert::TryFrom; pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::SYNC; -pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> Result { +pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> WasiResult { wasi::__wasi_device_t::try_from(dev).map_err(Into::into) } -pub(crate) fn stino_from_nix(ino: libc::ino_t) -> Result { +pub(crate) fn stino_from_nix(ino: libc::ino_t) -> WasiResult { wasi::__wasi_device_t::try_from(ino).map_err(Into::into) } -pub(crate) fn stnlink_from_nix(nlink: libc::nlink_t) -> Result { +pub(crate) fn stnlink_from_nix(nlink: libc::nlink_t) -> WasiResult { Ok(nlink.into()) } diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs index bffb9c6b10..8923114c8f 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs @@ -1,8 +1,8 @@ use crate::old::snapshot_0::hostcalls_impl::PathGet; -use crate::old::snapshot_0::{Error, Result}; +use crate::old::snapshot_0::wasi::{WasiError, WasiResult}; use std::os::unix::prelude::AsRawFd; -pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { +pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> { use yanix::file::{unlinkat, AtFlag}; match unsafe { unlinkat( @@ -32,7 +32,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory { - return Err(Error::EISDIR); + return Err(WasiError::EISDIR); } } Err(err) => { @@ -47,7 +47,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { } } -pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { +pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> { use yanix::file::{fstatat, symlinkat, AtFlag}; log::debug!("path_symlink old_path = {:?}", old_path); @@ -69,7 +69,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { AtFlag::SYMLINK_NOFOLLOW, ) } { - Ok(_) => return Err(Error::EEXIST), + Ok(_) => return Err(WasiError::EEXIST), Err(err) => { log::debug!("path_symlink fstatat error: {:?}", err); } @@ -81,7 +81,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { } } -pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { +pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { use yanix::file::{fstatat, renameat, AtFlag}; match unsafe { renameat( @@ -113,9 +113,9 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul Ok(_) => { // check if destination contains a trailing slash if resolved_new.path().contains('/') { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } else { - return Err(Error::ENOENT); + return Err(WasiError::ENOENT); } } Err(err) => { @@ -132,13 +132,13 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul pub(crate) mod fd_readdir_impl { use crate::old::snapshot_0::sys::fdentry_impl::OsHandle; - use crate::old::snapshot_0::Result; + use crate::old::snapshot_0::wasi::WasiResult; use std::sync::{Mutex, MutexGuard}; use yanix::dir::Dir; pub(crate) fn get_dir_from_os_handle<'a>( os_handle: &'a mut OsHandle, - ) -> Result> { + ) -> WasiResult> { let dir = match os_handle.dir { Some(ref mut dir) => dir, None => { diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/fdentry_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/fdentry_impl.rs index a46177c3c5..a9bee8eeb9 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/fdentry_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/fdentry_impl.rs @@ -1,5 +1,5 @@ use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef}; -use crate::old::snapshot_0::{sys::unix::sys_impl, wasi, Error, Result}; +use crate::old::snapshot_0::{sys::unix::sys_impl, wasi}; use std::fs::File; use std::io; use std::mem::ManuallyDrop; @@ -29,7 +29,7 @@ pub(crate) fn descriptor_as_oshandle<'lifetime>( /// This function is unsafe because it operates on a raw file descriptor. pub(crate) unsafe fn determine_type_and_access_rights( fd: &Fd, -) -> Result<( +) -> io::Result<( wasi::__wasi_filetype_t, wasi::__wasi_rights_t, wasi::__wasi_rights_t, @@ -51,7 +51,7 @@ pub(crate) unsafe fn determine_type_and_access_rights( /// This function is unsafe because it operates on a raw file descriptor. pub(crate) unsafe fn determine_type_rights( fd: &Fd, -) -> Result<( +) -> io::Result<( wasi::__wasi_filetype_t, wasi::__wasi_rights_t, wasi::__wasi_rights_t, @@ -111,7 +111,7 @@ pub(crate) unsafe fn determine_type_rights( wasi::RIGHTS_SOCKET_BASE, wasi::RIGHTS_SOCKET_INHERITING, ), - _ => return Err(Error::EINVAL), + _ => return Err(io::Error::from_raw_os_error(libc::EINVAL)), } } else if ft.is_fifo() { log::debug!("Host fd {:?} is a fifo", fd.as_raw_fd()); @@ -122,7 +122,7 @@ pub(crate) unsafe fn determine_type_rights( ) } else { log::debug!("Host fd {:?} is unknown", fd.as_raw_fd()); - return Err(Error::EINVAL); + return Err(io::Error::from_raw_os_error(libc::EINVAL)); } }; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs index 688fcc63e2..f96473da90 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs @@ -3,94 +3,101 @@ #![allow(non_snake_case)] #![allow(dead_code)] use crate::old::snapshot_0::host::FileType; -use crate::old::snapshot_0::{ - error::FromRawOsError, helpers, sys::unix::sys_impl, wasi, Error, Result, -}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; +use crate::old::snapshot_0::{helpers, sys::unix::sys_impl}; use std::ffi::OsStr; +use std::io; use std::os::unix::prelude::OsStrExt; use yanix::file::OFlag; pub(crate) use sys_impl::host_impl::*; -impl FromRawOsError for Error { - fn from_raw_os_error(code: i32) -> Self { - match code { - libc::EPERM => Self::EPERM, - libc::ENOENT => Self::ENOENT, - libc::ESRCH => Self::ESRCH, - libc::EINTR => Self::EINTR, - libc::EIO => Self::EIO, - libc::ENXIO => Self::ENXIO, - libc::E2BIG => Self::E2BIG, - libc::ENOEXEC => Self::ENOEXEC, - libc::EBADF => Self::EBADF, - libc::ECHILD => Self::ECHILD, - libc::EAGAIN => Self::EAGAIN, - libc::ENOMEM => Self::ENOMEM, - libc::EACCES => Self::EACCES, - libc::EFAULT => Self::EFAULT, - libc::EBUSY => Self::EBUSY, - libc::EEXIST => Self::EEXIST, - libc::EXDEV => Self::EXDEV, - libc::ENODEV => Self::ENODEV, - libc::ENOTDIR => Self::ENOTDIR, - libc::EISDIR => Self::EISDIR, - libc::EINVAL => Self::EINVAL, - libc::ENFILE => Self::ENFILE, - libc::EMFILE => Self::EMFILE, - libc::ENOTTY => Self::ENOTTY, - libc::ETXTBSY => Self::ETXTBSY, - libc::EFBIG => Self::EFBIG, - libc::ENOSPC => Self::ENOSPC, - libc::ESPIPE => Self::ESPIPE, - libc::EROFS => Self::EROFS, - libc::EMLINK => Self::EMLINK, - libc::EPIPE => Self::EPIPE, - libc::EDOM => Self::EDOM, - libc::ERANGE => Self::ERANGE, - libc::EDEADLK => Self::EDEADLK, - libc::ENAMETOOLONG => Self::ENAMETOOLONG, - libc::ENOLCK => Self::ENOLCK, - libc::ENOSYS => Self::ENOSYS, - libc::ENOTEMPTY => Self::ENOTEMPTY, - libc::ELOOP => Self::ELOOP, - libc::ENOMSG => Self::ENOMSG, - libc::EIDRM => Self::EIDRM, - libc::ENOLINK => Self::ENOLINK, - libc::EPROTO => Self::EPROTO, - libc::EMULTIHOP => Self::EMULTIHOP, - libc::EBADMSG => Self::EBADMSG, - libc::EOVERFLOW => Self::EOVERFLOW, - libc::EILSEQ => Self::EILSEQ, - libc::ENOTSOCK => Self::ENOTSOCK, - libc::EDESTADDRREQ => Self::EDESTADDRREQ, - libc::EMSGSIZE => Self::EMSGSIZE, - libc::EPROTOTYPE => Self::EPROTOTYPE, - libc::ENOPROTOOPT => Self::ENOPROTOOPT, - libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT, - libc::EAFNOSUPPORT => Self::EAFNOSUPPORT, - libc::EADDRINUSE => Self::EADDRINUSE, - libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL, - libc::ENETDOWN => Self::ENETDOWN, - libc::ENETUNREACH => Self::ENETUNREACH, - libc::ENETRESET => Self::ENETRESET, - libc::ECONNABORTED => Self::ECONNABORTED, - libc::ECONNRESET => Self::ECONNRESET, - libc::ENOBUFS => Self::ENOBUFS, - libc::EISCONN => Self::EISCONN, - libc::ENOTCONN => Self::ENOTCONN, - libc::ETIMEDOUT => Self::ETIMEDOUT, - libc::ECONNREFUSED => Self::ECONNREFUSED, - libc::EHOSTUNREACH => Self::EHOSTUNREACH, - libc::EALREADY => Self::EALREADY, - libc::EINPROGRESS => Self::EINPROGRESS, - libc::ESTALE => Self::ESTALE, - libc::EDQUOT => Self::EDQUOT, - libc::ECANCELED => Self::ECANCELED, - libc::EOWNERDEAD => Self::EOWNERDEAD, - libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE, - x => { - log::debug!("Unknown errno value: {}", x); +impl From for WasiError { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(code) => match code { + libc::EPERM => Self::EPERM, + libc::ENOENT => Self::ENOENT, + libc::ESRCH => Self::ESRCH, + libc::EINTR => Self::EINTR, + libc::EIO => Self::EIO, + libc::ENXIO => Self::ENXIO, + libc::E2BIG => Self::E2BIG, + libc::ENOEXEC => Self::ENOEXEC, + libc::EBADF => Self::EBADF, + libc::ECHILD => Self::ECHILD, + libc::EAGAIN => Self::EAGAIN, + libc::ENOMEM => Self::ENOMEM, + libc::EACCES => Self::EACCES, + libc::EFAULT => Self::EFAULT, + libc::EBUSY => Self::EBUSY, + libc::EEXIST => Self::EEXIST, + libc::EXDEV => Self::EXDEV, + libc::ENODEV => Self::ENODEV, + libc::ENOTDIR => Self::ENOTDIR, + libc::EISDIR => Self::EISDIR, + libc::EINVAL => Self::EINVAL, + libc::ENFILE => Self::ENFILE, + libc::EMFILE => Self::EMFILE, + libc::ENOTTY => Self::ENOTTY, + libc::ETXTBSY => Self::ETXTBSY, + libc::EFBIG => Self::EFBIG, + libc::ENOSPC => Self::ENOSPC, + libc::ESPIPE => Self::ESPIPE, + libc::EROFS => Self::EROFS, + libc::EMLINK => Self::EMLINK, + libc::EPIPE => Self::EPIPE, + libc::EDOM => Self::EDOM, + libc::ERANGE => Self::ERANGE, + libc::EDEADLK => Self::EDEADLK, + libc::ENAMETOOLONG => Self::ENAMETOOLONG, + libc::ENOLCK => Self::ENOLCK, + libc::ENOSYS => Self::ENOSYS, + libc::ENOTEMPTY => Self::ENOTEMPTY, + libc::ELOOP => Self::ELOOP, + libc::ENOMSG => Self::ENOMSG, + libc::EIDRM => Self::EIDRM, + libc::ENOLINK => Self::ENOLINK, + libc::EPROTO => Self::EPROTO, + libc::EMULTIHOP => Self::EMULTIHOP, + libc::EBADMSG => Self::EBADMSG, + libc::EOVERFLOW => Self::EOVERFLOW, + libc::EILSEQ => Self::EILSEQ, + libc::ENOTSOCK => Self::ENOTSOCK, + libc::EDESTADDRREQ => Self::EDESTADDRREQ, + libc::EMSGSIZE => Self::EMSGSIZE, + libc::EPROTOTYPE => Self::EPROTOTYPE, + libc::ENOPROTOOPT => Self::ENOPROTOOPT, + libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT, + libc::EAFNOSUPPORT => Self::EAFNOSUPPORT, + libc::EADDRINUSE => Self::EADDRINUSE, + libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL, + libc::ENETDOWN => Self::ENETDOWN, + libc::ENETUNREACH => Self::ENETUNREACH, + libc::ENETRESET => Self::ENETRESET, + libc::ECONNABORTED => Self::ECONNABORTED, + libc::ECONNRESET => Self::ECONNRESET, + libc::ENOBUFS => Self::ENOBUFS, + libc::EISCONN => Self::EISCONN, + libc::ENOTCONN => Self::ENOTCONN, + libc::ETIMEDOUT => Self::ETIMEDOUT, + libc::ECONNREFUSED => Self::ECONNREFUSED, + libc::EHOSTUNREACH => Self::EHOSTUNREACH, + libc::EALREADY => Self::EALREADY, + libc::EINPROGRESS => Self::EINPROGRESS, + libc::ESTALE => Self::ESTALE, + libc::EDQUOT => Self::EDQUOT, + libc::ECANCELED => Self::ECANCELED, + libc::EOWNERDEAD => Self::EOWNERDEAD, + libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE, + libc::ENOTSUP => Self::ENOTSUP, + x => { + log::debug!("Unknown errno value: {}", x); + Self::EIO + } + }, + None => { + log::debug!("Other I/O error: {}", err); Self::EIO } } @@ -154,13 +161,13 @@ pub(crate) fn nix_from_oflags(oflags: wasi::__wasi_oflags_t) -> OFlag { nix_flags } -pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result { +pub(crate) fn filestat_from_nix(filestat: libc::stat) -> WasiResult { use std::convert::TryInto; - fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result { + fn filestat_to_timestamp(secs: u64, nsecs: u64) -> WasiResult { secs.checked_mul(1_000_000_000) .and_then(|sec_nsec| sec_nsec.checked_add(nsecs)) - .ok_or(Error::EOVERFLOW) + .ok_or(WasiError::EOVERFLOW) } let filetype = yanix::file::FileType::from_stat_st_mode(filestat.st_mode); @@ -195,7 +202,7 @@ pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result>(s: S) -> Result { +pub(crate) fn path_from_host>(s: S) -> WasiResult { helpers::path_from_slice(s.as_ref().as_bytes()).map(String::from) } diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs index d22d711c6b..2766838fa1 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs @@ -3,7 +3,7 @@ use crate::old::snapshot_0::host::Dirent; use crate::old::snapshot_0::hostcalls_impl::PathGet; use crate::old::snapshot_0::sys::{fdentry_impl::OsHandle, host_impl, unix::sys_impl}; -use crate::old::snapshot_0::{wasi, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; use std::convert::TryInto; use std::fs::File; use std::os::unix::fs::FileExt; @@ -15,21 +15,25 @@ pub(crate) fn fd_pread( file: &File, buf: &mut [u8], offset: wasi::__wasi_filesize_t, -) -> Result { +) -> WasiResult { file.read_at(buf, offset).map_err(Into::into) } -pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result { +pub(crate) fn fd_pwrite( + file: &File, + buf: &[u8], + offset: wasi::__wasi_filesize_t, +) -> WasiResult { file.write_at(buf, offset).map_err(Into::into) } -pub(crate) fn fd_fdstat_get(fd: &File) -> Result { +pub(crate) fn fd_fdstat_get(fd: &File) -> WasiResult { unsafe { yanix::fcntl::get_status_flags(fd.as_raw_fd()) } .map(host_impl::fdflags_from_nix) .map_err(Into::into) } -pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> { +pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> { let nix_flags = host_impl::nix_from_fdflags(fdflags); unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }.map_err(Into::into) } @@ -39,7 +43,7 @@ pub(crate) fn fd_advise( advice: wasi::__wasi_advice_t, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, -) -> Result<()> { +) -> WasiResult<()> { use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice}; let offset = offset.try_into()?; let len = len.try_into()?; @@ -50,12 +54,12 @@ pub(crate) fn fd_advise( wasi::__WASI_ADVICE_NOREUSE => PosixFadviseAdvice::NoReuse, wasi::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::Random, wasi::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::Normal, - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }; unsafe { posix_fadvise(file.as_raw_fd(), offset, len, host_advice) }.map_err(Into::into) } -pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> { +pub(crate) fn path_create_directory(resolved: PathGet) -> WasiResult<()> { use yanix::file::{mkdirat, Mode}; unsafe { mkdirat( @@ -67,7 +71,7 @@ pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> { .map_err(Into::into) } -pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { +pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { use yanix::file::{linkat, AtFlag}; unsafe { linkat( @@ -87,7 +91,7 @@ pub(crate) fn path_open( write: bool, oflags: wasi::__wasi_oflags_t, fs_flags: wasi::__wasi_fdflags_t, -) -> Result { +) -> WasiResult { use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag}; let mut nix_all_oflags = if read && write { @@ -136,7 +140,7 @@ pub(crate) fn path_open( } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } } Err(err) => { @@ -158,7 +162,7 @@ pub(crate) fn path_open( } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink { - return Err(Error::ELOOP); + return Err(WasiError::ELOOP); } } Err(err) => { @@ -169,7 +173,7 @@ pub(crate) fn path_open( // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on // a symlink. libc::EMLINK if !(nix_all_oflags & OFlag::NOFOLLOW).is_empty() => { - return Err(Error::ELOOP); + return Err(WasiError::ELOOP); } _ => {} } @@ -184,7 +188,7 @@ pub(crate) fn path_open( Ok(unsafe { File::from_raw_fd(new_fd) }) } -pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result { +pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> WasiResult { use std::cmp::min; use yanix::file::readlinkat; let read_link = unsafe { readlinkat(resolved.dirfd().as_raw_fd(), resolved.path()) } @@ -197,7 +201,7 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result Ok(copy_len) } -pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result { +pub(crate) fn fd_filestat_get(file: &std::fs::File) -> WasiResult { use yanix::file::fstat; unsafe { fstat(file.as_raw_fd()) } .map_err(Into::into) @@ -207,7 +211,7 @@ pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result Result { +) -> WasiResult { use yanix::file::{fstatat, AtFlag}; let atflags = match dirflags { 0 => AtFlag::empty(), @@ -224,7 +228,7 @@ pub(crate) fn path_filestat_set_times( st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { use std::time::{Duration, UNIX_EPOCH}; use yanix::filetime::*; @@ -234,7 +238,7 @@ pub(crate) fn path_filestat_set_times( let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0; if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } let symlink_nofollow = wasi::__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW != dirflags; @@ -265,7 +269,7 @@ pub(crate) fn path_filestat_set_times( .map_err(Into::into) } -pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { +pub(crate) fn path_remove_directory(resolved: PathGet) -> WasiResult<()> { use yanix::file::{unlinkat, AtFlag}; unsafe { unlinkat( @@ -280,7 +284,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { pub(crate) fn fd_readdir<'a>( os_handle: &'a mut OsHandle, cookie: wasi::__wasi_dircookie_t, -) -> Result> + 'a> { +) -> WasiResult> + 'a> { use yanix::dir::{DirIter, Entry, EntryExt, SeekLoc}; // Get an instance of `Dir`; this is host-specific due to intricasies diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs_helpers.rs index 609e42dc5c..0be360f3d5 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs_helpers.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs_helpers.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] #![allow(unused_unsafe)] use crate::old::snapshot_0::sys::host_impl; -use crate::old::snapshot_0::{wasi, Result}; +use crate::old::snapshot_0::wasi::{self, WasiResult}; use std::fs::File; use yanix::file::OFlag; @@ -36,7 +36,7 @@ pub(crate) fn path_open_rights( (needed_base, needed_inheriting) } -pub(crate) fn openat(dirfd: &File, path: &str) -> Result { +pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult { use std::os::unix::prelude::{AsRawFd, FromRawFd}; use yanix::file::{openat, Mode}; @@ -54,7 +54,7 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result { .map_err(Into::into) } -pub(crate) fn readlinkat(dirfd: &File, path: &str) -> Result { +pub(crate) fn readlinkat(dirfd: &File, path: &str) -> WasiResult { use std::os::unix::prelude::AsRawFd; use yanix::file::readlinkat; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/misc.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/misc.rs index e6e270159f..914a25d94a 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/misc.rs @@ -1,22 +1,24 @@ #![allow(non_camel_case_types)] #![allow(unused_unsafe)] use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData}; -use crate::old::snapshot_0::{wasi, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; use std::io; use yanix::clock::{clock_getres, clock_gettime, ClockId}; -fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result { +fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> WasiResult { // convert the supported clocks to libc types, or return EINVAL match clock_id { wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime), wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic), wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime), wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => Ok(ClockId::ThreadCPUTime), - _ => Err(Error::EINVAL), + _ => Err(WasiError::EINVAL), } } -pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result { +pub(crate) fn clock_res_get( + clock_id: wasi::__wasi_clockid_t, +) -> WasiResult { let clock_id = wasi_clock_id_to_unix(clock_id)?; let timespec = clock_getres(clock_id)?; @@ -26,18 +28,20 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result Result { +pub(crate) fn clock_time_get( + clock_id: wasi::__wasi_clockid_t, +) -> WasiResult { let clock_id = wasi_clock_id_to_unix(clock_id)?; let timespec = clock_gettime(clock_id)?; @@ -46,14 +50,14 @@ pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result, fd_events: Vec, events: &mut Vec, -) -> Result<()> { +) -> WasiResult<()> { use std::{convert::TryInto, os::unix::prelude::AsRawFd}; use yanix::poll::{poll, PollFd, PollFlags}; @@ -122,7 +126,7 @@ fn poll_oneoff_handle_timeout_event( fn poll_oneoff_handle_fd_event<'a>( ready_events: impl Iterator, yanix::poll::PollFd)>, events: &mut Vec, -) -> Result<()> { +) -> WasiResult<()> { use std::{convert::TryInto, os::unix::prelude::AsRawFd}; use yanix::{file::fionread, poll::PollFlags}; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/host_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/host_impl.rs index d867e51b6f..90ae925e43 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/host_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/host_impl.rs @@ -1,16 +1,16 @@ -use crate::old::snapshot_0::{wasi, Result}; +use crate::old::snapshot_0::wasi::{self, WasiResult}; use std::convert::TryInto; pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::RSYNC; -pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> Result { +pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> WasiResult { Ok(wasi::__wasi_device_t::from(dev)) } -pub(crate) fn stino_from_nix(ino: libc::ino_t) -> Result { +pub(crate) fn stino_from_nix(ino: libc::ino_t) -> WasiResult { Ok(wasi::__wasi_device_t::from(ino)) } -pub(crate) fn stnlink_from_nix(nlink: libc::nlink_t) -> Result { +pub(crate) fn stnlink_from_nix(nlink: libc::nlink_t) -> WasiResult { nlink.try_into().map_err(Into::into) } diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs index 86b1ec443e..efcff139a9 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs @@ -1,8 +1,8 @@ use crate::old::snapshot_0::hostcalls_impl::PathGet; -use crate::old::snapshot_0::Result; +use crate::old::snapshot_0::wasi::WasiResult; use std::os::unix::prelude::AsRawFd; -pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { +pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> { use yanix::file::{unlinkat, AtFlag}; unsafe { unlinkat( @@ -14,7 +14,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { .map_err(Into::into) } -pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { +pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> { use yanix::file::symlinkat; log::debug!("path_symlink old_path = {:?}", old_path); @@ -24,7 +24,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { .map_err(Into::into) } -pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { +pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { use yanix::file::renameat; unsafe { renameat( @@ -39,10 +39,10 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul pub(crate) mod fd_readdir_impl { use crate::old::snapshot_0::sys::fdentry_impl::OsHandle; - use crate::old::snapshot_0::Result; + use crate::old::snapshot_0::wasi::WasiResult; use yanix::dir::Dir; - pub(crate) fn get_dir_from_os_handle(os_handle: &mut OsHandle) -> Result> { + pub(crate) fn get_dir_from_os_handle(os_handle: &mut OsHandle) -> WasiResult> { // We need to duplicate the fd, because `opendir(3)`: // After a successful call to fdopendir(), fd is used internally by the implementation, // and should not otherwise be used by the application. diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs index d7e8288323..c5382556ab 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs @@ -20,13 +20,9 @@ cfg_if::cfg_if! { } } -use crate::old::snapshot_0::Result; use std::fs::{File, OpenOptions}; +use std::io::Result; pub(crate) fn dev_null() -> Result { - OpenOptions::new() - .read(true) - .write(true) - .open("/dev/null") - .map_err(Into::into) + OpenOptions::new().read(true).write(true).open("/dev/null") } diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/fdentry_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/fdentry_impl.rs index 4b1c6ba39e..b5a35833d6 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/fdentry_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/fdentry_impl.rs @@ -1,5 +1,5 @@ use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef}; -use crate::old::snapshot_0::{wasi, Error, Result}; +use crate::old::snapshot_0::wasi; use std::fs::File; use std::io; use std::mem::ManuallyDrop; @@ -57,7 +57,7 @@ pub(crate) fn descriptor_as_oshandle<'lifetime>( /// This function is unsafe because it operates on a raw file handle. pub(crate) unsafe fn determine_type_and_access_rights( handle: &Handle, -) -> Result<( +) -> io::Result<( wasi::__wasi_filetype_t, wasi::__wasi_rights_t, wasi::__wasi_rights_t, @@ -88,7 +88,7 @@ pub(crate) unsafe fn determine_type_and_access_rights( /// This function is unsafe because it operates on a raw file handle. pub(crate) unsafe fn determine_type_rights( handle: &Handle, -) -> Result<( +) -> io::Result<( wasi::__wasi_filetype_t, wasi::__wasi_rights_t, wasi::__wasi_rights_t, @@ -106,7 +106,7 @@ pub(crate) unsafe fn determine_type_rights( } else if file_type.is_disk() { // disk file: file, dir or disk device let file = std::mem::ManuallyDrop::new(File::from_raw_handle(handle.as_raw_handle())); - let meta = file.metadata().map_err(|_| Error::EINVAL)?; + let meta = file.metadata()?; if meta.is_dir() { ( wasi::__WASI_FILETYPE_DIRECTORY, @@ -120,7 +120,7 @@ pub(crate) unsafe fn determine_type_rights( wasi::RIGHTS_REGULAR_FILE_INHERITING, ) } else { - return Err(Error::EINVAL); + return Err(io::Error::from_raw_os_error(libc::EINVAL)); } } else if file_type.is_pipe() { // pipe object: socket, named pipe or anonymous pipe @@ -131,7 +131,7 @@ pub(crate) unsafe fn determine_type_rights( wasi::RIGHTS_SOCKET_INHERITING, ) } else { - return Err(Error::EINVAL); + return Err(io::Error::from_raw_os_error(libc::EINVAL)); } }; Ok((file_type, rights_base, rights_inheriting)) diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs index 036c5010e4..53d8073724 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs @@ -3,7 +3,7 @@ #![allow(non_snake_case)] #![allow(unused)] use crate::old::snapshot_0::host::FileType; -use crate::old::snapshot_0::{error::FromRawOsError, wasi, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; use std::convert::TryInto; use std::ffi::OsStr; use std::fs::OpenOptions; @@ -15,34 +15,42 @@ use std::time::{SystemTime, UNIX_EPOCH}; use winapi::shared::winerror; use winx::file::{AccessMode, Attributes, CreationDisposition, Flags}; -impl FromRawOsError for Error { - fn from_raw_os_error(code: i32) -> Self { - // TODO: implement error mapping between Windows and WASI - match code as u32 { - winerror::ERROR_SUCCESS => Self::ESUCCESS, - winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG, - winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT, - winerror::ERROR_PATH_NOT_FOUND => Self::ENOENT, - winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE, - winerror::ERROR_ACCESS_DENIED => Self::EACCES, - winerror::ERROR_SHARING_VIOLATION => Self::EACCES, - winerror::ERROR_PRIVILEGE_NOT_HELD => Self::ENOTCAPABLE, // TODO is this the correct mapping? - winerror::ERROR_INVALID_HANDLE => Self::EBADF, - winerror::ERROR_INVALID_NAME => Self::ENOENT, - winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM, - winerror::ERROR_OUTOFMEMORY => Self::ENOMEM, - winerror::ERROR_DIR_NOT_EMPTY => Self::ENOTEMPTY, - winerror::ERROR_NOT_READY => Self::EBUSY, - winerror::ERROR_BUSY => Self::EBUSY, - winerror::ERROR_NOT_SUPPORTED => Self::ENOTSUP, - winerror::ERROR_FILE_EXISTS => Self::EEXIST, - winerror::ERROR_BROKEN_PIPE => Self::EPIPE, - winerror::ERROR_BUFFER_OVERFLOW => Self::ENAMETOOLONG, - winerror::ERROR_NOT_A_REPARSE_POINT => Self::EINVAL, - winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL, - winerror::ERROR_DIRECTORY => Self::ENOTDIR, - winerror::ERROR_ALREADY_EXISTS => Self::EEXIST, - _ => Self::ENOTSUP, +impl From for WasiError { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(code) => match code as u32 { + winerror::ERROR_SUCCESS => Self::ESUCCESS, + winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG, + winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT, + winerror::ERROR_PATH_NOT_FOUND => Self::ENOENT, + winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE, + winerror::ERROR_ACCESS_DENIED => Self::EACCES, + winerror::ERROR_SHARING_VIOLATION => Self::EACCES, + winerror::ERROR_PRIVILEGE_NOT_HELD => Self::ENOTCAPABLE, + winerror::ERROR_INVALID_HANDLE => Self::EBADF, + winerror::ERROR_INVALID_NAME => Self::ENOENT, + winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM, + winerror::ERROR_OUTOFMEMORY => Self::ENOMEM, + winerror::ERROR_DIR_NOT_EMPTY => Self::ENOTEMPTY, + winerror::ERROR_NOT_READY => Self::EBUSY, + winerror::ERROR_BUSY => Self::EBUSY, + winerror::ERROR_NOT_SUPPORTED => Self::ENOTSUP, + winerror::ERROR_FILE_EXISTS => Self::EEXIST, + winerror::ERROR_BROKEN_PIPE => Self::EPIPE, + winerror::ERROR_BUFFER_OVERFLOW => Self::ENAMETOOLONG, + winerror::ERROR_NOT_A_REPARSE_POINT => Self::EINVAL, + winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL, + winerror::ERROR_DIRECTORY => Self::ENOTDIR, + winerror::ERROR_ALREADY_EXISTS => Self::EEXIST, + x => { + log::debug!("unknown error value: {}", x); + Self::EIO + } + }, + None => { + log::debug!("Other I/O error: {}", err); + Self::EIO + } } } } @@ -137,15 +145,15 @@ fn change_time(file: &File) -> io::Result { winx::file::change_time(file) } -fn systemtime_to_timestamp(st: SystemTime) -> Result { +fn systemtime_to_timestamp(st: SystemTime) -> WasiResult { st.duration_since(UNIX_EPOCH) - .map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH + .map_err(|_| WasiError::EINVAL)? // date earlier than UNIX_EPOCH .as_nanos() .try_into() .map_err(Into::into) // u128 doesn't fit into u64 } -pub(crate) fn filestat_from_win(file: &File) -> Result { +pub(crate) fn filestat_from_win(file: &File) -> WasiResult { let metadata = file.metadata()?; Ok(wasi::__wasi_filestat_t { dev: device_id(file)?, @@ -163,7 +171,7 @@ pub(crate) fn filestat_from_win(file: &File) -> Result /// /// NB WASI spec requires OS string to be valid UTF-8. Otherwise, /// `__WASI_ERRNO_ILSEQ` error is returned. -pub(crate) fn path_from_host>(s: S) -> Result { +pub(crate) fn path_from_host>(s: S) -> WasiResult { let vec: Vec = s.as_ref().encode_wide().collect(); - String::from_utf16(&vec).map_err(|_| Error::EILSEQ) + String::from_utf16(&vec).map_err(|_| WasiError::EILSEQ) } diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs index cc157e7882..f0f7453c7e 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs @@ -8,7 +8,7 @@ use crate::old::snapshot_0::hostcalls_impl::{fd_filestat_set_times_impl, PathGet use crate::old::snapshot_0::sys::fdentry_impl::determine_type_rights; use crate::old::snapshot_0::sys::host_impl::{self, path_from_host}; use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::PathGetExt; -use crate::old::snapshot_0::{wasi, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; use log::{debug, trace}; use std::convert::TryInto; use std::fs::{File, Metadata, OpenOptions}; @@ -44,16 +44,20 @@ pub(crate) fn fd_pread( file: &File, buf: &mut [u8], offset: wasi::__wasi_filesize_t, -) -> Result { +) -> WasiResult { 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: wasi::__wasi_filesize_t) -> Result { +pub(crate) fn fd_pwrite( + file: &File, + buf: &[u8], + offset: wasi::__wasi_filesize_t, +) -> WasiResult { write_at(file, buf, offset).map_err(Into::into) } -pub(crate) fn fd_fdstat_get(fd: &File) -> Result { +pub(crate) fn fd_fdstat_get(fd: &File) -> WasiResult { let mut fdflags = 0; let handle = unsafe { fd.as_raw_handle() }; @@ -79,7 +83,7 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result { Ok(fdflags) } -pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> { +pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> { unimplemented!("fd_fdstat_set_flags") } @@ -88,7 +92,7 @@ pub(crate) fn fd_advise( advice: wasi::__wasi_advice_t, _offset: wasi::__wasi_filesize_t, _len: wasi::__wasi_filesize_t, -) -> Result<()> { +) -> WasiResult<()> { match advice { wasi::__WASI_ADVICE_DONTNEED | wasi::__WASI_ADVICE_SEQUENTIAL @@ -96,18 +100,18 @@ pub(crate) fn fd_advise( | wasi::__WASI_ADVICE_NOREUSE | wasi::__WASI_ADVICE_RANDOM | wasi::__WASI_ADVICE_NORMAL => {} - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), } Ok(()) } -pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> { +pub(crate) fn path_create_directory(resolved: PathGet) -> WasiResult<()> { let path = resolved.concatenate()?; std::fs::create_dir(&path).map_err(Into::into) } -pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { +pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { unimplemented!("path_link") } @@ -117,7 +121,7 @@ pub(crate) fn path_open( write: bool, oflags: wasi::__wasi_oflags_t, fdflags: wasi::__wasi_fdflags_t, -) -> Result { +) -> WasiResult { use winx::file::{AccessMode, CreationDisposition, Flags}; // convert open flags @@ -143,11 +147,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(Error::ELOOP); + return Err(WasiError::ELOOP); } // check if we are trying to open a file as a dir if file_type.is_file() && oflags & wasi::__WASI_OFLAGS_DIRECTORY != 0 { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } } Err(err) => match err.raw_os_error() { @@ -162,7 +166,7 @@ pub(crate) fn path_open( } None => { log::debug!("Inconvertible OS error: {}", err); - return Err(Error::EIO); + return Err(WasiError::EIO); } }, } @@ -236,7 +240,7 @@ fn dirent_from_path>( path: P, name: &str, cookie: wasi::__wasi_dircookie_t, -) -> Result { +) -> WasiResult { let path = path.as_ref(); trace!("dirent_from_path: opening {}", path.to_string_lossy()); @@ -285,7 +289,7 @@ fn dirent_from_path>( pub(crate) fn fd_readdir( fd: &File, cookie: wasi::__wasi_dircookie_t, -) -> Result>> { +) -> WasiResult>> { use winx::file::get_file_path; let cookie = cookie.try_into()?; @@ -321,7 +325,7 @@ pub(crate) fn fd_readdir( Ok(iter.skip(cookie)) } -pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result { +pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> WasiResult { use winx::file::get_file_path; let path = resolved.concatenate()?; @@ -335,8 +339,8 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result let dir_path = PathBuf::from(strip_extended_prefix(dir_path)); let target_path = target_path .strip_prefix(dir_path) - .map_err(|_| Error::ENOTCAPABLE) - .and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?; + .map_err(|_| WasiError::ENOTCAPABLE) + .and_then(|path| path.to_str().map(String::from).ok_or(WasiError::EILSEQ))?; if buf.len() > 0 { let mut chars = target_path.chars(); @@ -358,7 +362,7 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result } } -fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> Result> { +fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> WasiResult> { if resolved.path().ends_with('/') { let suffix = resolved.path().trim_end_matches('/'); concatenate(resolved.dirfd(), Path::new(suffix)).map(Some) @@ -367,7 +371,7 @@ fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> Result Result<()> { +pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { use std::fs; let old_path = resolved_old.concatenate()?; @@ -378,12 +382,12 @@ 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(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } // Second sanity check: check we're not trying to rename a file into a path // ending in a trailing slash. if old_path.is_file() && resolved_new.path().ends_with('/') { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } // TODO handle symlinks @@ -399,7 +403,7 @@ 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() { - return Err(Error::EISDIR); + return Err(WasiError::EISDIR); } else { // Ok, let's try removing an empty dir at new_path if it exists // and is a nonempty dir. @@ -413,7 +417,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul // a file instead of a dir, and if so, throw ENOTDIR. if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved_old)? { if path.is_file() { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } } } @@ -424,19 +428,19 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Error::EIO) + Err(WasiError::EIO) } } } -pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result { +pub(crate) fn fd_filestat_get(file: &std::fs::File) -> WasiResult { host_impl::filestat_from_win(file) } pub(crate) fn path_filestat_get( resolved: PathGet, dirflags: wasi::__wasi_lookupflags_t, -) -> Result { +) -> WasiResult { let path = resolved.concatenate()?; let file = File::open(path)?; host_impl::filestat_from_win(&file) @@ -448,7 +452,7 @@ pub(crate) fn path_filestat_set_times( st_atim: wasi::__wasi_timestamp_t, mut st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { use winx::file::AccessMode; let path = resolved.concatenate()?; let file = OpenOptions::new() @@ -457,7 +461,7 @@ pub(crate) fn path_filestat_set_times( fd_filestat_set_times_impl(&file, st_atim, st_mtim, fst_flags) } -pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { +pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> { use std::os::windows::fs::{symlink_dir, symlink_file}; let old_path = concatenate(resolved.dirfd(), Path::new(old_path))?; @@ -479,14 +483,14 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { winerror::ERROR_ACCESS_DENIED => { // does the target exist? if new_path.exists() { - return Err(Error::EEXIST); + return Err(WasiError::EEXIST); } } winerror::ERROR_INVALID_NAME => { // does the target without trailing slashes exist? if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved)? { if path.exists() { - return Err(Error::EEXIST); + return Err(WasiError::EEXIST); } } } @@ -497,12 +501,12 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Error::EIO) + Err(WasiError::EIO) } } } -pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { +pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> { use std::fs; let path = resolved.concatenate()?; @@ -532,19 +536,19 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Error::EIO) + Err(WasiError::EIO) } } } else if file_type.is_dir() { - Err(Error::EISDIR) + Err(WasiError::EISDIR) } else if file_type.is_file() { fs::remove_file(path).map_err(Into::into) } else { - Err(Error::EINVAL) + Err(WasiError::EINVAL) } } -pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { +pub(crate) fn path_remove_directory(resolved: PathGet) -> WasiResult<()> { let path = resolved.concatenate()?; std::fs::remove_dir(&path).map_err(Into::into) } diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs_helpers.rs index a89a37f6e0..63efce5a4c 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs_helpers.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs_helpers.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types)] use crate::old::snapshot_0::hostcalls_impl::PathGet; -use crate::old::snapshot_0::{wasi, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; use std::ffi::{OsStr, OsString}; use std::fs::File; use std::os::windows::ffi::{OsStrExt, OsStringExt}; @@ -8,11 +8,11 @@ use std::path::{Path, PathBuf}; use winapi::shared::winerror; pub(crate) trait PathGetExt { - fn concatenate(&self) -> Result; + fn concatenate(&self) -> WasiResult; } impl PathGetExt for PathGet { - fn concatenate(&self) -> Result { + fn concatenate(&self) -> WasiResult { concatenate(self.dirfd(), Path::new(self.path())) } } @@ -46,7 +46,7 @@ pub(crate) fn path_open_rights( (needed_base, needed_inheriting) } -pub(crate) fn openat(dirfd: &File, path: &str) -> Result { +pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult { use std::fs::OpenOptions; use std::os::windows::fs::OpenOptionsExt; use winx::file::Flags; @@ -63,13 +63,13 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result { if let Some(code) = err.raw_os_error() { log::debug!("openat error={:?}", code); if code as u32 == winerror::ERROR_INVALID_NAME { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } } Err(err.into()) } -pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result { +pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> WasiResult { use winx::file::get_file_path; let path = concatenate(dirfd, Path::new(s_path))?; @@ -83,8 +83,8 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result { let dir_path = PathBuf::from(strip_extended_prefix(dir_path)); let target_path = target_path .strip_prefix(dir_path) - .map_err(|_| Error::ENOTCAPABLE)?; - let target_path = target_path.to_str().ok_or(Error::EILSEQ)?; + .map_err(|_| WasiError::ENOTCAPABLE)?; + let target_path = target_path.to_str().ok_or(WasiError::EILSEQ)?; return Ok(target_path.to_owned()); } Err(e) => e, @@ -96,7 +96,7 @@ 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() { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } } } @@ -113,13 +113,13 @@ pub(crate) fn strip_extended_prefix>(path: P) -> OsString { } } -pub(crate) fn concatenate>(dirfd: &File, path: P) -> Result { +pub(crate) fn concatenate>(dirfd: &File, path: P) -> WasiResult { use winx::file::get_file_path; // WASI is not able to deal with absolute paths // so error out if absolute if path.as_ref().is_absolute() { - return Err(Error::ENOTCAPABLE); + return Err(WasiError::ENOTCAPABLE); } let dir_path = get_file_path(dirfd)?; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs index bf8df626cd..395adce4f0 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs @@ -4,7 +4,8 @@ use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData}; use crate::old::snapshot_0::memory::*; use crate::old::snapshot_0::sys::host_impl; -use crate::old::snapshot_0::{wasi, wasi32, Error, Result}; +use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult}; +use crate::old::snapshot_0::wasi32; use cpu_time::{ProcessTime, ThreadTime}; use lazy_static::lazy_static; use std::convert::TryInto; @@ -17,7 +18,9 @@ lazy_static! { // Timer resolution on Windows is really hard. We may consider exposing the resolution of the respective // timers as an associated function in the future. -pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result { +pub(crate) fn clock_res_get( + clock_id: wasi::__wasi_clockid_t, +) -> WasiResult { Ok(match clock_id { // This is the best that we can do with std::time::SystemTime. // Rust uses GetSystemTimeAsFileTime, which is said to have the resolution of @@ -61,17 +64,19 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result 100, - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }) } -pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result { +pub(crate) fn clock_time_get( + clock_id: wasi::__wasi_clockid_t, +) -> WasiResult { let duration = match clock_id { wasi::__WASI_CLOCKID_REALTIME => get_monotonic_time(), wasi::__WASI_CLOCKID_MONOTONIC => get_realtime_time()?, wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => get_proc_cputime()?, wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => get_thread_cputime()?, - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }; duration.as_nanos().try_into().map_err(Into::into) } @@ -80,7 +85,7 @@ pub(crate) fn poll_oneoff( timeout: Option, fd_events: Vec, events: &mut Vec, -) -> Result> { +) -> WasiResult> { unimplemented!("poll_oneoff") } @@ -94,17 +99,17 @@ fn get_monotonic_time() -> Duration { START_MONOTONIC.elapsed() } -fn get_realtime_time() -> Result { +fn get_realtime_time() -> WasiResult { SystemTime::now() .duration_since(UNIX_EPOCH) - .map_err(|_| Error::EFAULT) + .map_err(|_| WasiError::EFAULT) } -fn get_proc_cputime() -> Result { +fn get_proc_cputime() -> WasiResult { Ok(ProcessTime::try_now()?.as_duration()) } -fn get_thread_cputime() -> Result { +fn get_thread_cputime() -> WasiResult { Ok(ThreadTime::try_now()?.as_duration()) } diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs index 35d00ac935..7783272946 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs @@ -2,13 +2,9 @@ pub(crate) mod fdentry_impl; pub(crate) mod host_impl; pub(crate) mod hostcalls_impl; -use crate::old::snapshot_0::Result; use std::fs::{File, OpenOptions}; +use std::io::Result; pub(crate) fn dev_null() -> Result { - OpenOptions::new() - .read(true) - .write(true) - .open("NUL") - .map_err(Into::into) + OpenOptions::new().read(true).write(true).open("NUL") } diff --git a/crates/wasi-common/src/old/snapshot_0/wasi.rs b/crates/wasi-common/src/old/snapshot_0/wasi.rs index 63a08e8c5e..966fed9bbd 100644 --- a/crates/wasi-common/src/old/snapshot_0/wasi.rs +++ b/crates/wasi-common/src/old/snapshot_0/wasi.rs @@ -10,6 +10,115 @@ use wig::witx_wasi_types; witx_wasi_types!("old/snapshot_0" "wasi_unstable"); +pub type WasiResult = Result; + +#[derive(Clone, Copy, Debug, thiserror::Error, Eq, PartialEq)] +#[repr(u16)] +#[error("{:?} ({})", self, strerror(*self as __wasi_errno_t))] +pub enum WasiError { + ESUCCESS = __WASI_ERRNO_SUCCESS, + E2BIG = __WASI_ERRNO_2BIG, + EACCES = __WASI_ERRNO_ACCES, + EADDRINUSE = __WASI_ERRNO_ADDRINUSE, + EADDRNOTAVAIL = __WASI_ERRNO_ADDRNOTAVAIL, + EAFNOSUPPORT = __WASI_ERRNO_AFNOSUPPORT, + EAGAIN = __WASI_ERRNO_AGAIN, + EALREADY = __WASI_ERRNO_ALREADY, + EBADF = __WASI_ERRNO_BADF, + EBADMSG = __WASI_ERRNO_BADMSG, + EBUSY = __WASI_ERRNO_BUSY, + ECANCELED = __WASI_ERRNO_CANCELED, + ECHILD = __WASI_ERRNO_CHILD, + ECONNABORTED = __WASI_ERRNO_CONNABORTED, + ECONNREFUSED = __WASI_ERRNO_CONNREFUSED, + ECONNRESET = __WASI_ERRNO_CONNRESET, + EDEADLK = __WASI_ERRNO_DEADLK, + EDESTADDRREQ = __WASI_ERRNO_DESTADDRREQ, + EDOM = __WASI_ERRNO_DOM, + EDQUOT = __WASI_ERRNO_DQUOT, + EEXIST = __WASI_ERRNO_EXIST, + EFAULT = __WASI_ERRNO_FAULT, + EFBIG = __WASI_ERRNO_FBIG, + EHOSTUNREACH = __WASI_ERRNO_HOSTUNREACH, + EIDRM = __WASI_ERRNO_IDRM, + EILSEQ = __WASI_ERRNO_ILSEQ, + EINPROGRESS = __WASI_ERRNO_INPROGRESS, + EINTR = __WASI_ERRNO_INTR, + EINVAL = __WASI_ERRNO_INVAL, + EIO = __WASI_ERRNO_IO, + EISCONN = __WASI_ERRNO_ISCONN, + EISDIR = __WASI_ERRNO_ISDIR, + ELOOP = __WASI_ERRNO_LOOP, + EMFILE = __WASI_ERRNO_MFILE, + EMLINK = __WASI_ERRNO_MLINK, + EMSGSIZE = __WASI_ERRNO_MSGSIZE, + EMULTIHOP = __WASI_ERRNO_MULTIHOP, + ENAMETOOLONG = __WASI_ERRNO_NAMETOOLONG, + ENETDOWN = __WASI_ERRNO_NETDOWN, + ENETRESET = __WASI_ERRNO_NETRESET, + ENETUNREACH = __WASI_ERRNO_NETUNREACH, + ENFILE = __WASI_ERRNO_NFILE, + ENOBUFS = __WASI_ERRNO_NOBUFS, + ENODEV = __WASI_ERRNO_NODEV, + ENOENT = __WASI_ERRNO_NOENT, + ENOEXEC = __WASI_ERRNO_NOEXEC, + ENOLCK = __WASI_ERRNO_NOLCK, + ENOLINK = __WASI_ERRNO_NOLINK, + ENOMEM = __WASI_ERRNO_NOMEM, + ENOMSG = __WASI_ERRNO_NOMSG, + ENOPROTOOPT = __WASI_ERRNO_NOPROTOOPT, + ENOSPC = __WASI_ERRNO_NOSPC, + ENOSYS = __WASI_ERRNO_NOSYS, + ENOTCONN = __WASI_ERRNO_NOTCONN, + ENOTDIR = __WASI_ERRNO_NOTDIR, + ENOTEMPTY = __WASI_ERRNO_NOTEMPTY, + ENOTRECOVERABLE = __WASI_ERRNO_NOTRECOVERABLE, + ENOTSOCK = __WASI_ERRNO_NOTSOCK, + ENOTSUP = __WASI_ERRNO_NOTSUP, + ENOTTY = __WASI_ERRNO_NOTTY, + ENXIO = __WASI_ERRNO_NXIO, + EOVERFLOW = __WASI_ERRNO_OVERFLOW, + EOWNERDEAD = __WASI_ERRNO_OWNERDEAD, + EPERM = __WASI_ERRNO_PERM, + EPIPE = __WASI_ERRNO_PIPE, + EPROTO = __WASI_ERRNO_PROTO, + EPROTONOSUPPORT = __WASI_ERRNO_PROTONOSUPPORT, + EPROTOTYPE = __WASI_ERRNO_PROTOTYPE, + ERANGE = __WASI_ERRNO_RANGE, + EROFS = __WASI_ERRNO_ROFS, + ESPIPE = __WASI_ERRNO_SPIPE, + ESRCH = __WASI_ERRNO_SRCH, + ESTALE = __WASI_ERRNO_STALE, + ETIMEDOUT = __WASI_ERRNO_TIMEDOUT, + ETXTBSY = __WASI_ERRNO_TXTBSY, + EXDEV = __WASI_ERRNO_XDEV, + ENOTCAPABLE = __WASI_ERRNO_NOTCAPABLE, +} + +impl WasiError { + pub fn as_raw_errno(self) -> __wasi_errno_t { + self as __wasi_errno_t + } +} + +impl From for WasiError { + fn from(_err: std::convert::Infallible) -> Self { + unreachable!() + } +} + +impl From for WasiError { + fn from(_err: std::num::TryFromIntError) -> Self { + Self::EOVERFLOW + } +} + +impl From for WasiError { + fn from(_err: std::str::Utf8Error) -> Self { + Self::EILSEQ + } +} + pub(crate) const RIGHTS_ALL: __wasi_rights_t = __WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_READ | __WASI_RIGHTS_FD_SEEK diff --git a/crates/wasi-common/src/sys/unix/bsd/host_impl.rs b/crates/wasi-common/src/sys/unix/bsd/host_impl.rs index 53f0782deb..d2ab148fc6 100644 --- a/crates/wasi-common/src/sys/unix/bsd/host_impl.rs +++ b/crates/wasi-common/src/sys/unix/bsd/host_impl.rs @@ -1,12 +1,12 @@ -use crate::{wasi, Result}; +use crate::wasi::{self, WasiResult}; use std::convert::TryFrom; pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::SYNC; -pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> Result { +pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> WasiResult { wasi::__wasi_device_t::try_from(dev).map_err(Into::into) } -pub(crate) fn stino_from_nix(ino: libc::ino_t) -> Result { +pub(crate) fn stino_from_nix(ino: libc::ino_t) -> WasiResult { wasi::__wasi_device_t::try_from(ino).map_err(Into::into) } diff --git a/crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs b/crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs index b82b917c1c..9b56bb76a0 100644 --- a/crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs +++ b/crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs @@ -1,8 +1,8 @@ use crate::hostcalls_impl::PathGet; -use crate::{Error, Result}; +use crate::wasi::{WasiError, WasiResult}; use std::os::unix::prelude::AsRawFd; -pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { +pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> { use yanix::file::{unlinkat, AtFlag}; match unsafe { unlinkat( @@ -32,7 +32,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory { - return Err(Error::EISDIR); + return Err(WasiError::EISDIR); } } Err(err) => { @@ -47,7 +47,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { } } -pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { +pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> { use yanix::file::{fstatat, symlinkat, AtFlag}; log::debug!("path_symlink old_path = {:?}", old_path); @@ -69,7 +69,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { AtFlag::SYMLINK_NOFOLLOW, ) } { - Ok(_) => return Err(Error::EEXIST), + Ok(_) => return Err(WasiError::EEXIST), Err(err) => { log::debug!("path_symlink fstatat error: {:?}", err); } @@ -81,7 +81,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { } } -pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { +pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { use yanix::file::{fstatat, renameat, AtFlag}; match unsafe { renameat( @@ -113,9 +113,9 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul Ok(_) => { // check if destination contains a trailing slash if resolved_new.path().contains('/') { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } else { - return Err(Error::ENOENT); + return Err(WasiError::ENOENT); } } Err(err) => { @@ -132,13 +132,13 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul pub(crate) mod fd_readdir_impl { use crate::sys::fdentry_impl::OsHandle; - use crate::Result; + use crate::wasi::WasiResult; use std::sync::{Mutex, MutexGuard}; use yanix::dir::Dir; pub(crate) fn get_dir_from_os_handle<'a>( os_handle: &'a mut OsHandle, - ) -> Result> { + ) -> WasiResult> { let dir = match os_handle.dir { Some(ref mut dir) => dir, None => { diff --git a/crates/wasi-common/src/sys/unix/fdentry_impl.rs b/crates/wasi-common/src/sys/unix/fdentry_impl.rs index 2ba4bd0c13..7a45e28c13 100644 --- a/crates/wasi-common/src/sys/unix/fdentry_impl.rs +++ b/crates/wasi-common/src/sys/unix/fdentry_impl.rs @@ -1,5 +1,5 @@ use crate::fdentry::{Descriptor, OsHandleRef}; -use crate::{sys::unix::sys_impl, wasi, Error, Result}; +use crate::{sys::unix::sys_impl, wasi}; use std::fs::File; use std::io; use std::mem::ManuallyDrop; @@ -33,7 +33,7 @@ pub(crate) fn descriptor_as_oshandle<'lifetime>( /// This function is unsafe because it operates on a raw file descriptor. pub(crate) unsafe fn determine_type_and_access_rights( fd: &Fd, -) -> Result<( +) -> io::Result<( wasi::__wasi_filetype_t, wasi::__wasi_rights_t, wasi::__wasi_rights_t, @@ -57,7 +57,7 @@ pub(crate) unsafe fn determine_type_and_access_rights( /// This function is unsafe because it operates on a raw file descriptor. pub(crate) unsafe fn determine_type_rights( fd: &Fd, -) -> Result<( +) -> io::Result<( wasi::__wasi_filetype_t, wasi::__wasi_rights_t, wasi::__wasi_rights_t, @@ -117,7 +117,7 @@ pub(crate) unsafe fn determine_type_rights( wasi::RIGHTS_SOCKET_BASE, wasi::RIGHTS_SOCKET_INHERITING, ), - _ => return Err(Error::EINVAL), + _ => return Err(io::Error::from_raw_os_error(libc::EINVAL)), } } else if ft.is_fifo() { log::debug!("Host fd {:?} is a fifo", fd.as_raw_fd()); @@ -128,7 +128,7 @@ pub(crate) unsafe fn determine_type_rights( ) } else { log::debug!("Host fd {:?} is unknown", fd.as_raw_fd()); - return Err(Error::EINVAL); + return Err(io::Error::from_raw_os_error(libc::EINVAL)); } }; diff --git a/crates/wasi-common/src/sys/unix/host_impl.rs b/crates/wasi-common/src/sys/unix/host_impl.rs index dea0b106eb..3a3010b1f7 100644 --- a/crates/wasi-common/src/sys/unix/host_impl.rs +++ b/crates/wasi-common/src/sys/unix/host_impl.rs @@ -3,92 +3,101 @@ #![allow(non_snake_case)] #![allow(dead_code)] use crate::host::FileType; -use crate::{error::FromRawOsError, helpers, sys::unix::sys_impl, wasi, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; +use crate::{helpers, sys::unix::sys_impl}; use std::ffi::OsStr; +use std::io; use std::os::unix::prelude::OsStrExt; use yanix::file::OFlag; pub(crate) use sys_impl::host_impl::*; -impl FromRawOsError for Error { - fn from_raw_os_error(code: i32) -> Self { - match code { - libc::EPERM => Self::EPERM, - libc::ENOENT => Self::ENOENT, - libc::ESRCH => Self::ESRCH, - libc::EINTR => Self::EINTR, - libc::EIO => Self::EIO, - libc::ENXIO => Self::ENXIO, - libc::E2BIG => Self::E2BIG, - libc::ENOEXEC => Self::ENOEXEC, - libc::EBADF => Self::EBADF, - libc::ECHILD => Self::ECHILD, - libc::EAGAIN => Self::EAGAIN, - libc::ENOMEM => Self::ENOMEM, - libc::EACCES => Self::EACCES, - libc::EFAULT => Self::EFAULT, - libc::EBUSY => Self::EBUSY, - libc::EEXIST => Self::EEXIST, - libc::EXDEV => Self::EXDEV, - libc::ENODEV => Self::ENODEV, - libc::ENOTDIR => Self::ENOTDIR, - libc::EISDIR => Self::EISDIR, - libc::EINVAL => Self::EINVAL, - libc::ENFILE => Self::ENFILE, - libc::EMFILE => Self::EMFILE, - libc::ENOTTY => Self::ENOTTY, - libc::ETXTBSY => Self::ETXTBSY, - libc::EFBIG => Self::EFBIG, - libc::ENOSPC => Self::ENOSPC, - libc::ESPIPE => Self::ESPIPE, - libc::EROFS => Self::EROFS, - libc::EMLINK => Self::EMLINK, - libc::EPIPE => Self::EPIPE, - libc::EDOM => Self::EDOM, - libc::ERANGE => Self::ERANGE, - libc::EDEADLK => Self::EDEADLK, - libc::ENAMETOOLONG => Self::ENAMETOOLONG, - libc::ENOLCK => Self::ENOLCK, - libc::ENOSYS => Self::ENOSYS, - libc::ENOTEMPTY => Self::ENOTEMPTY, - libc::ELOOP => Self::ELOOP, - libc::ENOMSG => Self::ENOMSG, - libc::EIDRM => Self::EIDRM, - libc::ENOLINK => Self::ENOLINK, - libc::EPROTO => Self::EPROTO, - libc::EMULTIHOP => Self::EMULTIHOP, - libc::EBADMSG => Self::EBADMSG, - libc::EOVERFLOW => Self::EOVERFLOW, - libc::EILSEQ => Self::EILSEQ, - libc::ENOTSOCK => Self::ENOTSOCK, - libc::EDESTADDRREQ => Self::EDESTADDRREQ, - libc::EMSGSIZE => Self::EMSGSIZE, - libc::EPROTOTYPE => Self::EPROTOTYPE, - libc::ENOPROTOOPT => Self::ENOPROTOOPT, - libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT, - libc::EAFNOSUPPORT => Self::EAFNOSUPPORT, - libc::EADDRINUSE => Self::EADDRINUSE, - libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL, - libc::ENETDOWN => Self::ENETDOWN, - libc::ENETUNREACH => Self::ENETUNREACH, - libc::ENETRESET => Self::ENETRESET, - libc::ECONNABORTED => Self::ECONNABORTED, - libc::ECONNRESET => Self::ECONNRESET, - libc::ENOBUFS => Self::ENOBUFS, - libc::EISCONN => Self::EISCONN, - libc::ENOTCONN => Self::ENOTCONN, - libc::ETIMEDOUT => Self::ETIMEDOUT, - libc::ECONNREFUSED => Self::ECONNREFUSED, - libc::EHOSTUNREACH => Self::EHOSTUNREACH, - libc::EALREADY => Self::EALREADY, - libc::EINPROGRESS => Self::EINPROGRESS, - libc::ESTALE => Self::ESTALE, - libc::EDQUOT => Self::EDQUOT, - libc::ECANCELED => Self::ECANCELED, - libc::EOWNERDEAD => Self::EOWNERDEAD, - libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE, - x => { - log::debug!("Unknown errno value: {}", x); +impl From for WasiError { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(code) => match code { + libc::EPERM => Self::EPERM, + libc::ENOENT => Self::ENOENT, + libc::ESRCH => Self::ESRCH, + libc::EINTR => Self::EINTR, + libc::EIO => Self::EIO, + libc::ENXIO => Self::ENXIO, + libc::E2BIG => Self::E2BIG, + libc::ENOEXEC => Self::ENOEXEC, + libc::EBADF => Self::EBADF, + libc::ECHILD => Self::ECHILD, + libc::EAGAIN => Self::EAGAIN, + libc::ENOMEM => Self::ENOMEM, + libc::EACCES => Self::EACCES, + libc::EFAULT => Self::EFAULT, + libc::EBUSY => Self::EBUSY, + libc::EEXIST => Self::EEXIST, + libc::EXDEV => Self::EXDEV, + libc::ENODEV => Self::ENODEV, + libc::ENOTDIR => Self::ENOTDIR, + libc::EISDIR => Self::EISDIR, + libc::EINVAL => Self::EINVAL, + libc::ENFILE => Self::ENFILE, + libc::EMFILE => Self::EMFILE, + libc::ENOTTY => Self::ENOTTY, + libc::ETXTBSY => Self::ETXTBSY, + libc::EFBIG => Self::EFBIG, + libc::ENOSPC => Self::ENOSPC, + libc::ESPIPE => Self::ESPIPE, + libc::EROFS => Self::EROFS, + libc::EMLINK => Self::EMLINK, + libc::EPIPE => Self::EPIPE, + libc::EDOM => Self::EDOM, + libc::ERANGE => Self::ERANGE, + libc::EDEADLK => Self::EDEADLK, + libc::ENAMETOOLONG => Self::ENAMETOOLONG, + libc::ENOLCK => Self::ENOLCK, + libc::ENOSYS => Self::ENOSYS, + libc::ENOTEMPTY => Self::ENOTEMPTY, + libc::ELOOP => Self::ELOOP, + libc::ENOMSG => Self::ENOMSG, + libc::EIDRM => Self::EIDRM, + libc::ENOLINK => Self::ENOLINK, + libc::EPROTO => Self::EPROTO, + libc::EMULTIHOP => Self::EMULTIHOP, + libc::EBADMSG => Self::EBADMSG, + libc::EOVERFLOW => Self::EOVERFLOW, + libc::EILSEQ => Self::EILSEQ, + libc::ENOTSOCK => Self::ENOTSOCK, + libc::EDESTADDRREQ => Self::EDESTADDRREQ, + libc::EMSGSIZE => Self::EMSGSIZE, + libc::EPROTOTYPE => Self::EPROTOTYPE, + libc::ENOPROTOOPT => Self::ENOPROTOOPT, + libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT, + libc::EAFNOSUPPORT => Self::EAFNOSUPPORT, + libc::EADDRINUSE => Self::EADDRINUSE, + libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL, + libc::ENETDOWN => Self::ENETDOWN, + libc::ENETUNREACH => Self::ENETUNREACH, + libc::ENETRESET => Self::ENETRESET, + libc::ECONNABORTED => Self::ECONNABORTED, + libc::ECONNRESET => Self::ECONNRESET, + libc::ENOBUFS => Self::ENOBUFS, + libc::EISCONN => Self::EISCONN, + libc::ENOTCONN => Self::ENOTCONN, + libc::ETIMEDOUT => Self::ETIMEDOUT, + libc::ECONNREFUSED => Self::ECONNREFUSED, + libc::EHOSTUNREACH => Self::EHOSTUNREACH, + libc::EALREADY => Self::EALREADY, + libc::EINPROGRESS => Self::EINPROGRESS, + libc::ESTALE => Self::ESTALE, + libc::EDQUOT => Self::EDQUOT, + libc::ECANCELED => Self::ECANCELED, + libc::EOWNERDEAD => Self::EOWNERDEAD, + libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE, + libc::ENOTSUP => Self::ENOTSUP, + x => { + log::debug!("Unknown errno value: {}", x); + Self::EIO + } + }, + None => { + log::debug!("Other I/O error: {}", err); Self::EIO } } @@ -152,13 +161,13 @@ pub(crate) fn nix_from_oflags(oflags: wasi::__wasi_oflags_t) -> OFlag { nix_flags } -pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result { +pub(crate) fn filestat_from_nix(filestat: libc::stat) -> WasiResult { use std::convert::TryInto; - fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result { + fn filestat_to_timestamp(secs: u64, nsecs: u64) -> WasiResult { secs.checked_mul(1_000_000_000) .and_then(|sec_nsec| sec_nsec.checked_add(nsecs)) - .ok_or(Error::EOVERFLOW) + .ok_or(WasiError::EOVERFLOW) } let filetype = yanix::file::FileType::from_stat_st_mode(filestat.st_mode); @@ -193,7 +202,7 @@ pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result>(s: S) -> Result { +pub(crate) fn path_from_host>(s: S) -> WasiResult { helpers::path_from_slice(s.as_ref().as_bytes()).map(String::from) } diff --git a/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs index 85ac6bb1c2..abba915480 100644 --- a/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs @@ -3,8 +3,9 @@ use crate::fdentry::Descriptor; use crate::host::Dirent; use crate::hostcalls_impl::PathGet; -use crate::sys::{fdentry_impl::OsHandle, host_impl, unix::sys_impl}; -use crate::{wasi, Error, Result}; +use crate::sys::fdentry_impl::OsHandle; +use crate::sys::{host_impl, unix::sys_impl}; +use crate::wasi::{self, WasiError, WasiResult}; use std::convert::TryInto; use std::fs::File; use std::os::unix::fs::FileExt; @@ -16,15 +17,19 @@ pub(crate) fn fd_pread( file: &File, buf: &mut [u8], offset: wasi::__wasi_filesize_t, -) -> Result { +) -> WasiResult { file.read_at(buf, offset).map_err(Into::into) } -pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result { +pub(crate) fn fd_pwrite( + file: &File, + buf: &[u8], + offset: wasi::__wasi_filesize_t, +) -> WasiResult { file.write_at(buf, offset).map_err(Into::into) } -pub(crate) fn fd_fdstat_get(fd: &File) -> Result { +pub(crate) fn fd_fdstat_get(fd: &File) -> WasiResult { unsafe { yanix::fcntl::get_status_flags(fd.as_raw_fd()) } .map(host_impl::fdflags_from_nix) .map_err(Into::into) @@ -33,7 +38,7 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result { pub(crate) fn fd_fdstat_set_flags( fd: &File, fdflags: wasi::__wasi_fdflags_t, -) -> Result> { +) -> WasiResult> { let nix_flags = host_impl::nix_from_fdflags(fdflags); unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) } .map(|_| None) @@ -45,7 +50,7 @@ pub(crate) fn fd_advise( advice: wasi::__wasi_advice_t, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, -) -> Result<()> { +) -> WasiResult<()> { use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice}; let offset = offset.try_into()?; let len = len.try_into()?; @@ -56,17 +61,17 @@ pub(crate) fn fd_advise( wasi::__WASI_ADVICE_NOREUSE => PosixFadviseAdvice::NoReuse, wasi::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::Random, wasi::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::Normal, - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }; unsafe { posix_fadvise(file.as_raw_fd(), offset, len, host_advice) }.map_err(Into::into) } -pub(crate) fn path_create_directory(base: &File, path: &str) -> Result<()> { +pub(crate) fn path_create_directory(base: &File, path: &str) -> WasiResult<()> { use yanix::file::{mkdirat, Mode}; unsafe { mkdirat(base.as_raw_fd(), path, Mode::from_bits_truncate(0o777)) }.map_err(Into::into) } -pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { +pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { use yanix::file::{linkat, AtFlag}; unsafe { linkat( @@ -86,7 +91,7 @@ pub(crate) fn path_open( write: bool, oflags: wasi::__wasi_oflags_t, fs_flags: wasi::__wasi_fdflags_t, -) -> Result { +) -> WasiResult { use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag}; let mut nix_all_oflags = if read && write { @@ -136,7 +141,7 @@ pub(crate) fn path_open( } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } } Err(err) => { @@ -158,7 +163,7 @@ pub(crate) fn path_open( } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink { - return Err(Error::ELOOP); + return Err(WasiError::ELOOP); } } Err(err) => { @@ -169,7 +174,7 @@ pub(crate) fn path_open( // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on // a symlink. libc::EMLINK if !(nix_all_oflags & OFlag::NOFOLLOW).is_empty() => { - return Err(Error::ELOOP); + return Err(WasiError::ELOOP); } _ => {} } @@ -184,7 +189,7 @@ pub(crate) fn path_open( Ok(OsHandle::from(unsafe { File::from_raw_fd(new_fd) }).into()) } -pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result { +pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> WasiResult { use std::cmp::min; use yanix::file::readlinkat; let read_link = unsafe { readlinkat(resolved.dirfd().as_raw_fd(), resolved.path()) } @@ -197,7 +202,7 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result Ok(copy_len) } -pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result { +pub(crate) fn fd_filestat_get(file: &std::fs::File) -> WasiResult { use yanix::file::fstat; unsafe { fstat(file.as_raw_fd()) } .map_err(Into::into) @@ -207,7 +212,7 @@ pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result Result { +) -> WasiResult { use yanix::file::{fstatat, AtFlag}; let atflags = match dirflags { 0 => AtFlag::empty(), @@ -224,7 +229,7 @@ pub(crate) fn path_filestat_set_times( st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { use std::time::{Duration, UNIX_EPOCH}; use yanix::filetime::*; @@ -234,7 +239,7 @@ pub(crate) fn path_filestat_set_times( let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0; if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { - return Err(Error::EINVAL); + return Err(WasiError::EINVAL); } let symlink_nofollow = wasi::__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW != dirflags; @@ -265,7 +270,7 @@ pub(crate) fn path_filestat_set_times( .map_err(Into::into) } -pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { +pub(crate) fn path_remove_directory(resolved: PathGet) -> WasiResult<()> { use yanix::file::{unlinkat, AtFlag}; unsafe { @@ -281,7 +286,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { pub(crate) fn fd_readdir<'a>( os_handle: &'a mut OsHandle, cookie: wasi::__wasi_dircookie_t, -) -> Result> + 'a> { +) -> WasiResult> + 'a> { use yanix::dir::{DirIter, Entry, EntryExt, SeekLoc}; // Get an instance of `Dir`; this is host-specific due to intricasies diff --git a/crates/wasi-common/src/sys/unix/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/sys/unix/hostcalls_impl/fs_helpers.rs index 785b553d96..f151feee1a 100644 --- a/crates/wasi-common/src/sys/unix/hostcalls_impl/fs_helpers.rs +++ b/crates/wasi-common/src/sys/unix/hostcalls_impl/fs_helpers.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] #![allow(unused_unsafe)] use crate::sys::host_impl; -use crate::{wasi, Result}; +use crate::wasi::{self, WasiResult}; use std::fs::File; use yanix::file::OFlag; @@ -36,7 +36,7 @@ pub(crate) fn path_open_rights( (needed_base, needed_inheriting) } -pub(crate) fn openat(dirfd: &File, path: &str) -> Result { +pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult { use std::os::unix::prelude::{AsRawFd, FromRawFd}; use yanix::file::{openat, Mode}; @@ -54,7 +54,7 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result { .map_err(Into::into) } -pub(crate) fn readlinkat(dirfd: &File, path: &str) -> Result { +pub(crate) fn readlinkat(dirfd: &File, path: &str) -> WasiResult { use std::os::unix::prelude::AsRawFd; use yanix::file::readlinkat; diff --git a/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs b/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs index 678f335cad..9456d2a69f 100644 --- a/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs @@ -1,22 +1,24 @@ #![allow(non_camel_case_types)] #![allow(unused_unsafe)] use crate::hostcalls_impl::{ClockEventData, FdEventData}; -use crate::{wasi, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; use std::io; use yanix::clock::{clock_getres, clock_gettime, ClockId}; -fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result { +fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> WasiResult { // convert the supported clocks to libc types, or return EINVAL match clock_id { wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime), wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic), wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime), wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => Ok(ClockId::ThreadCPUTime), - _ => Err(Error::EINVAL), + _ => Err(WasiError::EINVAL), } } -pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result { +pub(crate) fn clock_res_get( + clock_id: wasi::__wasi_clockid_t, +) -> WasiResult { let clock_id = wasi_clock_id_to_unix(clock_id)?; let timespec = clock_getres(clock_id)?; @@ -26,18 +28,20 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result Result { +pub(crate) fn clock_time_get( + clock_id: wasi::__wasi_clockid_t, +) -> WasiResult { let clock_id = wasi_clock_id_to_unix(clock_id)?; let timespec = clock_gettime(clock_id)?; @@ -46,14 +50,14 @@ pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result, fd_events: Vec, events: &mut Vec, -) -> Result<()> { +) -> WasiResult<()> { use std::{convert::TryInto, os::unix::prelude::AsRawFd}; use yanix::poll::{poll, PollFd, PollFlags}; @@ -122,12 +126,12 @@ fn poll_oneoff_handle_timeout_event( fn poll_oneoff_handle_fd_event<'a>( ready_events: impl Iterator, yanix::poll::PollFd)>, events: &mut Vec, -) -> Result<()> { +) -> WasiResult<()> { use crate::fdentry::Descriptor; use std::{convert::TryInto, os::unix::prelude::AsRawFd}; use yanix::{file::fionread, poll::PollFlags}; - fn query_nbytes(fd: &Descriptor) -> Result { + fn query_nbytes(fd: &Descriptor) -> WasiResult { // fionread may overflow for large files, so use another way for regular files. if let Descriptor::OsHandle(os_handle) = fd { let meta = os_handle.metadata()?; diff --git a/crates/wasi-common/src/sys/unix/linux/host_impl.rs b/crates/wasi-common/src/sys/unix/linux/host_impl.rs index d7a3e46fdb..b1850f9daa 100644 --- a/crates/wasi-common/src/sys/unix/linux/host_impl.rs +++ b/crates/wasi-common/src/sys/unix/linux/host_impl.rs @@ -1,11 +1,11 @@ -use crate::{wasi, Result}; +use crate::wasi::{self, WasiResult}; pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::RSYNC; -pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> Result { +pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> WasiResult { Ok(wasi::__wasi_device_t::from(dev)) } -pub(crate) fn stino_from_nix(ino: libc::ino_t) -> Result { +pub(crate) fn stino_from_nix(ino: libc::ino_t) -> WasiResult { Ok(wasi::__wasi_device_t::from(ino)) } diff --git a/crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs b/crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs index 308c085d4c..42ea5c8b92 100644 --- a/crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs +++ b/crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs @@ -1,9 +1,9 @@ use crate::fdentry::Descriptor; use crate::hostcalls_impl::PathGet; -use crate::Result; +use crate::wasi::WasiResult; use std::os::unix::prelude::AsRawFd; -pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { +pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> { use yanix::file::{unlinkat, AtFlag}; unsafe { unlinkat( @@ -15,7 +15,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { .map_err(Into::into) } -pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { +pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> { use yanix::file::symlinkat; log::debug!("path_symlink old_path = {:?}", old_path); @@ -25,7 +25,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { .map_err(Into::into) } -pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { +pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { use yanix::file::renameat; match (resolved_old.dirfd(), resolved_new.dirfd()) { (Descriptor::OsHandle(resolved_old_file), Descriptor::OsHandle(resolved_new_file)) => { @@ -47,10 +47,10 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul pub(crate) mod fd_readdir_impl { use crate::sys::fdentry_impl::OsHandle; - use crate::Result; + use crate::wasi::WasiResult; use yanix::dir::Dir; - pub(crate) fn get_dir_from_os_handle(os_handle: &mut OsHandle) -> Result> { + pub(crate) fn get_dir_from_os_handle(os_handle: &mut OsHandle) -> WasiResult> { // We need to duplicate the fd, because `opendir(3)`: // After a successful call to fdopendir(), fd is used internally by the implementation, // and should not otherwise be used by the application. diff --git a/crates/wasi-common/src/sys/unix/mod.rs b/crates/wasi-common/src/sys/unix/mod.rs index b34024676b..abd5160114 100644 --- a/crates/wasi-common/src/sys/unix/mod.rs +++ b/crates/wasi-common/src/sys/unix/mod.rs @@ -20,18 +20,14 @@ cfg_if::cfg_if! { } } -use crate::Result; use std::fs::{File, OpenOptions}; +use std::io::Result; use std::path::Path; pub(crate) fn dev_null() -> Result { - OpenOptions::new() - .read(true) - .write(true) - .open("/dev/null") - .map_err(Into::into) + OpenOptions::new().read(true).write(true).open("/dev/null") } pub fn preopen_dir>(path: P) -> Result { - File::open(path).map_err(Into::into) + File::open(path) } diff --git a/crates/wasi-common/src/sys/windows/fdentry_impl.rs b/crates/wasi-common/src/sys/windows/fdentry_impl.rs index bd1d1e88cf..8776111673 100644 --- a/crates/wasi-common/src/sys/windows/fdentry_impl.rs +++ b/crates/wasi-common/src/sys/windows/fdentry_impl.rs @@ -1,5 +1,5 @@ use crate::fdentry::{Descriptor, OsHandleRef}; -use crate::{wasi, Error, Result}; +use crate::wasi; use std::fs::File; use std::io; use std::mem::ManuallyDrop; @@ -63,7 +63,7 @@ pub(crate) fn descriptor_as_oshandle<'lifetime>( /// This function is unsafe because it operates on a raw file descriptor. pub(crate) unsafe fn determine_type_and_access_rights( handle: &Handle, -) -> Result<( +) -> io::Result<( wasi::__wasi_filetype_t, wasi::__wasi_rights_t, wasi::__wasi_rights_t, @@ -96,7 +96,7 @@ pub(crate) unsafe fn determine_type_and_access_rights( /// This function is unsafe because it operates on a raw file descriptor. pub(crate) unsafe fn determine_type_rights( handle: &Handle, -) -> Result<( +) -> io::Result<( wasi::__wasi_filetype_t, wasi::__wasi_rights_t, wasi::__wasi_rights_t, @@ -114,7 +114,7 @@ pub(crate) unsafe fn determine_type_rights( } else if file_type.is_disk() { // disk file: file, dir or disk device let file = std::mem::ManuallyDrop::new(File::from_raw_handle(handle.as_raw_handle())); - let meta = file.metadata().map_err(|_| Error::EINVAL)?; + let meta = file.metadata()?; if meta.is_dir() { ( wasi::__WASI_FILETYPE_DIRECTORY, @@ -128,7 +128,7 @@ pub(crate) unsafe fn determine_type_rights( wasi::RIGHTS_REGULAR_FILE_INHERITING, ) } else { - return Err(Error::EINVAL); + return Err(io::Error::from_raw_os_error(libc::EINVAL)); } } else if file_type.is_pipe() { // pipe object: socket, named pipe or anonymous pipe @@ -139,7 +139,7 @@ pub(crate) unsafe fn determine_type_rights( wasi::RIGHTS_SOCKET_INHERITING, ) } else { - return Err(Error::EINVAL); + return Err(io::Error::from_raw_os_error(libc::EINVAL)); } }; Ok((file_type, rights_base, rights_inheriting)) diff --git a/crates/wasi-common/src/sys/windows/host_impl.rs b/crates/wasi-common/src/sys/windows/host_impl.rs index ad5ecd4483..cadb7205bf 100644 --- a/crates/wasi-common/src/sys/windows/host_impl.rs +++ b/crates/wasi-common/src/sys/windows/host_impl.rs @@ -1,6 +1,6 @@ //! WASI host types specific to Windows host. use crate::host::FileType; -use crate::{error::FromRawOsError, wasi, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; use std::convert::TryInto; use std::ffi::OsStr; use std::fs::{self, File}; @@ -9,34 +9,42 @@ use std::os::windows::ffi::OsStrExt; use std::time::{SystemTime, UNIX_EPOCH}; use winapi::shared::winerror; -impl FromRawOsError for Error { - fn from_raw_os_error(code: i32) -> Self { - // TODO: implement error mapping between Windows and WASI - match code as u32 { - winerror::ERROR_SUCCESS => Self::ESUCCESS, - winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG, - winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT, - winerror::ERROR_PATH_NOT_FOUND => Self::ENOENT, - winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE, - winerror::ERROR_ACCESS_DENIED => Self::EACCES, - winerror::ERROR_SHARING_VIOLATION => Self::EACCES, - winerror::ERROR_PRIVILEGE_NOT_HELD => Self::ENOTCAPABLE, // TODO is this the correct mapping? - winerror::ERROR_INVALID_HANDLE => Self::EBADF, - winerror::ERROR_INVALID_NAME => Self::ENOENT, - winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM, - winerror::ERROR_OUTOFMEMORY => Self::ENOMEM, - winerror::ERROR_DIR_NOT_EMPTY => Self::ENOTEMPTY, - winerror::ERROR_NOT_READY => Self::EBUSY, - winerror::ERROR_BUSY => Self::EBUSY, - winerror::ERROR_NOT_SUPPORTED => Self::ENOTSUP, - winerror::ERROR_FILE_EXISTS => Self::EEXIST, - winerror::ERROR_BROKEN_PIPE => Self::EPIPE, - winerror::ERROR_BUFFER_OVERFLOW => Self::ENAMETOOLONG, - winerror::ERROR_NOT_A_REPARSE_POINT => Self::EINVAL, - winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL, - winerror::ERROR_DIRECTORY => Self::ENOTDIR, - winerror::ERROR_ALREADY_EXISTS => Self::EEXIST, - _ => Self::ENOTSUP, +impl From for WasiError { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(code) => match code as u32 { + winerror::ERROR_SUCCESS => Self::ESUCCESS, + winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG, + winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT, + winerror::ERROR_PATH_NOT_FOUND => Self::ENOENT, + winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE, + winerror::ERROR_ACCESS_DENIED => Self::EACCES, + winerror::ERROR_SHARING_VIOLATION => Self::EACCES, + winerror::ERROR_PRIVILEGE_NOT_HELD => Self::ENOTCAPABLE, + winerror::ERROR_INVALID_HANDLE => Self::EBADF, + winerror::ERROR_INVALID_NAME => Self::ENOENT, + winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM, + winerror::ERROR_OUTOFMEMORY => Self::ENOMEM, + winerror::ERROR_DIR_NOT_EMPTY => Self::ENOTEMPTY, + winerror::ERROR_NOT_READY => Self::EBUSY, + winerror::ERROR_BUSY => Self::EBUSY, + winerror::ERROR_NOT_SUPPORTED => Self::ENOTSUP, + winerror::ERROR_FILE_EXISTS => Self::EEXIST, + winerror::ERROR_BROKEN_PIPE => Self::EPIPE, + winerror::ERROR_BUFFER_OVERFLOW => Self::ENAMETOOLONG, + winerror::ERROR_NOT_A_REPARSE_POINT => Self::EINVAL, + winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL, + winerror::ERROR_DIRECTORY => Self::ENOTDIR, + winerror::ERROR_ALREADY_EXISTS => Self::EEXIST, + x => { + log::debug!("unknown error value: {}", x); + Self::EIO + } + }, + None => { + log::debug!("Other I/O error: {}", err); + Self::EIO + } } } } @@ -73,15 +81,15 @@ fn change_time(file: &File) -> io::Result { winx::file::change_time(file) } -fn systemtime_to_timestamp(st: SystemTime) -> Result { +fn systemtime_to_timestamp(st: SystemTime) -> WasiResult { st.duration_since(UNIX_EPOCH) - .map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH + .map_err(|_| WasiError::EINVAL)? // date earlier than UNIX_EPOCH .as_nanos() .try_into() .map_err(Into::into) // u128 doesn't fit into u64 } -pub(crate) fn filestat_from_win(file: &File) -> Result { +pub(crate) fn filestat_from_win(file: &File) -> WasiResult { let metadata = file.metadata()?; Ok(wasi::__wasi_filestat_t { dev: device_id(file)?, @@ -99,7 +107,7 @@ pub(crate) fn filestat_from_win(file: &File) -> Result /// /// NB WASI spec requires OS string to be valid UTF-8. Otherwise, /// `__WASI_ERRNO_ILSEQ` error is returned. -pub(crate) fn path_from_host>(s: S) -> Result { +pub(crate) fn path_from_host>(s: S) -> WasiResult { let vec: Vec = s.as_ref().encode_wide().collect(); - String::from_utf16(&vec).map_err(|_| Error::EILSEQ) + String::from_utf16(&vec).map_err(|_| WasiError::EILSEQ) } diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs index a6e86650e6..6d7030cfb3 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs @@ -8,7 +8,7 @@ use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet}; use crate::sys::fdentry_impl::{determine_type_rights, OsHandle}; use crate::sys::host_impl::{self, path_from_host}; use crate::sys::hostcalls_impl::fs_helpers::PathGetExt; -use crate::{wasi, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; use log::{debug, trace}; use std::convert::TryInto; use std::fs::{File, Metadata, OpenOptions}; @@ -44,16 +44,20 @@ pub(crate) fn fd_pread( file: &File, buf: &mut [u8], offset: wasi::__wasi_filesize_t, -) -> Result { +) -> WasiResult { 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: wasi::__wasi_filesize_t) -> Result { +pub(crate) fn fd_pwrite( + file: &File, + buf: &[u8], + offset: wasi::__wasi_filesize_t, +) -> WasiResult { write_at(file, buf, offset).map_err(Into::into) } -pub(crate) fn fd_fdstat_get(fd: &File) -> Result { +pub(crate) fn fd_fdstat_get(fd: &File) -> WasiResult { let mut fdflags = 0; let handle = unsafe { fd.as_raw_handle() }; @@ -82,7 +86,7 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result { pub(crate) fn fd_fdstat_set_flags( fd: &File, fdflags: wasi::__wasi_fdflags_t, -) -> Result> { +) -> WasiResult> { let handle = unsafe { fd.as_raw_handle() }; let access_mode = winx::file::query_access_information(handle)?; @@ -106,7 +110,7 @@ pub(crate) fn fd_advise( advice: wasi::__wasi_advice_t, _offset: wasi::__wasi_filesize_t, _len: wasi::__wasi_filesize_t, -) -> Result<()> { +) -> WasiResult<()> { match advice { wasi::__WASI_ADVICE_DONTNEED | wasi::__WASI_ADVICE_SEQUENTIAL @@ -114,18 +118,18 @@ pub(crate) fn fd_advise( | wasi::__WASI_ADVICE_NOREUSE | wasi::__WASI_ADVICE_RANDOM | wasi::__WASI_ADVICE_NORMAL => {} - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), } Ok(()) } -pub(crate) fn path_create_directory(file: &File, path: &str) -> Result<()> { +pub(crate) fn path_create_directory(file: &File, path: &str) -> WasiResult<()> { let path = concatenate(file, path)?; std::fs::create_dir(&path).map_err(Into::into) } -pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { +pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { unimplemented!("path_link") } @@ -135,7 +139,7 @@ pub(crate) fn path_open( write: bool, oflags: wasi::__wasi_oflags_t, fdflags: wasi::__wasi_fdflags_t, -) -> Result { +) -> WasiResult { use winx::file::{AccessMode, CreationDisposition, Flags}; let is_trunc = oflags & wasi::__WASI_OFLAGS_TRUNC != 0; @@ -145,7 +149,7 @@ pub(crate) fn path_open( // This is because truncation requires `GENERIC_WRITE` access, which will override the removal // of the `FILE_WRITE_DATA` permission. if fdflags & wasi::__WASI_FDFLAGS_APPEND != 0 { - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } } @@ -172,11 +176,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(Error::ELOOP); + return Err(WasiError::ELOOP); } // check if we are trying to open a file as a dir if file_type.is_file() && oflags & wasi::__WASI_OFLAGS_DIRECTORY != 0 { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } } Err(err) => match err.raw_os_error() { @@ -191,7 +195,7 @@ pub(crate) fn path_open( } None => { log::debug!("Inconvertible OS error: {}", err); - return Err(Error::EIO); + return Err(WasiError::EIO); } }, } @@ -276,7 +280,7 @@ fn dirent_from_path>( path: P, name: &str, cookie: wasi::__wasi_dircookie_t, -) -> Result { +) -> WasiResult { let path = path.as_ref(); trace!("dirent_from_path: opening {}", path.to_string_lossy()); @@ -325,7 +329,7 @@ fn dirent_from_path>( pub(crate) fn fd_readdir( fd: &File, cookie: wasi::__wasi_dircookie_t, -) -> Result>> { +) -> WasiResult>> { use winx::file::get_file_path; let cookie = cookie.try_into()?; @@ -361,7 +365,7 @@ pub(crate) fn fd_readdir( Ok(iter.skip(cookie)) } -pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result { +pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> WasiResult { use winx::file::get_file_path; let path = resolved.concatenate()?; @@ -375,8 +379,8 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result let dir_path = PathBuf::from(strip_extended_prefix(dir_path)); let target_path = target_path .strip_prefix(dir_path) - .map_err(|_| Error::ENOTCAPABLE) - .and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?; + .map_err(|_| WasiError::ENOTCAPABLE) + .and_then(|path| path.to_str().map(String::from).ok_or(WasiError::EILSEQ))?; if buf.len() > 0 { let mut chars = target_path.chars(); @@ -398,7 +402,7 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result } } -fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> Result> { +fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> WasiResult> { if resolved.path().ends_with('/') { let suffix = resolved.path().trim_end_matches('/'); concatenate(&resolved.dirfd().as_os_handle(), Path::new(suffix)).map(Some) @@ -407,7 +411,7 @@ fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> Result Result<()> { +pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> { use std::fs; let old_path = resolved_old.concatenate()?; @@ -418,12 +422,12 @@ 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(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } // Second sanity check: check we're not trying to rename a file into a path // ending in a trailing slash. if old_path.is_file() && resolved_new.path().ends_with('/') { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } // TODO handle symlinks @@ -439,7 +443,7 @@ 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() { - return Err(Error::EISDIR); + return Err(WasiError::EISDIR); } else { // Ok, let's try removing an empty dir at new_path if it exists // and is a nonempty dir. @@ -453,7 +457,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul // a file instead of a dir, and if so, throw ENOTDIR. if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved_old)? { if path.is_file() { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } } } @@ -464,19 +468,19 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Error::EIO) + Err(WasiError::EIO) } } } -pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result { +pub(crate) fn fd_filestat_get(file: &std::fs::File) -> WasiResult { host_impl::filestat_from_win(file) } pub(crate) fn path_filestat_get( resolved: PathGet, dirflags: wasi::__wasi_lookupflags_t, -) -> Result { +) -> WasiResult { let path = resolved.concatenate()?; let file = File::open(path)?; host_impl::filestat_from_win(&file) @@ -488,7 +492,7 @@ pub(crate) fn path_filestat_set_times( st_atim: wasi::__wasi_timestamp_t, mut st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, -) -> Result<()> { +) -> WasiResult<()> { use winx::file::AccessMode; let path = resolved.concatenate()?; let file = OpenOptions::new() @@ -498,7 +502,7 @@ pub(crate) fn path_filestat_set_times( fd_filestat_set_times_impl(&modifiable_fd, st_atim, st_mtim, fst_flags) } -pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { +pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> { use std::os::windows::fs::{symlink_dir, symlink_file}; let old_path = concatenate(&resolved.dirfd().as_os_handle(), Path::new(old_path))?; @@ -520,14 +524,14 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { winerror::ERROR_ACCESS_DENIED => { // does the target exist? if new_path.exists() { - return Err(Error::EEXIST); + return Err(WasiError::EEXIST); } } winerror::ERROR_INVALID_NAME => { // does the target without trailing slashes exist? if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved)? { if path.exists() { - return Err(Error::EEXIST); + return Err(WasiError::EEXIST); } } } @@ -538,12 +542,12 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Error::EIO) + Err(WasiError::EIO) } } } -pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { +pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> { use std::fs; let path = resolved.concatenate()?; @@ -573,19 +577,19 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Error::EIO) + Err(WasiError::EIO) } } } else if file_type.is_dir() { - Err(Error::EISDIR) + Err(WasiError::EISDIR) } else if file_type.is_file() { fs::remove_file(path).map_err(Into::into) } else { - Err(Error::EINVAL) + Err(WasiError::EINVAL) } } -pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { +pub(crate) fn path_remove_directory(resolved: PathGet) -> WasiResult<()> { let path = resolved.concatenate()?; std::fs::remove_dir(&path).map_err(Into::into) } diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs index df77548ce9..7d35a4d95f 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs +++ b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] use crate::fdentry::Descriptor; use crate::hostcalls_impl::PathGet; -use crate::{wasi, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; use std::ffi::{OsStr, OsString}; use std::fs::File; use std::os::windows::ffi::{OsStrExt, OsStringExt}; @@ -9,11 +9,11 @@ use std::path::{Path, PathBuf}; use winapi::shared::winerror; pub(crate) trait PathGetExt { - fn concatenate(&self) -> Result; + fn concatenate(&self) -> WasiResult; } impl PathGetExt for PathGet { - fn concatenate(&self) -> Result { + fn concatenate(&self) -> WasiResult { match self.dirfd() { Descriptor::OsHandle(file) => concatenate(file, Path::new(self.path())), Descriptor::VirtualFile(_virt) => { @@ -55,7 +55,7 @@ pub(crate) fn path_open_rights( (needed_base, needed_inheriting) } -pub(crate) fn openat(dirfd: &File, path: &str) -> Result { +pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult { use std::fs::OpenOptions; use std::os::windows::fs::OpenOptionsExt; use winx::file::Flags; @@ -72,13 +72,13 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result { if let Some(code) = err.raw_os_error() { log::debug!("openat error={:?}", code); if code as u32 == winerror::ERROR_INVALID_NAME { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } } Err(err.into()) } -pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result { +pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> WasiResult { use winx::file::get_file_path; let path = concatenate(dirfd, Path::new(s_path))?; @@ -92,8 +92,8 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result { let dir_path = PathBuf::from(strip_extended_prefix(dir_path)); let target_path = target_path .strip_prefix(dir_path) - .map_err(|_| Error::ENOTCAPABLE)?; - let target_path = target_path.to_str().ok_or(Error::EILSEQ)?; + .map_err(|_| WasiError::ENOTCAPABLE)?; + let target_path = target_path.to_str().ok_or(WasiError::EILSEQ)?; return Ok(target_path.to_owned()); } Err(e) => e, @@ -105,7 +105,7 @@ 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() { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } } } @@ -122,13 +122,13 @@ pub(crate) fn strip_extended_prefix>(path: P) -> OsString { } } -pub(crate) fn concatenate>(file: &File, path: P) -> Result { +pub(crate) fn concatenate>(file: &File, path: P) -> WasiResult { use winx::file::get_file_path; // WASI is not able to deal with absolute paths // so error out if absolute if path.as_ref().is_absolute() { - return Err(Error::ENOTCAPABLE); + return Err(WasiError::ENOTCAPABLE); } let dir_path = get_file_path(file)?; diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs index a3b56c00be..cb27e3690f 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs @@ -5,7 +5,8 @@ use crate::fdentry::Descriptor; use crate::hostcalls_impl::{ClockEventData, FdEventData}; use crate::memory::*; use crate::sys::host_impl; -use crate::{error::WasiError, wasi, wasi32, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; +use crate::wasi32; use cpu_time::{ProcessTime, ThreadTime}; use lazy_static::lazy_static; use log::{debug, error, trace, warn}; @@ -24,9 +25,9 @@ struct StdinPoll { enum PollState { Ready, - NotReady, // it's not ready, but we didn't wait - TimedOut, // it's not ready and a timeout has occurred - Error(WasiError), // not using the top-lever Error because it's not Clone + NotReady, // it's not ready, but we didn't wait + TimedOut, // it's not ready and a timeout has occurred + Error(WasiError), } enum WaitMode { @@ -82,7 +83,7 @@ impl StdinPoll { // Linux returns `POLLIN` in both cases, and we imitate this behavior. let resp = match std::io::stdin().lock().fill_buf() { Ok(_) => PollState::Ready, - Err(e) => PollState::Error(Error::from(e).as_wasi_error()), + Err(e) => PollState::Error(WasiError::from(e)), }; // Notify the requestor about data in stdin. They may have already timed out, @@ -108,7 +109,9 @@ lazy_static! { // Timer resolution on Windows is really hard. We may consider exposing the resolution of the respective // timers as an associated function in the future. -pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result { +pub(crate) fn clock_res_get( + clock_id: wasi::__wasi_clockid_t, +) -> WasiResult { Ok(match clock_id { // This is the best that we can do with std::time::SystemTime. // Rust uses GetSystemTimeAsFileTime, which is said to have the resolution of @@ -152,25 +155,28 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result 100, - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }) } -pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result { +pub(crate) fn clock_time_get( + clock_id: wasi::__wasi_clockid_t, +) -> WasiResult { let duration = match clock_id { wasi::__WASI_CLOCKID_REALTIME => get_monotonic_time(), wasi::__WASI_CLOCKID_MONOTONIC => get_realtime_time()?, wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => get_proc_cputime()?, wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => get_thread_cputime()?, - _ => return Err(Error::EINVAL), + _ => return Err(WasiError::EINVAL), }; duration.as_nanos().try_into().map_err(Into::into) } -fn make_rw_event(event: &FdEventData, nbytes: Result) -> wasi::__wasi_event_t { - use crate::error::AsWasiError; - let error = nbytes.as_wasi_error(); - let nbytes = nbytes.unwrap_or_default(); +fn make_rw_event(event: &FdEventData, nbytes: WasiResult) -> wasi::__wasi_event_t { + let (nbytes, error) = match nbytes { + Ok(nbytes) => (nbytes, WasiError::ESUCCESS), + Err(e) => (u64::default(), e), + }; wasi::__wasi_event_t { userdata: event.userdata, r#type: event.r#type, @@ -233,7 +239,7 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec, ) { let new_event = make_rw_event(&event, Err(error)); @@ -244,7 +250,7 @@ pub(crate) fn poll_oneoff( timeout: Option, fd_events: Vec, events: &mut Vec, -) -> Result<()> { +) -> WasiResult<()> { use std::fs::Metadata; use std::thread; @@ -289,7 +295,7 @@ pub(crate) fn poll_oneoff( let ftype = unsafe { winx::file::get_file_type(os_handle.as_raw_handle()) }?; if ftype.is_unknown() || ftype.is_char() { debug!("poll_oneoff: unsupported file type: {:?}", ftype); - handle_error_event(event, Error::ENOTSUP, events); + handle_error_event(event, WasiError::ENOTSUP, events); } else if ftype.is_disk() { immediate_events.push(event); } else if ftype.is_pipe() { @@ -349,7 +355,7 @@ pub(crate) fn poll_oneoff( PollState::Ready => handle_rw_event(event, events), PollState::NotReady => {} // not immediately available, so just ignore PollState::TimedOut => handle_timeout_event(timeout.unwrap().0, events), - PollState::Error(e) => handle_error_event(event, Error::Wasi(e), events), + PollState::Error(e) => handle_error_event(event, e, events), } } } @@ -365,7 +371,7 @@ pub(crate) fn poll_oneoff( } None => { error!("Polling only pipes with no timeout not supported on Windows."); - return Err(Error::ENOTSUP); + return Err(WasiError::ENOTSUP); } } } @@ -383,17 +389,17 @@ fn get_monotonic_time() -> Duration { START_MONOTONIC.elapsed() } -fn get_realtime_time() -> Result { +fn get_realtime_time() -> WasiResult { SystemTime::now() .duration_since(UNIX_EPOCH) - .map_err(|_| Error::EFAULT) + .map_err(|_| WasiError::EFAULT) } -fn get_proc_cputime() -> Result { +fn get_proc_cputime() -> WasiResult { Ok(ProcessTime::try_now()?.as_duration()) } -fn get_thread_cputime() -> Result { +fn get_thread_cputime() -> WasiResult { Ok(ThreadTime::try_now()?.as_duration()) } diff --git a/crates/wasi-common/src/sys/windows/mod.rs b/crates/wasi-common/src/sys/windows/mod.rs index 398d945323..b9e51e25f8 100644 --- a/crates/wasi-common/src/sys/windows/mod.rs +++ b/crates/wasi-common/src/sys/windows/mod.rs @@ -2,16 +2,12 @@ pub(crate) mod fdentry_impl; pub(crate) mod host_impl; pub(crate) mod hostcalls_impl; -use crate::Result; use std::fs::{File, OpenOptions}; +use std::io::Result; use std::path::Path; pub(crate) fn dev_null() -> Result { - OpenOptions::new() - .read(true) - .write(true) - .open("NUL") - .map_err(Into::into) + OpenOptions::new().read(true).write(true).open("NUL") } pub fn preopen_dir>(path: P) -> Result { @@ -28,5 +24,4 @@ pub fn preopen_dir>(path: P) -> Result { .read(true) .attributes(FILE_FLAG_BACKUP_SEMANTICS) .open(path) - .map_err(Into::into) } diff --git a/crates/wasi-common/src/virtfs.rs b/crates/wasi-common/src/virtfs.rs index 52e48629aa..50c34177d8 100644 --- a/crates/wasi-common/src/virtfs.rs +++ b/crates/wasi-common/src/virtfs.rs @@ -1,6 +1,7 @@ use crate::host::Dirent; use crate::host::FileType; -use crate::{wasi, wasi32, Error, Result}; +use crate::wasi::{self, WasiError, WasiResult}; +use crate::wasi32; use filetime::FileTime; use log::trace; use std::cell::RefCell; @@ -44,8 +45,8 @@ pub(crate) trait VirtualFile: MovableFile { fn try_clone(&self) -> io::Result>; - fn readlinkat(&self, _path: &Path) -> Result { - Err(Error::EACCES) + fn readlinkat(&self, _path: &Path) -> WasiResult { + Err(WasiError::EACCES) } fn openat( @@ -55,51 +56,51 @@ pub(crate) trait VirtualFile: MovableFile { _write: bool, _oflags: wasi::__wasi_oflags_t, _fd_flags: wasi::__wasi_fdflags_t, - ) -> Result> { - Err(Error::EACCES) + ) -> WasiResult> { + Err(WasiError::EACCES) } - fn remove_directory(&self, _path: &str) -> Result<()> { - Err(Error::EACCES) + fn remove_directory(&self, _path: &str) -> WasiResult<()> { + Err(WasiError::EACCES) } - fn unlink_file(&self, _path: &str) -> Result<()> { - Err(Error::EACCES) + fn unlink_file(&self, _path: &str) -> WasiResult<()> { + Err(WasiError::EACCES) } - fn datasync(&self) -> Result<()> { - Err(Error::EINVAL) + fn datasync(&self) -> WasiResult<()> { + Err(WasiError::EINVAL) } - fn sync(&self) -> Result<()> { + fn sync(&self) -> WasiResult<()> { Ok(()) } - fn create_directory(&self, _path: &Path) -> Result<()> { - Err(Error::EACCES) + fn create_directory(&self, _path: &Path) -> WasiResult<()> { + Err(WasiError::EACCES) } fn readdir( &self, _cookie: wasi::__wasi_dircookie_t, - ) -> Result>>> { - Err(Error::EBADF) + ) -> WasiResult>>> { + Err(WasiError::EBADF) } - fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> Result { - Err(Error::EBADF) + fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> WasiResult { + Err(WasiError::EBADF) } - fn pread(&self, _buf: &mut [u8], _offset: u64) -> Result { - Err(Error::EBADF) + fn pread(&self, _buf: &mut [u8], _offset: u64) -> WasiResult { + Err(WasiError::EBADF) } - fn pwrite(&self, _buf: &mut [u8], _offset: u64) -> Result { - Err(Error::EBADF) + fn pwrite(&self, _buf: &mut [u8], _offset: u64) -> WasiResult { + Err(WasiError::EBADF) } - fn seek(&mut self, _offset: SeekFrom) -> Result { - Err(Error::EBADF) + fn seek(&mut self, _offset: SeekFrom) -> WasiResult { + Err(WasiError::EBADF) } fn advise( @@ -107,36 +108,40 @@ pub(crate) trait VirtualFile: MovableFile { _advice: wasi::__wasi_advice_t, _offset: wasi::__wasi_filesize_t, _len: wasi::__wasi_filesize_t, - ) -> Result<()> { - Err(Error::EBADF) + ) -> WasiResult<()> { + Err(WasiError::EBADF) } fn allocate( &self, _offset: wasi::__wasi_filesize_t, _len: wasi::__wasi_filesize_t, - ) -> Result<()> { - Err(Error::EBADF) + ) -> WasiResult<()> { + Err(WasiError::EBADF) } - fn filestat_get(&self) -> Result { - Err(Error::EBADF) + fn filestat_get(&self) -> WasiResult { + Err(WasiError::EBADF) } - fn filestat_set_times(&self, _atim: Option, _mtim: Option) -> Result<()> { - Err(Error::EBADF) + fn filestat_set_times( + &self, + _atim: Option, + _mtim: Option, + ) -> WasiResult<()> { + Err(WasiError::EBADF) } - fn filestat_set_size(&self, _st_size: wasi::__wasi_filesize_t) -> Result<()> { - Err(Error::EBADF) + fn filestat_set_size(&self, _st_size: wasi::__wasi_filesize_t) -> WasiResult<()> { + Err(WasiError::EBADF) } - fn fdstat_set_flags(&mut self, _fdflags: wasi::__wasi_fdflags_t) -> Result<()> { - Err(Error::EBADF) + fn fdstat_set_flags(&mut self, _fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> { + Err(WasiError::EBADF) } - fn read_vectored(&mut self, _iovs: &mut [io::IoSliceMut]) -> Result { - Err(Error::EBADF) + fn read_vectored(&mut self, _iovs: &mut [io::IoSliceMut]) -> WasiResult { + Err(WasiError::EBADF) } fn get_file_type(&self) -> wasi::__wasi_filetype_t; @@ -157,23 +162,30 @@ pub trait FileContents { /// The current number of bytes this `FileContents` describes. fn size(&self) -> wasi::__wasi_filesize_t; /// Resize to hold `new_size` number of bytes, or error if this is not possible. - fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> Result<()>; + fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> WasiResult<()>; /// Write a list of `IoSlice` starting at `offset`. `offset` plus the total size of all `iovs` /// is guaranteed to not exceed `max_size`. Implementations must not indicate more bytes have /// been written than can be held by `iovs`. - fn pwritev(&mut self, iovs: &[io::IoSlice], offset: wasi::__wasi_filesize_t) -> Result; + fn pwritev( + &mut self, + iovs: &[io::IoSlice], + offset: wasi::__wasi_filesize_t, + ) -> WasiResult; /// Read from the file from `offset`, filling a list of `IoSlice`. The returend size must not /// be more than the capactiy of `iovs`, and must not exceed the limit reported by /// `self.max_size()`. - fn preadv(&self, iovs: &mut [io::IoSliceMut], offset: wasi::__wasi_filesize_t) - -> Result; + fn preadv( + &self, + iovs: &mut [io::IoSliceMut], + offset: wasi::__wasi_filesize_t, + ) -> WasiResult; /// Write contents from `buf` to this file starting at `offset`. `offset` plus the length of /// `buf` is guaranteed to not exceed `max_size`. Implementations must not indicate more bytes /// have been written than the size of `buf`. - fn pwrite(&mut self, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result; + fn pwrite(&mut self, buf: &[u8], offset: wasi::__wasi_filesize_t) -> WasiResult; /// Read from the file at `offset`, filling `buf`. The returned size must not be more than the /// capacity of `buf`, and `offset` plus the returned size must not exceed `self.max_size()`. - fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> Result; + fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> WasiResult; } impl FileContents for VecFileContents { @@ -185,8 +197,8 @@ impl FileContents for VecFileContents { self.content.len() as wasi::__wasi_filesize_t } - fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> Result<()> { - let new_size: usize = new_size.try_into().map_err(|_| Error::EINVAL)?; + fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> WasiResult<()> { + let new_size: usize = new_size.try_into().map_err(|_| WasiError::EINVAL)?; self.content.resize(new_size, 0); Ok(()) } @@ -195,7 +207,7 @@ impl FileContents for VecFileContents { &self, iovs: &mut [io::IoSliceMut], offset: wasi::__wasi_filesize_t, - ) -> Result { + ) -> WasiResult { let mut read_total = 0usize; for iov in iovs.iter_mut() { let read = self.pread(iov, offset)?; @@ -204,7 +216,11 @@ impl FileContents for VecFileContents { Ok(read_total) } - fn pwritev(&mut self, iovs: &[io::IoSlice], offset: wasi::__wasi_filesize_t) -> Result { + fn pwritev( + &mut self, + iovs: &[io::IoSlice], + offset: wasi::__wasi_filesize_t, + ) -> WasiResult { let mut write_total = 0usize; for iov in iovs.iter() { let written = self.pwrite(iov, offset)?; @@ -213,9 +229,9 @@ impl FileContents for VecFileContents { Ok(write_total) } - fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> Result { + fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> WasiResult { trace!(" | pread(buf.len={}, offset={})", buf.len(), offset); - let offset: usize = offset.try_into().map_err(|_| Error::EINVAL)?; + let offset: usize = offset.try_into().map_err(|_| WasiError::EINVAL)?; let data_remaining = self.content.len().saturating_sub(offset); @@ -228,10 +244,10 @@ impl FileContents for VecFileContents { res } - fn pwrite(&mut self, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result { - let offset: usize = offset.try_into().map_err(|_| Error::EINVAL)?; + fn pwrite(&mut self, buf: &[u8], offset: wasi::__wasi_filesize_t) -> WasiResult { + let offset: usize = offset.try_into().map_err(|_| WasiError::EINVAL)?; - let write_end = offset.checked_add(buf.len()).ok_or(Error::EFBIG)?; + let write_end = offset.checked_add(buf.len()).ok_or(WasiError::EFBIG)?; if write_end > self.content.len() { self.content.resize(write_end, 0); @@ -305,9 +321,9 @@ impl VirtualFile for InMemoryFile { })) } - fn readlinkat(&self, _path: &Path) -> Result { + fn readlinkat(&self, _path: &Path) -> WasiResult { // no symlink support, so always say it's invalid. - Err(Error::ENOTDIR) + Err(WasiError::ENOTDIR) } fn openat( @@ -317,7 +333,7 @@ impl VirtualFile for InMemoryFile { write: bool, oflags: wasi::__wasi_oflags_t, fd_flags: wasi::__wasi_fdflags_t, - ) -> Result> { + ) -> WasiResult> { log::trace!( "InMemoryFile::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}", path, @@ -333,7 +349,7 @@ impl VirtualFile for InMemoryFile { path ); log::trace!(" return ENOTDIR"); - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } if path == Path::new(".") { @@ -344,24 +360,24 @@ impl VirtualFile for InMemoryFile { None => self.try_clone().map_err(Into::into), } } else { - Err(Error::EACCES) + Err(WasiError::EACCES) } } - fn remove_directory(&self, _path: &str) -> Result<()> { - Err(Error::ENOTDIR) + fn remove_directory(&self, _path: &str) -> WasiResult<()> { + Err(WasiError::ENOTDIR) } - fn unlink_file(&self, _path: &str) -> Result<()> { - Err(Error::ENOTDIR) + fn unlink_file(&self, _path: &str) -> WasiResult<()> { + Err(WasiError::ENOTDIR) } - fn fdstat_set_flags(&mut self, fdflags: wasi::__wasi_fdflags_t) -> Result<()> { + fn fdstat_set_flags(&mut self, fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> { self.fd_flags = fdflags; Ok(()) } - fn write_vectored(&mut self, iovs: &[io::IoSlice]) -> Result { + fn write_vectored(&mut self, iovs: &[io::IoSlice]) -> WasiResult { trace!("write_vectored(iovs={:?})", iovs); let mut data = self.data.borrow_mut(); @@ -389,10 +405,10 @@ impl VirtualFile for InMemoryFile { if let Some(end) = write_start.checked_add(max_size as wasi::__wasi_filesize_t) { if end > data.max_size() { - return Err(Error::EFBIG); + return Err(WasiError::EFBIG); } } else { - return Err(Error::EFBIG); + return Err(WasiError::EFBIG); } trace!(" | *write_start={:?}", write_start); @@ -407,43 +423,43 @@ impl VirtualFile for InMemoryFile { Ok(written) } - fn read_vectored(&mut self, iovs: &mut [io::IoSliceMut]) -> Result { + fn read_vectored(&mut self, iovs: &mut [io::IoSliceMut]) -> WasiResult { trace!("read_vectored(iovs={:?})", iovs); trace!(" | *read_start={:?}", self.cursor); self.data.borrow_mut().preadv(iovs, self.cursor) } - fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> Result { + fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> WasiResult { self.data.borrow_mut().pread(buf, offset) } - fn pwrite(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> Result { + fn pwrite(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> WasiResult { self.data.borrow_mut().pwrite(buf, offset) } - fn seek(&mut self, offset: SeekFrom) -> Result { + fn seek(&mut self, offset: SeekFrom) -> WasiResult { let content_len = self.data.borrow().size(); match offset { SeekFrom::Current(offset) => { let new_cursor = if offset < 0 { self.cursor .checked_sub(offset.wrapping_neg() as u64) - .ok_or(Error::EINVAL)? + .ok_or(WasiError::EINVAL)? } else { self.cursor .checked_add(offset as u64) - .ok_or(Error::EINVAL)? + .ok_or(WasiError::EINVAL)? }; self.cursor = std::cmp::min(content_len, new_cursor); } SeekFrom::End(offset) => { // A negative offset from the end would be past the end of the file, - let offset: u64 = offset.try_into().map_err(|_| Error::EINVAL)?; + let offset: u64 = offset.try_into().map_err(|_| WasiError::EINVAL)?; self.cursor = content_len.saturating_sub(offset); } SeekFrom::Start(offset) => { // A negative offset from the end would be before the start of the file. - let offset: u64 = offset.try_into().map_err(|_| Error::EINVAL)?; + let offset: u64 = offset.try_into().map_err(|_| WasiError::EINVAL)?; self.cursor = std::cmp::min(content_len, offset); } } @@ -456,7 +472,7 @@ impl VirtualFile for InMemoryFile { advice: wasi::__wasi_advice_t, _offset: wasi::__wasi_filesize_t, _len: wasi::__wasi_filesize_t, - ) -> Result<()> { + ) -> WasiResult<()> { // we'll just ignore advice for now, unless it's totally invalid match advice { wasi::__WASI_ADVICE_DONTNEED @@ -465,7 +481,7 @@ impl VirtualFile for InMemoryFile { | wasi::__WASI_ADVICE_NOREUSE | wasi::__WASI_ADVICE_RANDOM | wasi::__WASI_ADVICE_NORMAL => Ok(()), - _ => Err(Error::EINVAL), + _ => Err(WasiError::EINVAL), } } @@ -473,12 +489,12 @@ impl VirtualFile for InMemoryFile { &self, offset: wasi::__wasi_filesize_t, len: wasi::__wasi_filesize_t, - ) -> Result<()> { - let new_limit = offset.checked_add(len).ok_or(Error::EFBIG)?; + ) -> WasiResult<()> { + let new_limit = offset.checked_add(len).ok_or(WasiError::EFBIG)?; let mut data = self.data.borrow_mut(); if new_limit > data.max_size() { - return Err(Error::EFBIG); + return Err(WasiError::EFBIG); } if new_limit > data.size() { @@ -488,15 +504,15 @@ impl VirtualFile for InMemoryFile { Ok(()) } - fn filestat_set_size(&self, st_size: wasi::__wasi_filesize_t) -> Result<()> { + fn filestat_set_size(&self, st_size: wasi::__wasi_filesize_t) -> WasiResult<()> { let mut data = self.data.borrow_mut(); if st_size > data.max_size() { - return Err(Error::EFBIG); + return Err(WasiError::EFBIG); } data.resize(st_size) } - fn filestat_get(&self) -> Result { + fn filestat_get(&self) -> WasiResult { let stat = wasi::__wasi_filestat_t { dev: 0, ino: 0, @@ -594,9 +610,9 @@ impl VirtualFile for VirtualDir { })) } - fn readlinkat(&self, _path: &Path) -> Result { + fn readlinkat(&self, _path: &Path) -> WasiResult { // Files are not symbolic links or directories, faithfully report ENOTDIR. - Err(Error::ENOTDIR) + Err(WasiError::ENOTDIR) } fn openat( @@ -606,7 +622,7 @@ impl VirtualFile for VirtualDir { write: bool, oflags: wasi::__wasi_oflags_t, fd_flags: wasi::__wasi_fdflags_t, - ) -> Result> { + ) -> WasiResult> { log::trace!( "VirtualDir::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}", path, @@ -631,7 +647,7 @@ impl VirtualFile for VirtualDir { // openat may have been passed a path with a trailing slash, but files are mapped to paths // with trailing slashes normalized out. - let file_name = path.file_name().ok_or(Error::EINVAL)?; + let file_name = path.file_name().ok_or(WasiError::EINVAL)?; let mut entries = self.entries.borrow_mut(); let entry_count = entries.len(); match entries.entry(Path::new(file_name).to_path_buf()) { @@ -640,7 +656,7 @@ impl VirtualFile for VirtualDir { if (oflags & creat_excl_mask) == creat_excl_mask { log::trace!("VirtualDir::openat was passed oflags CREAT|EXCL, but the file {:?} exists.", file_name); log::trace!(" return EEXIST"); - return Err(Error::EEXIST); + return Err(WasiError::EEXIST); } if (oflags & wasi::__WASI_OFLAGS_DIRECTORY) != 0 @@ -651,7 +667,7 @@ impl VirtualFile for VirtualDir { file_name ); log::trace!(" return ENOTDIR"); - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } e.get().try_clone().map_err(Into::into) @@ -663,7 +679,7 @@ impl VirtualFile for VirtualDir { // would have with `usize`. The limit is the full `u32` range minus two so we // can reserve "self" and "parent" cookie values. if entry_count >= (std::u32::MAX - RESERVED_ENTRY_COUNT) as usize { - return Err(Error::ENOSPC); + return Err(WasiError::ENOSPC); } log::trace!( @@ -676,26 +692,26 @@ impl VirtualFile for VirtualDir { file.set_parent(Some(self.try_clone().expect("can clone self"))); v.insert(file).try_clone().map_err(Into::into) } else { - Err(Error::EACCES) + Err(WasiError::EACCES) } } } } - fn remove_directory(&self, path: &str) -> Result<()> { + fn remove_directory(&self, path: &str) -> WasiResult<()> { let trimmed_path = path.trim_end_matches('/'); let mut entries = self.entries.borrow_mut(); match entries.entry(Path::new(trimmed_path).to_path_buf()) { Entry::Occupied(e) => { // first, does this name a directory? if e.get().get_file_type() != wasi::__WASI_FILETYPE_DIRECTORY { - return Err(Error::ENOTDIR); + return Err(WasiError::ENOTDIR); } // Okay, but is the directory empty? let iter = e.get().readdir(wasi::__WASI_DIRCOOKIE_START)?; if iter.skip(RESERVED_ENTRY_COUNT as usize).next().is_some() { - return Err(Error::ENOTEMPTY); + return Err(WasiError::ENOTEMPTY); } // Alright, it's an empty directory. We can remove it. @@ -711,19 +727,19 @@ impl VirtualFile for VirtualDir { "VirtualDir::remove_directory failed to remove {}, no such entry", trimmed_path ); - Err(Error::ENOENT) + Err(WasiError::ENOENT) } } } - fn unlink_file(&self, path: &str) -> Result<()> { + fn unlink_file(&self, path: &str) -> WasiResult<()> { let trimmed_path = path.trim_end_matches('/'); // Special case: we may be unlinking this directory itself if path is `"."`. In that case, // fail with EISDIR, since this is a directory. Alternatively, we may be unlinking `".."`, // which is bound the same way, as this is by definition contained in a directory. if trimmed_path == "." || trimmed_path == ".." { - return Err(Error::EISDIR); + return Err(WasiError::EISDIR); } let mut entries = self.entries.borrow_mut(); @@ -731,7 +747,7 @@ impl VirtualFile for VirtualDir { Entry::Occupied(e) => { // Directories must be removed through `remove_directory`, not `unlink_file`. if e.get().get_file_type() == wasi::__WASI_FILETYPE_DIRECTORY { - return Err(Error::EISDIR); + return Err(WasiError::EISDIR); } let removed = e.remove_entry(); @@ -746,15 +762,15 @@ impl VirtualFile for VirtualDir { "VirtualDir::unlink_file failed to remove {}, no such entry", trimmed_path ); - Err(Error::ENOENT) + Err(WasiError::ENOENT) } } } - fn create_directory(&self, path: &Path) -> Result<()> { + fn create_directory(&self, path: &Path) -> WasiResult<()> { let mut entries = self.entries.borrow_mut(); match entries.entry(path.to_owned()) { - Entry::Occupied(_) => Err(Error::EEXIST), + Entry::Occupied(_) => Err(WasiError::EEXIST), Entry::Vacant(v) => { if self.writable { let new_dir = Box::new(VirtualDir::new(true)); @@ -762,26 +778,26 @@ impl VirtualFile for VirtualDir { v.insert(new_dir); Ok(()) } else { - Err(Error::EACCES) + Err(WasiError::EACCES) } } } } - fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> Result { - Err(Error::EBADF) + fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> WasiResult { + Err(WasiError::EBADF) } fn readdir( &self, cookie: wasi::__wasi_dircookie_t, - ) -> Result>>> { + ) -> WasiResult>>> { struct VirtualDirIter { start: u32, entries: Rc>>>, } impl Iterator for VirtualDirIter { - type Item = Result; + type Item = WasiResult; fn next(&mut self) -> Option { log::trace!("VirtualDirIter::next continuing from {}", self.start); @@ -850,7 +866,7 @@ impl VirtualFile for VirtualDir { })) } - fn filestat_get(&self) -> Result { + fn filestat_get(&self) -> WasiResult { let stat = wasi::__wasi_filestat_t { dev: 0, ino: 0, diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index e418546a07..385541a0cf 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/crates/wasi-common/src/wasi.rs @@ -10,6 +10,115 @@ use wig::witx_wasi_types; witx_wasi_types!("snapshot" "wasi_snapshot_preview1"); +pub type WasiResult = Result; + +#[derive(Clone, Copy, Debug, thiserror::Error, Eq, PartialEq)] +#[repr(u16)] +#[error("{:?} ({})", self, strerror(*self as __wasi_errno_t))] +pub enum WasiError { + ESUCCESS = __WASI_ERRNO_SUCCESS, + E2BIG = __WASI_ERRNO_2BIG, + EACCES = __WASI_ERRNO_ACCES, + EADDRINUSE = __WASI_ERRNO_ADDRINUSE, + EADDRNOTAVAIL = __WASI_ERRNO_ADDRNOTAVAIL, + EAFNOSUPPORT = __WASI_ERRNO_AFNOSUPPORT, + EAGAIN = __WASI_ERRNO_AGAIN, + EALREADY = __WASI_ERRNO_ALREADY, + EBADF = __WASI_ERRNO_BADF, + EBADMSG = __WASI_ERRNO_BADMSG, + EBUSY = __WASI_ERRNO_BUSY, + ECANCELED = __WASI_ERRNO_CANCELED, + ECHILD = __WASI_ERRNO_CHILD, + ECONNABORTED = __WASI_ERRNO_CONNABORTED, + ECONNREFUSED = __WASI_ERRNO_CONNREFUSED, + ECONNRESET = __WASI_ERRNO_CONNRESET, + EDEADLK = __WASI_ERRNO_DEADLK, + EDESTADDRREQ = __WASI_ERRNO_DESTADDRREQ, + EDOM = __WASI_ERRNO_DOM, + EDQUOT = __WASI_ERRNO_DQUOT, + EEXIST = __WASI_ERRNO_EXIST, + EFAULT = __WASI_ERRNO_FAULT, + EFBIG = __WASI_ERRNO_FBIG, + EHOSTUNREACH = __WASI_ERRNO_HOSTUNREACH, + EIDRM = __WASI_ERRNO_IDRM, + EILSEQ = __WASI_ERRNO_ILSEQ, + EINPROGRESS = __WASI_ERRNO_INPROGRESS, + EINTR = __WASI_ERRNO_INTR, + EINVAL = __WASI_ERRNO_INVAL, + EIO = __WASI_ERRNO_IO, + EISCONN = __WASI_ERRNO_ISCONN, + EISDIR = __WASI_ERRNO_ISDIR, + ELOOP = __WASI_ERRNO_LOOP, + EMFILE = __WASI_ERRNO_MFILE, + EMLINK = __WASI_ERRNO_MLINK, + EMSGSIZE = __WASI_ERRNO_MSGSIZE, + EMULTIHOP = __WASI_ERRNO_MULTIHOP, + ENAMETOOLONG = __WASI_ERRNO_NAMETOOLONG, + ENETDOWN = __WASI_ERRNO_NETDOWN, + ENETRESET = __WASI_ERRNO_NETRESET, + ENETUNREACH = __WASI_ERRNO_NETUNREACH, + ENFILE = __WASI_ERRNO_NFILE, + ENOBUFS = __WASI_ERRNO_NOBUFS, + ENODEV = __WASI_ERRNO_NODEV, + ENOENT = __WASI_ERRNO_NOENT, + ENOEXEC = __WASI_ERRNO_NOEXEC, + ENOLCK = __WASI_ERRNO_NOLCK, + ENOLINK = __WASI_ERRNO_NOLINK, + ENOMEM = __WASI_ERRNO_NOMEM, + ENOMSG = __WASI_ERRNO_NOMSG, + ENOPROTOOPT = __WASI_ERRNO_NOPROTOOPT, + ENOSPC = __WASI_ERRNO_NOSPC, + ENOSYS = __WASI_ERRNO_NOSYS, + ENOTCONN = __WASI_ERRNO_NOTCONN, + ENOTDIR = __WASI_ERRNO_NOTDIR, + ENOTEMPTY = __WASI_ERRNO_NOTEMPTY, + ENOTRECOVERABLE = __WASI_ERRNO_NOTRECOVERABLE, + ENOTSOCK = __WASI_ERRNO_NOTSOCK, + ENOTSUP = __WASI_ERRNO_NOTSUP, + ENOTTY = __WASI_ERRNO_NOTTY, + ENXIO = __WASI_ERRNO_NXIO, + EOVERFLOW = __WASI_ERRNO_OVERFLOW, + EOWNERDEAD = __WASI_ERRNO_OWNERDEAD, + EPERM = __WASI_ERRNO_PERM, + EPIPE = __WASI_ERRNO_PIPE, + EPROTO = __WASI_ERRNO_PROTO, + EPROTONOSUPPORT = __WASI_ERRNO_PROTONOSUPPORT, + EPROTOTYPE = __WASI_ERRNO_PROTOTYPE, + ERANGE = __WASI_ERRNO_RANGE, + EROFS = __WASI_ERRNO_ROFS, + ESPIPE = __WASI_ERRNO_SPIPE, + ESRCH = __WASI_ERRNO_SRCH, + ESTALE = __WASI_ERRNO_STALE, + ETIMEDOUT = __WASI_ERRNO_TIMEDOUT, + ETXTBSY = __WASI_ERRNO_TXTBSY, + EXDEV = __WASI_ERRNO_XDEV, + ENOTCAPABLE = __WASI_ERRNO_NOTCAPABLE, +} + +impl WasiError { + pub fn as_raw_errno(self) -> __wasi_errno_t { + self as __wasi_errno_t + } +} + +impl From for WasiError { + fn from(_err: std::convert::Infallible) -> Self { + unreachable!() + } +} + +impl From for WasiError { + fn from(_err: std::num::TryFromIntError) -> Self { + Self::EOVERFLOW + } +} + +impl From for WasiError { + fn from(_err: std::str::Utf8Error) -> Self { + Self::EILSEQ + } +} + pub(crate) const RIGHTS_ALL: __wasi_rights_t = __WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_READ | __WASI_RIGHTS_FD_SEEK diff --git a/crates/wasi-common/wig/src/hostcalls.rs b/crates/wasi-common/wig/src/hostcalls.rs index df7d813f1d..938ca5a2e0 100644 --- a/crates/wasi-common/wig/src/hostcalls.rs +++ b/crates/wasi-common/wig/src/hostcalls.rs @@ -92,8 +92,7 @@ fn generate_wrappers(func: &witx::InterfaceFunc, old: bool) -> TokenStream { quote! { let ret = #call .err() - .unwrap_or(super::Error::ESUCCESS) - .as_wasi_error(); + .unwrap_or(super::wasi::WasiError::ESUCCESS); log::trace!(" | errno={}", ret); ret.as_raw_errno() }