From 19369142cbdd32d57fdf0bb8c5b2ff18ef43177b Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Mon, 17 Aug 2020 17:20:16 -0700 Subject: [PATCH 01/13] wasi-common: trace and convert error this is a bug - the TODO was never resolved, even when the code to implement it was added right below :) tracing is already in the transitive deps via wiggle, so no extra trouble there. tracing::debug is more appropriate than eprintln --- Cargo.lock | 13 +++++++------ crates/wasi-common/Cargo.toml | 1 + crates/wasi-common/src/wasi.rs | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e19c67c2e..fac8e273c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2156,9 +2156,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e2a2de6b0d5cbb13fc21193a2296888eaab62b6044479aafb3c54c01c29fcd" +checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" dependencies = [ "cfg-if", "log", @@ -2168,9 +2168,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b" +checksum = "1fe233f4227389ab7df5b32649239da7ebe0b281824b4e84b342d04d3fd8c25e" dependencies = [ "proc-macro2", "quote", @@ -2179,9 +2179,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ae75f0d28ae10786f3b1895c55fe72e79928fd5ccdebb5438c75e93fec178f" +checksum = "db63662723c316b43ca36d833707cc93dff82a02ba3d7e354f342682cc8b3545" dependencies = [ "lazy_static", ] @@ -2326,6 +2326,7 @@ dependencies = [ "libc", "log", "thiserror", + "tracing", "wig", "wiggle", "winapi", diff --git a/crates/wasi-common/Cargo.toml b/crates/wasi-common/Cargo.toml index c92e98a5e8..f7250c25df 100644 --- a/crates/wasi-common/Cargo.toml +++ b/crates/wasi-common/Cargo.toml @@ -27,6 +27,7 @@ filetime = "0.2.7" lazy_static = "1.4.0" wig = { path = "wig", version = "0.19.0" } wiggle = { path = "../wiggle", default-features = false, version = "0.19.0" } +tracing = "0.1.19" [target.'cfg(unix)'.dependencies] yanix = { path = "yanix", version = "0.19.0" } diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index f35055ffa8..c632461170 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/crates/wasi-common/src/wasi.rs @@ -2,6 +2,7 @@ //! pointer or `usize`-sized data are excluded here, so this file only contains //! fixed-size types, so it's host/target independent. use crate::WasiCtx; +use tracing::debug; wiggle::from_witx!({ witx: ["WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx"], @@ -19,9 +20,8 @@ impl wiggle::GuestErrorType for Errno { impl types::GuestErrorConversion for WasiCtx { fn into_errno(&self, e: wiggle::GuestError) -> Errno { - eprintln!("Guest error: {:?}", e); - // TODO proper error mapping - Errno::Inval + debug!("Guest error: {:?}", e); + e.into() } } From b8409dd9aa83d49985be3ff0f78da2026a44283f Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Mon, 17 Aug 2020 17:22:20 -0700 Subject: [PATCH 02/13] wasi-common: define an Error type for the crate --- crates/wasi-common/src/error.rs | 90 +++++++++++++++++++++++++++++++++ crates/wasi-common/src/lib.rs | 2 + 2 files changed, 92 insertions(+) create mode 100644 crates/wasi-common/src/error.rs diff --git a/crates/wasi-common/src/error.rs b/crates/wasi-common/src/error.rs new file mode 100644 index 0000000000..932519200d --- /dev/null +++ b/crates/wasi-common/src/error.rs @@ -0,0 +1,90 @@ +use thiserror::Error; + +pub type Result = std::result::Result; + +/// Internal error type for the `wasi-common` crate. +/// Contains variants of the WASI `$errno` type are added according to what is actually used internally by +/// the crate. Not all values are represented presently, +#[derive(Debug, Error)] +pub enum Error { + #[error(display = "Wiggle GuestError: {0}")] + Guest(#[from] wiggle::GuestError), + #[error(display = "TryFromIntError: {0}")] + TryFromInt(#[from] std::num::TryFromIntError), + #[error(display = "Utf8Error: {0}")] + Utf8(#[from] std::str::Utf8Error), + + // Below this, all variants are from the `$errno` type: + /// Errno::TooBig: Argument list too long + #[error(display = "TooBig: Argument list too long")] + TooBig, + /// Errno::Acces: Permission denied + #[error(display = "Acces: Permission denied")] + Acces, + /// Errno::Badf: Bad file descriptor + #[error(display = "Badf: Bad file descriptor")] + Badf, + /// Errno::Exist: File exists + #[error(display = "Exist: File exists")] + Exist, + /// Errno::Fault: Bad address + #[error(display = "Fault: Bad address")] + Fault, + /// Errno::Fbig: File too large + #[error(display = "Fbig: File too large")] + Fbig, + /// Errno::Ilseq: Illegal byte sequence + #[error(display = "Ilseq: Illegal byte sequence")] + Ilseq, + /// Errno::Inval: Invalid argument + #[error(display = "Inval: Invalid argument")] + Inval, + /// Errno::Io: I/O error + #[error(display = "Io: I/o error")] + Io, + /// Errno::Isdir: Is a directory + #[error(display = "Isdir: Is a directory")] + Isdir, + /// Errno::Loop: Too many levels of symbolic links + #[error(display = "Loop: Too many levels of symbolic links")] + Loop, + /// Errno::Mfile: File descriptor value too large + #[error(display = "Mfile: File descriptor value too large")] + Mfile, + /// Errno::Mlink: Too many links + #[error(display = "Mlink: Too many links")] + Mlink, + /// Errno::Nametoolong: Filename too long + #[error(display = "Nametoolong: Filename too long")] + Nametoolong, + /// Errno::Noent: No such file or directory + #[error(display = "Noent: No such file or directory")] + Noent, + /// Errno::Nospc: No space left on device + #[error(display = "Nospc: No space left on device")] + Nospc, + /// Errno::Notempty: Directory not empty. + #[error(display = "Notempty: Directory not empty")] + Notempty, + /// Errno::Notsup: Not supported, or operation not supported on socket. + #[error(display = "Notsup: Not supported, or operation not supported on socket")] + Notsup, + /// Errno::Overflow: Value too large to be stored in data type. + #[error(display = "Overflow: Value too large to be stored in data type")] + Overflow, + /// Errno::Perm: Operation not permitted + #[error(display = "Perm: Operation not permitted")] + Perm, + /// Errno::Spipe: Invalid seek + #[error(display = "Spipe: Invalid seek")] + Spipe, + /// Errno::Notcapable: Extension: Capabilities insufficient + #[error(display = "Notcapable: cabailities insufficient")] + Notcapable, +} + +impl From for Error { + fn from(_err: std::convert::Infallible) -> Self { + unreachable!("should be impossible: From") + } +} diff --git a/crates/wasi-common/src/lib.rs b/crates/wasi-common/src/lib.rs index 65b5ea047d..76e64bb3c0 100644 --- a/crates/wasi-common/src/lib.rs +++ b/crates/wasi-common/src/lib.rs @@ -23,6 +23,7 @@ mod ctx; mod entry; +mod error; mod fdpool; pub mod fs; mod handle; @@ -36,6 +37,7 @@ pub mod virtfs; pub mod wasi; pub use ctx::{WasiCtx, WasiCtxBuilder, WasiCtxBuilderError}; +pub use error::{Error, Result}; pub use handle::{Handle, HandleRights}; pub use sys::osdir::OsDir; pub use sys::osfile::OsFile; From e8160c9a6b8a58fad313bbce4c7a5ea4dc93a43b Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Mon, 17 Aug 2020 18:45:33 -0700 Subject: [PATCH 03/13] redefine crate to use `Error` everywhere except in `wasi` --- crates/wasi-common/src/ctx.rs | 8 +- crates/wasi-common/src/entry.rs | 8 +- crates/wasi-common/src/error.rs | 58 ++--- crates/wasi-common/src/fs/file.rs | 3 +- crates/wasi-common/src/handle.rs | 50 ++--- crates/wasi-common/src/path.rs | 46 ++-- .../src/snapshots/wasi_snapshot_preview1.rs | 46 ++-- crates/wasi-common/src/sys/clock.rs | 4 +- crates/wasi-common/src/sys/fd.rs | 5 +- crates/wasi-common/src/sys/osdir.rs | 7 +- crates/wasi-common/src/sys/osfile.rs | 7 +- crates/wasi-common/src/sys/osother.rs | 2 +- crates/wasi-common/src/sys/stdio.rs | 5 +- crates/wasi-common/src/sys/unix/bsd/osdir.rs | 2 +- crates/wasi-common/src/sys/unix/bsd/path.rs | 10 +- crates/wasi-common/src/sys/unix/clock.rs | 9 +- crates/wasi-common/src/sys/unix/fd.rs | 3 +- .../wasi-common/src/sys/unix/linux/osdir.rs | 2 +- crates/wasi-common/src/sys/unix/linux/path.rs | 2 +- crates/wasi-common/src/sys/unix/mod.rs | 99 +-------- crates/wasi-common/src/sys/unix/path.rs | 11 +- crates/wasi-common/src/sys/unix/poll.rs | 13 +- crates/wasi-common/src/sys/windows/clock.rs | 5 +- crates/wasi-common/src/sys/windows/fd.rs | 3 +- crates/wasi-common/src/sys/windows/mod.rs | 50 +---- crates/wasi-common/src/sys/windows/path.rs | 49 ++-- crates/wasi-common/src/sys/windows/poll.rs | 19 +- crates/wasi-common/src/virtfs.rs | 85 +++---- crates/wasi-common/src/virtfs/pipe.rs | 59 ++--- crates/wasi-common/src/wasi.rs | 210 ++++++++++++++++-- 30 files changed, 465 insertions(+), 415 deletions(-) diff --git a/crates/wasi-common/src/ctx.rs b/crates/wasi-common/src/ctx.rs index 05bb0fce94..8effbb4cc3 100644 --- a/crates/wasi-common/src/ctx.rs +++ b/crates/wasi-common/src/ctx.rs @@ -6,7 +6,7 @@ use crate::sys::stdio::NullDevice; use crate::sys::stdio::{Stderr, StderrExt, Stdin, StdinExt, Stdout, StdoutExt}; use crate::virtfs::{VirtualDir, VirtualDirEntry}; use crate::wasi::types; -use crate::wasi::{Errno, Result}; +use crate::{Error, Result}; use std::borrow::Borrow; use std::cell::RefCell; use std::collections::HashMap; @@ -466,7 +466,7 @@ impl WasiCtx { pub(crate) fn get_entry(&self, fd: types::Fd) -> Result> { match self.entries.borrow().get(&fd) { Some(entry) => Ok(entry), - None => Err(Errno::Badf), + None => Err(Error::Badf), } } @@ -475,7 +475,7 @@ impl WasiCtx { /// The `Entry` 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_entry(&self, entry: Entry) -> Result { - self.entries.borrow_mut().insert(entry).ok_or(Errno::Mfile) + self.entries.borrow_mut().insert(entry).ok_or(Error::Mfile) } /// Insert the specified `Entry` with the specified raw WASI `fd` key into the `WasiCtx` @@ -486,6 +486,6 @@ impl WasiCtx { /// Remove `Entry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object. pub(crate) fn remove_entry(&self, fd: types::Fd) -> Result> { - self.entries.borrow_mut().remove(fd).ok_or(Errno::Badf) + self.entries.borrow_mut().remove(fd).ok_or(Error::Badf) } } diff --git a/crates/wasi-common/src/entry.rs b/crates/wasi-common/src/entry.rs index ba9e90c160..f401a602f2 100644 --- a/crates/wasi-common/src/entry.rs +++ b/crates/wasi-common/src/entry.rs @@ -1,6 +1,6 @@ use crate::handle::{Handle, HandleRights}; use crate::wasi::types::Filetype; -use crate::wasi::{Errno, Result}; +use crate::{Error, Result}; use std::ops::Deref; use std::path::PathBuf; use std::rc::Rc; @@ -71,7 +71,7 @@ impl Entry { /// The `Entry` can only be converted into a valid `Handle` object if /// the specified set of base rights, and inheriting rights encapsulated within `rights` /// `HandleRights` structure is a subset of rights attached to this `Entry`. The check is - /// performed using `Entry::validate_rights` method. If the check fails, `Errno::Notcapable` + /// performed using `Entry::validate_rights` method. If the check fails, `Error::Notcapable` /// is returned. pub(crate) fn as_handle(&self, rights: &HandleRights) -> Result { self.validate_rights(rights)?; @@ -81,7 +81,7 @@ impl Entry { /// Check if this `Entry` object satisfies the specified `HandleRights`; i.e., if /// rights attached to this `Entry` object are a superset. /// - /// Upon unsuccessful check, `Errno::Notcapable` is returned. + /// Upon unsuccessful check, `Error::Notcapable` is returned. pub(crate) fn validate_rights(&self, rights: &HandleRights) -> Result<()> { let this_rights = self.handle.get_rights(); if this_rights.contains(rights) { @@ -92,7 +92,7 @@ impl Entry { rights, this_rights, ); - Err(Errno::Notcapable) + Err(Error::Notcapable) } } } diff --git a/crates/wasi-common/src/error.rs b/crates/wasi-common/src/error.rs index 932519200d..af6d83ea3c 100644 --- a/crates/wasi-common/src/error.rs +++ b/crates/wasi-common/src/error.rs @@ -4,82 +4,88 @@ pub type Result = std::result::Result; /// Internal error type for the `wasi-common` crate. /// Contains variants of the WASI `$errno` type are added according to what is actually used internally by -/// the crate. Not all values are represented presently, +/// the crate. Not all values are represented presently. #[derive(Debug, Error)] pub enum Error { - #[error(display = "Wiggle GuestError: {0}")] + #[error("Wiggle GuestError: {0}")] Guest(#[from] wiggle::GuestError), - #[error(display = "TryFromIntError: {0}")] + #[error("TryFromIntError: {0}")] TryFromInt(#[from] std::num::TryFromIntError), - #[error(display = "Utf8Error: {0}")] + #[error("Utf8Error: {0}")] Utf8(#[from] std::str::Utf8Error), + #[error("IO: {0}")] + IoError(#[from] std::io::Error), + // Below this, all variants are from the `$errno` type: /// Errno::TooBig: Argument list too long - #[error(display = "TooBig: Argument list too long")] + #[error("TooBig: Argument list too long")] TooBig, /// Errno::Acces: Permission denied - #[error(display = "Acces: Permission denied")] + #[error("Acces: Permission denied")] Acces, /// Errno::Badf: Bad file descriptor - #[error(display = "Badf: Bad file descriptor")] + #[error("Badf: Bad file descriptor")] Badf, /// Errno::Exist: File exists - #[error(display = "Exist: File exists")] + #[error("Exist: File exists")] Exist, /// Errno::Fault: Bad address - #[error(display = "Fault: Bad address")] + #[error("Fault: Bad address")] Fault, /// Errno::Fbig: File too large - #[error(display = "Fbig: File too large")] + #[error("Fbig: File too large")] Fbig, /// Errno::Ilseq: Illegal byte sequence - #[error(display = "Ilseq: Illegal byte sequence")] + #[error("Ilseq: Illegal byte sequence")] Ilseq, /// Errno::Inval: Invalid argument - #[error(display = "Inval: Invalid argument")] + #[error("Inval: Invalid argument")] Inval, /// Errno::Io: I/O error - #[error(display = "Io: I/o error")] + #[error("Io: I/o error")] Io, /// Errno::Isdir: Is a directory - #[error(display = "Isdir: Is a directory")] + #[error("Isdir: Is a directory")] Isdir, /// Errno::Loop: Too many levels of symbolic links - #[error(display = "Loop: Too many levels of symbolic links")] + #[error("Loop: Too many levels of symbolic links")] Loop, /// Errno::Mfile: File descriptor value too large - #[error(display = "Mfile: File descriptor value too large")] + #[error("Mfile: File descriptor value too large")] Mfile, /// Errno::Mlink: Too many links - #[error(display = "Mlink: Too many links")] + #[error("Mlink: Too many links")] Mlink, /// Errno::Nametoolong: Filename too long - #[error(display = "Nametoolong: Filename too long")] + #[error("Nametoolong: Filename too long")] Nametoolong, /// Errno::Noent: No such file or directory - #[error(display = "Noent: No such file or directory")] + #[error("Noent: No such file or directory")] Noent, /// Errno::Nospc: No space left on device - #[error(display = "Nospc: No space left on device")] + #[error("Nospc: No space left on device")] Nospc, + /// Errno::Notdir: Not a directory or a symbolic link to a directory. + #[error("Notdir: Not a directory or a symbolic link to a directory")] + Notdir, /// Errno::Notempty: Directory not empty. - #[error(display = "Notempty: Directory not empty")] + #[error("Notempty: Directory not empty")] Notempty, /// Errno::Notsup: Not supported, or operation not supported on socket. - #[error(display = "Notsup: Not supported, or operation not supported on socket")] + #[error("Notsup: Not supported, or operation not supported on socket")] Notsup, /// Errno::Overflow: Value too large to be stored in data type. - #[error(display = "Overflow: Value too large to be stored in data type")] + #[error("Overflow: Value too large to be stored in data type")] Overflow, /// Errno::Perm: Operation not permitted - #[error(display = "Perm: Operation not permitted")] + #[error("Perm: Operation not permitted")] Perm, /// Errno::Spipe: Invalid seek - #[error(display = "Spipe: Invalid seek")] + #[error("Spipe: Invalid seek")] Spipe, /// Errno::Notcapable: Extension: Capabilities insufficient - #[error(display = "Notcapable: cabailities insufficient")] + #[error("Notcapable: cabailities insufficient")] Notcapable, } diff --git a/crates/wasi-common/src/fs/file.rs b/crates/wasi-common/src/fs/file.rs index 9382804052..39a3b5a274 100644 --- a/crates/wasi-common/src/fs/file.rs +++ b/crates/wasi-common/src/fs/file.rs @@ -1,6 +1,7 @@ use crate::fs::Metadata; +use crate::wasi::types; use crate::wasi::wasi_snapshot_preview1::WasiSnapshotPreview1; -use crate::wasi::{types, Result}; +use crate::Result; use crate::WasiCtx; use std::io; diff --git a/crates/wasi-common/src/handle.rs b/crates/wasi-common/src/handle.rs index 8cdf6a4c57..72f0a7db1b 100644 --- a/crates/wasi-common/src/handle.rs +++ b/crates/wasi-common/src/handle.rs @@ -1,5 +1,5 @@ use crate::wasi::types::{self, Rights}; -use crate::wasi::{Errno, Result}; +use crate::{Error, Result}; use std::any::Any; use std::fmt; use std::io::{self, SeekFrom}; @@ -107,25 +107,25 @@ pub trait Handle { _offset: types::Filesize, _len: types::Filesize, ) -> Result<()> { - Err(Errno::Badf) + Err(Error::Badf) } fn allocate(&self, _offset: types::Filesize, _len: types::Filesize) -> Result<()> { - Err(Errno::Badf) + Err(Error::Badf) } fn datasync(&self) -> Result<()> { - Err(Errno::Inval) + Err(Error::Inval) } fn fdstat_get(&self) -> Result { Ok(types::Fdflags::empty()) } fn fdstat_set_flags(&self, _fdflags: types::Fdflags) -> Result<()> { - Err(Errno::Badf) + Err(Error::Badf) } fn filestat_get(&self) -> Result { - Err(Errno::Badf) + Err(Error::Badf) } fn filestat_set_size(&self, _st_size: types::Filesize) -> Result<()> { - Err(Errno::Badf) + Err(Error::Badf) } fn filestat_set_times( &self, @@ -133,39 +133,39 @@ pub trait Handle { _mtim: types::Timestamp, _fst_flags: types::Fstflags, ) -> Result<()> { - Err(Errno::Badf) + Err(Error::Badf) } fn preadv(&self, _buf: &mut [io::IoSliceMut], _offset: u64) -> Result { - Err(Errno::Badf) + Err(Error::Badf) } fn pwritev(&self, _buf: &[io::IoSlice], _offset: u64) -> Result { - Err(Errno::Badf) + Err(Error::Badf) } fn read_vectored(&self, _iovs: &mut [io::IoSliceMut]) -> Result { - Err(Errno::Badf) + Err(Error::Badf) } fn readdir<'a>( &'a self, _cookie: types::Dircookie, ) -> Result> + 'a>> { - Err(Errno::Badf) + Err(Error::Badf) } fn seek(&self, _offset: SeekFrom) -> Result { - Err(Errno::Badf) + Err(Error::Badf) } fn sync(&self) -> Result<()> { Ok(()) } fn write_vectored(&self, _iovs: &[io::IoSlice]) -> Result { - Err(Errno::Badf) + Err(Error::Badf) } // TODO perhaps should be a separate trait? // PathOps fn create_directory(&self, _path: &str) -> Result<()> { - Err(Errno::Acces) + Err(Error::Acces) } fn filestat_get_at(&self, _path: &str, _follow: bool) -> Result { - Err(Errno::Acces) + Err(Error::Acces) } fn filestat_set_times_at( &self, @@ -175,7 +175,7 @@ pub trait Handle { _fst_flags: types::Fstflags, _follow: bool, ) -> Result<()> { - Err(Errno::Acces) + Err(Error::Acces) } fn openat( &self, @@ -185,7 +185,7 @@ pub trait Handle { _oflags: types::Oflags, _fd_flags: types::Fdflags, ) -> Result> { - Err(Errno::Acces) + Err(Error::Acces) } fn link( &self, @@ -194,24 +194,24 @@ pub trait Handle { _new_path: &str, _follow: bool, ) -> Result<()> { - Err(Errno::Acces) + Err(Error::Acces) } fn readlink(&self, _path: &str, _buf: &mut [u8]) -> Result { - Err(Errno::Acces) + Err(Error::Acces) } fn readlinkat(&self, _path: &str) -> Result { - Err(Errno::Acces) + Err(Error::Acces) } fn remove_directory(&self, _path: &str) -> Result<()> { - Err(Errno::Acces) + Err(Error::Acces) } fn rename(&self, _old_path: &str, _new_handle: Box, _new_path: &str) -> Result<()> { - Err(Errno::Acces) + Err(Error::Acces) } fn symlink(&self, _old_path: &str, _new_path: &str) -> Result<()> { - Err(Errno::Acces) + Err(Error::Acces) } fn unlink_file(&self, _path: &str) -> Result<()> { - Err(Errno::Acces) + Err(Error::Acces) } } diff --git a/crates/wasi-common/src/path.rs b/crates/wasi-common/src/path.rs index fdce7b481a..b7065d664c 100644 --- a/crates/wasi-common/src/path.rs +++ b/crates/wasi-common/src/path.rs @@ -1,6 +1,7 @@ use crate::entry::Entry; use crate::handle::{Handle, HandleRights}; -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use std::path::{Component, Path}; use std::str; use wiggle::GuestPtr; @@ -26,12 +27,12 @@ pub(crate) fn get( if path.contains('\0') { // if contains NUL, return Ilseq - return Err(Errno::Ilseq); + return Err(Error::Ilseq); } if entry.get_file_type() != types::Filetype::Directory { // if `dirfd` doesn't refer to a directory, return `Notdir`. - return Err(Errno::Notdir); + return Err(Error::Notdir); } let handle = entry.as_handle(required_rights)?; @@ -60,7 +61,7 @@ pub(crate) fn 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(Errno::Noent), + None => return Err(Error::Noent), Some(p) => p, }; let tail = components.as_path(); @@ -78,18 +79,18 @@ pub(crate) fn get( match head { Component::Prefix(_) | Component::RootDir => { // path is absolute! - return Err(Errno::Notcapable); + return Err(Error::Notcapable); } Component::CurDir => { // "." so skip } Component::ParentDir => { // ".." so pop a dir - let _ = dir_stack.pop().ok_or(Errno::Notcapable)?; + let _ = dir_stack.pop().ok_or(Error::Notcapable)?; // we're not allowed to pop past the original directory if dir_stack.is_empty() { - return Err(Errno::Notcapable); + return Err(Error::Notcapable); } } Component::Normal(head) => { @@ -100,7 +101,7 @@ pub(crate) fn get( } if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) { - let fd = dir_stack.last().ok_or(Errno::Notcapable)?; + let fd = dir_stack.last().ok_or(Error::Notcapable)?; match fd.openat( &head, false, @@ -113,16 +114,16 @@ pub(crate) fn get( } Err(e) => { match e { - Errno::Loop | Errno::Mlink | Errno::Notdir => + Error::Loop | Error::Mlink | Error::Notdir => // Check to see if it was a symlink. Linux indicates // this with ENOTDIR because of the O_DIRECTORY flag. { // attempt symlink expansion - let fd = dir_stack.last().ok_or(Errno::Notcapable)?; + let fd = dir_stack.last().ok_or(Error::Notcapable)?; let mut link_path = fd.readlinkat(&head)?; symlink_expansions += 1; if symlink_expansions > MAX_SYMLINK_EXPANSIONS { - return Err(Errno::Loop); + return Err(Error::Loop); } if head.ends_with('/') { @@ -149,12 +150,12 @@ pub(crate) fn get( { // if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt // symlink expansion - let fd = dir_stack.last().ok_or(Errno::Notcapable)?; + let fd = dir_stack.last().ok_or(Error::Notcapable)?; match fd.readlinkat(&head) { Ok(mut link_path) => { symlink_expansions += 1; if symlink_expansions > MAX_SYMLINK_EXPANSIONS { - return Err(Errno::Loop); + return Err(Error::Loop); } if head.ends_with('/') { @@ -169,29 +170,26 @@ pub(crate) fn get( path_stack.push(link_path); continue; } + Err(Error::Inval) | Err(Error::Noent) | Err(Error::Notdir) => { + // this handles the cases when trying to link to + // a destination that already exists, and the target + // path contains a slash + } Err(e) => { - if e != Errno::Inval - && e != Errno::Noent - // this handles the cases when trying to link to - // a destination that already exists, and the target - // path contains a slash - && e != Errno::Notdir - { - return Err(e); - } + return Err(e); } } } // not a symlink, so we're done; - return Ok((dir_stack.pop().ok_or(Errno::Notcapable)?, head)); + return Ok((dir_stack.pop().ok_or(Error::Notcapable)?, head)); } } } None => { // 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((dir_stack.pop().ok_or(Errno::Notcapable)?, String::from("."))); + return Ok((dir_stack.pop().ok_or(Error::Notcapable)?, String::from("."))); } } } diff --git a/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs b/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs index a6d3d97d44..9f2eaa1443 100644 --- a/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs +++ b/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs @@ -2,9 +2,9 @@ use crate::entry::{Entry, EntryHandle}; use crate::handle::HandleRights; use crate::sys::clock; use crate::wasi::wasi_snapshot_preview1::WasiSnapshotPreview1; -use crate::wasi::{types, AsBytes, Errno, Result}; -use crate::WasiCtx; +use crate::wasi::{types, AsBytes}; use crate::{path, poll}; +use crate::{Error, Result, WasiCtx}; use log::{debug, error, trace}; use std::convert::TryInto; use std::io::{self, SeekFrom}; @@ -36,7 +36,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { let mut argv_size: types::Size = 0; for arg in &self.args { let arg_len = arg.as_bytes_with_nul().len().try_into()?; - argv_size = argv_size.checked_add(arg_len).ok_or(Errno::Overflow)?; + argv_size = argv_size.checked_add(arg_len).ok_or(Error::Overflow)?; } Ok((argc, argv_size)) } @@ -66,7 +66,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { let mut environ_size: types::Size = 0; for environ in &self.env { let env_len = environ.as_bytes_with_nul().len().try_into()?; - environ_size = environ_size.checked_add(env_len).ok_or(Errno::Overflow)?; + environ_size = environ_size.checked_add(env_len).ok_or(Error::Overflow)?; } Ok((environ_count, environ_size)) } @@ -114,7 +114,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { if let Ok(fe) = self.get_entry(fd) { // can't close preopened files if fe.preopen_path.is_some() { - return Err(Errno::Notsup); + return Err(Error::Notsup); } } self.remove_entry(fd)?; @@ -156,7 +156,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { let rights = HandleRights::new(fs_rights_base, fs_rights_inheriting); let entry = self.get_entry(fd)?; if !entry.get_rights().contains(&rights) { - return Err(Errno::Notcapable); + return Err(Error::Notcapable); } entry.set_rights(rights); Ok(()) @@ -174,7 +174,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { let entry = self.get_entry(fd)?; // This check will be unnecessary when rust-lang/rust#63326 is fixed if size > i64::max_value() as u64 { - return Err(Errno::TooBig); + return Err(Error::TooBig); } entry.as_handle(&required_rights)?.filestat_set_size(size) } @@ -210,7 +210,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { HandleRights::from_base(types::Rights::FD_READ | types::Rights::FD_SEEK); let entry = self.get_entry(fd)?; if offset > i64::max_value() as u64 { - return Err(Errno::Io); + return Err(Error::Io); } let host_nread = { @@ -229,9 +229,9 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { fn fd_prestat_get(&self, fd: types::Fd) -> Result { // TODO: should we validate any rights here? let entry = self.get_entry(fd)?; - let po_path = entry.preopen_path.as_ref().ok_or(Errno::Notsup)?; + let po_path = entry.preopen_path.as_ref().ok_or(Error::Notsup)?; if entry.get_file_type() != types::Filetype::Directory { - return Err(Errno::Notdir); + return Err(Error::Notdir); } let path = path::from_host(po_path.as_os_str())?; @@ -249,16 +249,16 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { ) -> Result<()> { // TODO: should we validate any rights here? let entry = self.get_entry(fd)?; - let po_path = entry.preopen_path.as_ref().ok_or(Errno::Notsup)?; + let po_path = entry.preopen_path.as_ref().ok_or(Error::Notsup)?; if entry.get_file_type() != types::Filetype::Directory { - return Err(Errno::Notdir); + return Err(Error::Notdir); } let host_path = path::from_host(po_path.as_os_str())?; let host_path_len = host_path.len().try_into()?; if host_path_len > path_len { - return Err(Errno::Nametoolong); + return Err(Error::Nametoolong); } trace!(" | path='{}'", host_path); @@ -287,7 +287,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { let entry = self.get_entry(fd)?; if offset > i64::max_value() as u64 { - return Err(Errno::Io); + return Err(Error::Io); } let host_nwritten = { @@ -343,7 +343,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { let dirent_len: types::Size = dirent_raw.len().try_into()?; let name_raw = name.as_bytes(); let name_len = name_raw.len().try_into()?; - let offset = dirent_len.checked_add(name_len).ok_or(Errno::Overflow)?; + let offset = dirent_len.checked_add(name_len).ok_or(Error::Overflow)?; if (buf_len - bufused) < offset { break; } else { @@ -360,7 +360,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { fn fd_renumber(&self, from: types::Fd, to: types::Fd) -> Result<()> { if !self.contains_entry(from) { - return Err(Errno::Badf); + return Err(Error::Badf); } // Don't allow renumbering over a pre-opened resource. @@ -368,12 +368,12 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { // userspace is capable of removing entries from its tables as well. if let Ok(from_fe) = self.get_entry(from) { if from_fe.preopen_path.is_some() { - return Err(Errno::Notsup); + return Err(Error::Notsup); } } if let Ok(to_fe) = self.get_entry(to) { if to_fe.preopen_path.is_some() { - return Err(Errno::Notsup); + return Err(Error::Notsup); } } let fe = self.remove_entry(from)?; @@ -676,7 +676,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { nsubscriptions: types::Size, ) -> Result { if u64::from(nsubscriptions) > types::Filesize::max_value() { - return Err(Errno::Inval); + return Err(Error::Inval); } let mut subscriptions = Vec::new(); @@ -694,7 +694,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { // As mandated by the WASI spec: // > If `nsubscriptions` is 0, returns `errno::inval`. if subscriptions.is_empty() { - return Err(Errno::Inval); + return Err(Error::Inval); } for subscription in subscriptions { @@ -722,7 +722,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { Err(error) => { events.push(types::Event { userdata: subscription.userdata, - error, + error: error.into(), type_: types::Eventtype::FdRead, fd_readwrite: types::EventFdReadwrite { nbytes: 0, @@ -748,7 +748,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { Err(error) => { events.push(types::Event { userdata: subscription.userdata, - error, + error: error.into(), type_: types::Eventtype::FdWrite, fd_readwrite: types::EventFdReadwrite { nbytes: 0, @@ -804,7 +804,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { let mut slice = buf.as_array(buf_len).as_slice()?; getrandom::getrandom(&mut *slice).map_err(|err| { error!("getrandom failure: {:?}", err); - Errno::Io + Error::Io }) } diff --git a/crates/wasi-common/src/sys/clock.rs b/crates/wasi-common/src/sys/clock.rs index 28a04f597b..a31bb1b131 100644 --- a/crates/wasi-common/src/sys/clock.rs +++ b/crates/wasi-common/src/sys/clock.rs @@ -1,5 +1,5 @@ use crate::wasi::types::{Subclockflags, SubscriptionClock}; -use crate::wasi::{Errno, Result}; +use crate::{Error, Result}; use std::time::SystemTime; pub(crate) use super::sys_impl::clock::*; @@ -10,7 +10,7 @@ pub(crate) fn to_relative_ns_delay(clock: &SubscriptionClock) -> Result { } let now: u128 = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .map_err(|_| Errno::Notcapable)? + .map_err(|_| Error::Notcapable)? .as_nanos(); let deadline = u128::from(clock.timeout); Ok(deadline.saturating_sub(now)) diff --git a/crates/wasi-common/src/sys/fd.rs b/crates/wasi-common/src/sys/fd.rs index 2fa59ee95c..ed6cd36b99 100644 --- a/crates/wasi-common/src/sys/fd.rs +++ b/crates/wasi-common/src/sys/fd.rs @@ -1,4 +1,5 @@ -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use filetime::{set_file_handle_times, FileTime}; use std::fs::File; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -17,7 +18,7 @@ pub(crate) fn filestat_set_times( let set_mtim_now = fst_flags.contains(&types::Fstflags::MTIM_NOW); if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { - return Err(Errno::Inval); + return Err(Error::Inval); } let atim = if set_atim { let time = UNIX_EPOCH + Duration::from_nanos(st_atim); diff --git a/crates/wasi-common/src/sys/osdir.rs b/crates/wasi-common/src/sys/osdir.rs index 6ba3cc63a9..87db639b1c 100644 --- a/crates/wasi-common/src/sys/osdir.rs +++ b/crates/wasi-common/src/sys/osdir.rs @@ -1,7 +1,8 @@ use super::sys_impl::oshandle::RawOsHandle; use super::{fd, path, AsFile}; use crate::handle::{Handle, HandleRights}; -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use log::{debug, error}; use std::any::Any; use std::io; @@ -102,7 +103,7 @@ impl Handle for OsDir { let new_handle = match new_handle.as_any().downcast_ref::() { None => { error!("Tried to link with handle that's not an OsDir"); - return Err(Errno::Badf); + return Err(Error::Badf); } Some(handle) => handle, }; @@ -121,7 +122,7 @@ impl Handle for OsDir { let new_handle = match new_handle.as_any().downcast_ref::() { None => { error!("Tried to rename with handle that's not an OsDir"); - return Err(Errno::Badf); + return Err(Error::Badf); } Some(handle) => handle, }; diff --git a/crates/wasi-common/src/sys/osfile.rs b/crates/wasi-common/src/sys/osfile.rs index f07ddf6240..31a2ccbf0e 100644 --- a/crates/wasi-common/src/sys/osfile.rs +++ b/crates/wasi-common/src/sys/osfile.rs @@ -1,7 +1,8 @@ use super::sys_impl::oshandle::RawOsHandle; use super::{fd, AsFile}; use crate::handle::{Handle, HandleRights}; -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use std::any::Any; use std::cell::Cell; use std::fs::File; @@ -77,10 +78,10 @@ impl Handle for OsFile { let fd = self.as_file()?; let metadata = fd.metadata()?; let current_size = metadata.len(); - let wanted_size = offset.checked_add(len).ok_or(Errno::TooBig)?; + let wanted_size = offset.checked_add(len).ok_or(Error::TooBig)?; // This check will be unnecessary when rust-lang/rust#63326 is fixed if wanted_size > i64::max_value() as u64 { - return Err(Errno::TooBig); + return Err(Error::TooBig); } if wanted_size > current_size { fd.set_len(wanted_size)?; diff --git a/crates/wasi-common/src/sys/osother.rs b/crates/wasi-common/src/sys/osother.rs index 4e5c90192d..73c359493e 100644 --- a/crates/wasi-common/src/sys/osother.rs +++ b/crates/wasi-common/src/sys/osother.rs @@ -3,7 +3,7 @@ use super::{fd, AsFile}; use crate::handle::{Handle, HandleRights}; use crate::sandboxed_tty_writer::SandboxedTTYWriter; use crate::wasi::types::{self, Filetype}; -use crate::wasi::Result; +use crate::Result; use std::any::Any; use std::cell::Cell; use std::fs::File; diff --git a/crates/wasi-common/src/sys/stdio.rs b/crates/wasi-common/src/sys/stdio.rs index 786643b559..ef5535c7ee 100644 --- a/crates/wasi-common/src/sys/stdio.rs +++ b/crates/wasi-common/src/sys/stdio.rs @@ -20,7 +20,8 @@ use super::{fd, AsFile}; use crate::handle::{Handle, HandleRights}; use crate::sandboxed_tty_writer::SandboxedTTYWriter; use crate::wasi::types::{self, Filetype}; -use crate::wasi::{Errno, Result, RightsExt}; +use crate::wasi::RightsExt; +use crate::{Error, Result}; use std::any::Any; use std::cell::Cell; use std::convert::TryInto; @@ -226,7 +227,7 @@ impl Handle for NullDevice { let mut total_len = 0u32; for iov in iovs { let len: types::Size = iov.len().try_into()?; - total_len = total_len.checked_add(len).ok_or(Errno::Overflow)?; + total_len = total_len.checked_add(len).ok_or(Error::Overflow)?; } Ok(total_len as usize) } diff --git a/crates/wasi-common/src/sys/unix/bsd/osdir.rs b/crates/wasi-common/src/sys/unix/bsd/osdir.rs index ed665329d6..b375254baa 100644 --- a/crates/wasi-common/src/sys/unix/bsd/osdir.rs +++ b/crates/wasi-common/src/sys/unix/bsd/osdir.rs @@ -1,6 +1,6 @@ use crate::handle::HandleRights; use crate::sys::sys_impl::oshandle::RawOsHandle; -use crate::wasi::Result; +use crate::Result; use std::cell::{Cell, RefCell, RefMut}; use std::io; use yanix::dir::Dir; diff --git a/crates/wasi-common/src/sys/unix/bsd/path.rs b/crates/wasi-common/src/sys/unix/bsd/path.rs index ab79064e8d..7c42495e07 100644 --- a/crates/wasi-common/src/sys/unix/bsd/path.rs +++ b/crates/wasi-common/src/sys/unix/bsd/path.rs @@ -1,5 +1,5 @@ use crate::sys::osdir::OsDir; -use crate::wasi::{Errno, Result}; +use crate::{Error, Result}; use std::os::unix::prelude::AsRawFd; pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> { @@ -20,7 +20,7 @@ pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> { match unsafe { fstatat(dirfd.as_raw_fd(), path, AtFlags::SYMLINK_NOFOLLOW) } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory { - return Err(Errno::Isdir); + return Err(Error::Isdir); } } Err(err) => { @@ -56,7 +56,7 @@ pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path: &str) -> Resu let new_path = new_path.trim_end_matches('/'); match unsafe { fstatat(new_dirfd.as_raw_fd(), new_path, AtFlags::SYMLINK_NOFOLLOW) } { - Ok(_) => return Err(Errno::Exist), + Ok(_) => return Err(Error::Exist), Err(err) => { log::debug!("path_symlink fstatat error: {:?}", err); } @@ -100,9 +100,9 @@ pub(crate) fn rename( Ok(_) => { // check if destination contains a trailing slash if new_path.contains('/') { - return Err(Errno::Notdir); + return Err(Error::Notdir); } else { - return Err(Errno::Noent); + return Err(Error::Noent); } } Err(err) => { diff --git a/crates/wasi-common/src/sys/unix/clock.rs b/crates/wasi-common/src/sys/unix/clock.rs index d043283462..e24c725807 100644 --- a/crates/wasi-common/src/sys/unix/clock.rs +++ b/crates/wasi-common/src/sys/unix/clock.rs @@ -1,4 +1,5 @@ -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use yanix::clock::{clock_getres, clock_gettime, ClockId}; pub(crate) fn res_get(clock_id: types::Clockid) -> Result { @@ -11,11 +12,11 @@ pub(crate) fn res_get(clock_id: types::Clockid) -> Result { (timespec.tv_sec as types::Timestamp) .checked_mul(1_000_000_000) .and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as types::Timestamp)) - .map_or(Err(Errno::Overflow), |resolution| { + .map_or(Err(Error::Overflow), |resolution| { // a supported clock can never return zero; this case will probably never get hit, but // make sure we follow the spec if resolution == 0 { - Err(Errno::Inval) + Err(Error::Inval) } else { Ok(resolution) } @@ -31,5 +32,5 @@ pub(crate) fn time_get(clock_id: types::Clockid) -> Result { (timespec.tv_sec as types::Timestamp) .checked_mul(1_000_000_000) .and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as types::Timestamp)) - .map_or(Err(Errno::Overflow), Ok) + .map_or(Err(Error::Overflow), Ok) } diff --git a/crates/wasi-common/src/sys/unix/fd.rs b/crates/wasi-common/src/sys/unix/fd.rs index 83d717711c..0b97a3b737 100644 --- a/crates/wasi-common/src/sys/unix/fd.rs +++ b/crates/wasi-common/src/sys/unix/fd.rs @@ -1,7 +1,8 @@ use super::oshandle::RawOsHandle; use crate::sys::osdir::OsDir; use crate::sys::osfile::OsFile; -use crate::wasi::{self, types, Result}; +use crate::wasi::{self, types}; +use crate::Result; use std::convert::TryInto; use std::fs::File; use std::os::unix::prelude::AsRawFd; diff --git a/crates/wasi-common/src/sys/unix/linux/osdir.rs b/crates/wasi-common/src/sys/unix/linux/osdir.rs index c803178c6a..57350afbaa 100644 --- a/crates/wasi-common/src/sys/unix/linux/osdir.rs +++ b/crates/wasi-common/src/sys/unix/linux/osdir.rs @@ -1,6 +1,6 @@ use crate::handle::HandleRights; use crate::sys::sys_impl::oshandle::RawOsHandle; -use crate::wasi::Result; +use crate::Result; use std::cell::Cell; use std::io; use yanix::dir::Dir; diff --git a/crates/wasi-common/src/sys/unix/linux/path.rs b/crates/wasi-common/src/sys/unix/linux/path.rs index 9bbcb34514..304040a9d9 100644 --- a/crates/wasi-common/src/sys/unix/linux/path.rs +++ b/crates/wasi-common/src/sys/unix/linux/path.rs @@ -1,5 +1,5 @@ use crate::sys::osdir::OsDir; -use crate::wasi::Result; +use crate::Result; use std::os::unix::prelude::AsRawFd; pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> { diff --git a/crates/wasi-common/src/sys/unix/mod.rs b/crates/wasi-common/src/sys/unix/mod.rs index 7a28810509..da33d2dc18 100644 --- a/crates/wasi-common/src/sys/unix/mod.rs +++ b/crates/wasi-common/src/sys/unix/mod.rs @@ -28,7 +28,8 @@ cfg_if::cfg_if! { use crate::handle::HandleRights; use crate::sys::AsFile; -use crate::wasi::{types, Errno, Result, RightsExt}; +use crate::wasi::{types, RightsExt}; +use crate::{Error, Result}; use std::convert::{TryFrom, TryInto}; use std::fs::File; use std::io; @@ -141,98 +142,6 @@ impl From for ClockId { } } -impl From for Errno { - fn from(err: io::Error) -> Self { - match err.raw_os_error() { - Some(code) => match code { - libc::EPERM => Self::Perm, - libc::ENOENT => Self::Noent, - libc::ESRCH => Self::Srch, - libc::EINTR => Self::Intr, - libc::EIO => Self::Io, - libc::ENXIO => Self::Nxio, - libc::E2BIG => Self::TooBig, - libc::ENOEXEC => Self::Noexec, - libc::EBADF => Self::Badf, - libc::ECHILD => Self::Child, - libc::EAGAIN => Self::Again, - libc::ENOMEM => Self::Nomem, - libc::EACCES => Self::Acces, - libc::EFAULT => Self::Fault, - libc::EBUSY => Self::Busy, - libc::EEXIST => Self::Exist, - libc::EXDEV => Self::Xdev, - libc::ENODEV => Self::Nodev, - libc::ENOTDIR => Self::Notdir, - libc::EISDIR => Self::Isdir, - libc::EINVAL => Self::Inval, - libc::ENFILE => Self::Nfile, - libc::EMFILE => Self::Mfile, - libc::ENOTTY => Self::Notty, - libc::ETXTBSY => Self::Txtbsy, - libc::EFBIG => Self::Fbig, - libc::ENOSPC => Self::Nospc, - libc::ESPIPE => Self::Spipe, - libc::EROFS => Self::Rofs, - libc::EMLINK => Self::Mlink, - libc::EPIPE => Self::Pipe, - libc::EDOM => Self::Dom, - libc::ERANGE => Self::Range, - libc::EDEADLK => Self::Deadlk, - libc::ENAMETOOLONG => Self::Nametoolong, - libc::ENOLCK => Self::Nolck, - libc::ENOSYS => Self::Nosys, - libc::ENOTEMPTY => Self::Notempty, - libc::ELOOP => Self::Loop, - libc::ENOMSG => Self::Nomsg, - libc::EIDRM => Self::Idrm, - libc::ENOLINK => Self::Nolink, - libc::EPROTO => Self::Proto, - libc::EMULTIHOP => Self::Multihop, - libc::EBADMSG => Self::Badmsg, - libc::EOVERFLOW => Self::Overflow, - libc::EILSEQ => Self::Ilseq, - libc::ENOTSOCK => Self::Notsock, - libc::EDESTADDRREQ => Self::Destaddrreq, - libc::EMSGSIZE => Self::Msgsize, - libc::EPROTOTYPE => Self::Prototype, - libc::ENOPROTOOPT => Self::Noprotoopt, - libc::EPROTONOSUPPORT => Self::Protonosupport, - libc::EAFNOSUPPORT => Self::Afnosupport, - libc::EADDRINUSE => Self::Addrinuse, - libc::EADDRNOTAVAIL => Self::Addrnotavail, - libc::ENETDOWN => Self::Netdown, - libc::ENETUNREACH => Self::Netunreach, - libc::ENETRESET => Self::Netreset, - libc::ECONNABORTED => Self::Connaborted, - libc::ECONNRESET => Self::Connreset, - libc::ENOBUFS => Self::Nobufs, - libc::EISCONN => Self::Isconn, - libc::ENOTCONN => Self::Notconn, - libc::ETIMEDOUT => Self::Timedout, - libc::ECONNREFUSED => Self::Connrefused, - libc::EHOSTUNREACH => Self::Hostunreach, - libc::EALREADY => Self::Already, - libc::EINPROGRESS => Self::Inprogress, - libc::ESTALE => Self::Stale, - libc::EDQUOT => Self::Dquot, - libc::ECANCELED => Self::Canceled, - libc::EOWNERDEAD => Self::Ownerdead, - libc::ENOTRECOVERABLE => Self::Notrecoverable, - libc::ENOTSUP => Self::Notsup, - x => { - log::debug!("Unknown errno value: {}", x); - Self::Io - } - }, - None => { - log::debug!("Other I/O error: {}", err); - Self::Io - } - } - } -} - impl From for OFlags { fn from(fdflags: types::Fdflags) -> Self { let mut nix_flags = Self::empty(); @@ -297,13 +206,13 @@ impl From for OFlags { } impl TryFrom for types::Filestat { - type Error = Errno; + type Error = Error; fn try_from(filestat: libc::stat) -> Result { fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result { secs.checked_mul(1_000_000_000) .and_then(|sec_nsec| sec_nsec.checked_add(nsecs)) - .ok_or(Errno::Overflow) + .ok_or(Error::Overflow) } let filetype = yanix::file::FileType::from_stat_st_mode(filestat.st_mode); diff --git a/crates/wasi-common/src/sys/unix/path.rs b/crates/wasi-common/src/sys/unix/path.rs index fcaf98a96b..df052e8940 100644 --- a/crates/wasi-common/src/sys/unix/path.rs +++ b/crates/wasi-common/src/sys/unix/path.rs @@ -1,7 +1,8 @@ use crate::handle::{Handle, HandleRights}; use crate::sys::osdir::OsDir; use crate::sys::AsFile; -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use std::convert::{TryFrom, TryInto}; use std::ffi::OsStr; use std::fs::File; @@ -144,7 +145,7 @@ pub(crate) fn open( match unsafe { fstatat(dirfd.as_raw_fd(), path, AtFlags::SYMLINK_NOFOLLOW) } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket { - return Err(Errno::Notsup); + return Err(Error::Notsup); } } Err(err) => { @@ -160,7 +161,7 @@ pub(crate) fn open( match unsafe { fstatat(dirfd.as_raw_fd(), path, AtFlags::SYMLINK_NOFOLLOW) } { Ok(stat) => { if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink { - return Err(Errno::Loop); + return Err(Error::Loop); } } Err(err) => { @@ -171,7 +172,7 @@ pub(crate) fn open( // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on // a symlink. libc::EMLINK if !(nix_all_oflags & OFlags::NOFOLLOW).is_empty() => { - return Err(Errno::Loop); + return Err(Error::Loop); } _ => {} } @@ -235,7 +236,7 @@ pub(crate) fn filestat_set_times_at( let set_mtim_now = fst_flags.contains(&types::Fstflags::MTIM_NOW); if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { - return Err(Errno::Inval); + return Err(Error::Inval); } let atim = if set_atim { diff --git a/crates/wasi-common/src/sys/unix/poll.rs b/crates/wasi-common/src/sys/unix/poll.rs index b185bdb93c..55bdafac48 100644 --- a/crates/wasi-common/src/sys/unix/poll.rs +++ b/crates/wasi-common/src/sys/unix/poll.rs @@ -1,7 +1,8 @@ use crate::entry::EntryHandle; use crate::poll::{ClockEventData, FdEventData}; use crate::sys::AsFile; -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use std::io; use std::{convert::TryInto, os::unix::prelude::AsRawFd}; use yanix::file::fionread; @@ -64,7 +65,7 @@ pub(crate) fn oneoff( fn handle_timeout_event(timeout: ClockEventData, events: &mut Vec) { events.push(types::Event { userdata: timeout.userdata, - error: Errno::Success, + error: types::Errno::Success, type_: types::Eventtype::Clock, fd_readwrite: types::EventFdReadwrite { flags: types::Eventrwflags::empty(), @@ -110,7 +111,7 @@ fn handle_fd_event( let output_event = if revents.contains(PollFlags::POLLNVAL) { types::Event { userdata: fd_event.userdata, - error: Errno::Badf, + error: Error::Badf.into(), type_: fd_event.r#type, fd_readwrite: types::EventFdReadwrite { nbytes: 0, @@ -120,7 +121,7 @@ fn handle_fd_event( } else if revents.contains(PollFlags::POLLERR) { types::Event { userdata: fd_event.userdata, - error: Errno::Io, + error: Error::Io.into(), type_: fd_event.r#type, fd_readwrite: types::EventFdReadwrite { nbytes: 0, @@ -130,7 +131,7 @@ fn handle_fd_event( } else if revents.contains(PollFlags::POLLHUP) { types::Event { userdata: fd_event.userdata, - error: Errno::Success, + error: types::Errno::Success, type_: fd_event.r#type, fd_readwrite: types::EventFdReadwrite { nbytes: 0, @@ -140,7 +141,7 @@ fn handle_fd_event( } else if revents.contains(PollFlags::POLLIN) | revents.contains(PollFlags::POLLOUT) { types::Event { userdata: fd_event.userdata, - error: Errno::Success, + error: types::Errno::Success, type_: fd_event.r#type, fd_readwrite: types::EventFdReadwrite { nbytes: nbytes.try_into()?, diff --git a/crates/wasi-common/src/sys/windows/clock.rs b/crates/wasi-common/src/sys/windows/clock.rs index e72820ad6d..28025247b0 100644 --- a/crates/wasi-common/src/sys/windows/clock.rs +++ b/crates/wasi-common/src/sys/windows/clock.rs @@ -1,4 +1,5 @@ -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use cpu_time::{ProcessTime, ThreadTime}; use lazy_static::lazy_static; use std::convert::TryInto; @@ -83,7 +84,7 @@ fn get_monotonic_time() -> Duration { fn get_realtime_time() -> Result { SystemTime::now() .duration_since(UNIX_EPOCH) - .map_err(|_| Errno::Fault) + .map_err(|_| Error::Fault) } fn get_proc_cputime() -> Result { diff --git a/crates/wasi-common/src/sys/windows/fd.rs b/crates/wasi-common/src/sys/windows/fd.rs index 78604a4719..dead303fb9 100644 --- a/crates/wasi-common/src/sys/windows/fd.rs +++ b/crates/wasi-common/src/sys/windows/fd.rs @@ -4,7 +4,8 @@ use crate::path; use crate::sys::osdir::OsDir; use crate::sys::osfile::OsFile; use crate::sys::AsFile; -use crate::wasi::{types, Result}; +use crate::wasi::types; +use crate::Result; use log::trace; use std::convert::TryInto; use std::fs::{File, OpenOptions}; diff --git a/crates/wasi-common/src/sys/windows/mod.rs b/crates/wasi-common/src/sys/windows/mod.rs index 109385f15a..9d0e7ae9e3 100644 --- a/crates/wasi-common/src/sys/windows/mod.rs +++ b/crates/wasi-common/src/sys/windows/mod.rs @@ -10,7 +10,8 @@ pub(crate) mod stdio; use crate::handle::HandleRights; use crate::sys::AsFile; -use crate::wasi::{types, Errno, Result, RightsExt}; +use crate::wasi::{types, RightsExt}; +use crate::{Error, Result}; use std::convert::{TryFrom, TryInto}; use std::fs::File; use std::mem::ManuallyDrop; @@ -18,7 +19,6 @@ use std::os::windows::prelude::{AsRawHandle, FromRawHandle}; use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; use std::{io, string}; -use winapi::shared::winerror; use winx::file::{CreationDisposition, Flags}; impl AsFile for T { @@ -106,47 +106,7 @@ pub(crate) fn file_serial_no(file: &File) -> io::Result { Ok(no) } -impl From for Errno { - fn from(err: io::Error) -> Self { - match err.raw_os_error() { - Some(code) => match code as u32 { - winerror::ERROR_SUCCESS => Self::Success, - winerror::ERROR_BAD_ENVIRONMENT => Self::TooBig, - winerror::ERROR_FILE_NOT_FOUND => Self::Noent, - winerror::ERROR_PATH_NOT_FOUND => Self::Noent, - winerror::ERROR_TOO_MANY_OPEN_FILES => Self::Nfile, - winerror::ERROR_ACCESS_DENIED => Self::Acces, - winerror::ERROR_SHARING_VIOLATION => Self::Acces, - winerror::ERROR_PRIVILEGE_NOT_HELD => Self::Notcapable, - winerror::ERROR_INVALID_HANDLE => Self::Badf, - winerror::ERROR_INVALID_NAME => Self::Noent, - winerror::ERROR_NOT_ENOUGH_MEMORY => Self::Nomem, - winerror::ERROR_OUTOFMEMORY => Self::Nomem, - winerror::ERROR_DIR_NOT_EMPTY => Self::Notempty, - winerror::ERROR_NOT_READY => Self::Busy, - winerror::ERROR_BUSY => Self::Busy, - winerror::ERROR_NOT_SUPPORTED => Self::Notsup, - winerror::ERROR_FILE_EXISTS => Self::Exist, - winerror::ERROR_BROKEN_PIPE => Self::Pipe, - winerror::ERROR_BUFFER_OVERFLOW => Self::Nametoolong, - winerror::ERROR_NOT_A_REPARSE_POINT => Self::Inval, - winerror::ERROR_NEGATIVE_SEEK => Self::Inval, - winerror::ERROR_DIRECTORY => Self::Notdir, - winerror::ERROR_ALREADY_EXISTS => Self::Exist, - x => { - log::debug!("winerror: unknown error value: {}", x); - Self::Io - } - }, - None => { - log::debug!("Other I/O error: {}", err); - Self::Io - } - } - } -} - -impl From for Errno { +impl From for Error { fn from(_err: string::FromUtf16Error) -> Self { Self::Ilseq } @@ -166,14 +126,14 @@ fn change_time(file: &File) -> io::Result { fn systemtime_to_timestamp(st: SystemTime) -> Result { st.duration_since(UNIX_EPOCH) - .map_err(|_| Errno::Inval)? // date earlier than UNIX_EPOCH + .map_err(|_| Error::Inval)? // date earlier than UNIX_EPOCH .as_nanos() .try_into() .map_err(Into::into) // u128 doesn't fit into u64 } impl TryFrom<&File> for types::Filestat { - type Error = Errno; + type Error = Error; fn try_from(file: &File) -> Result { let metadata = file.metadata()?; diff --git a/crates/wasi-common/src/sys/windows/path.rs b/crates/wasi-common/src/sys/windows/path.rs index d2a2d17276..7d0251ec13 100644 --- a/crates/wasi-common/src/sys/windows/path.rs +++ b/crates/wasi-common/src/sys/windows/path.rs @@ -1,7 +1,8 @@ use crate::handle::{Handle, HandleRights}; use crate::sys::osdir::OsDir; use crate::sys::{fd, AsFile}; -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use std::convert::TryFrom; use std::ffi::{OsStr, OsString}; use std::fs::{self, Metadata, OpenOptions}; @@ -35,7 +36,7 @@ fn concatenate>(file: &OsDir, path: P) -> Result { // WASI is not able to deal with absolute paths // so error out if absolute if path.as_ref().is_absolute() { - return Err(Errno::Notcapable); + return Err(Error::Notcapable); } let dir_path = get_file_path(&*file.as_file()?)?; @@ -131,8 +132,8 @@ pub(crate) fn readlinkat(dirfd: &OsDir, 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(|_| Errno::Notcapable)?; - let target_path = target_path.to_str().ok_or(Errno::Ilseq)?; + .map_err(|_| Error::Notcapable)?; + let target_path = target_path.to_str().ok_or(Error::Ilseq)?; return Ok(target_path.to_owned()); } Err(e) => e, @@ -144,7 +145,7 @@ pub(crate) fn readlinkat(dirfd: &OsDir, 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(Errno::Notdir); + return Err(Error::Notdir); } } } @@ -175,7 +176,7 @@ pub(crate) fn link( // fs::canonicalize under Windows will return: // * ERROR_FILE_NOT_FOUND, if it encounters a dangling symlink // * ERROR_CANT_RESOLVE_FILENAME, if it encounters a symlink loop - Some(code) if code as u32 == winerror::ERROR_CANT_RESOLVE_FILENAME => Errno::Loop, + Some(code) if code as u32 == winerror::ERROR_CANT_RESOLVE_FILENAME => Error::Loop, _ => e.into(), })?; } @@ -190,7 +191,7 @@ pub(crate) fn link( // implementations of link return `EPERM`, but `ERROR_ACCESS_DENIED` is converted // to `EACCES`. We detect and correct this case here. if fs::metadata(&old_path).map(|m| m.is_dir()).unwrap_or(false) { - return Err(Errno::Perm); + return Err(Error::Perm); } } } @@ -214,7 +215,7 @@ pub(crate) fn open( // This is because truncation requires `GENERIC_WRITE` access, which will override the removal // of the `FILE_WRITE_DATA` permission. if fdflags.contains(&types::Fdflags::APPEND) { - return Err(Errno::Notsup); + return Err(Error::Notsup); } } @@ -239,11 +240,11 @@ pub(crate) fn open( Ok(file_type) => { // check if we are trying to open a symlink if file_type.is_symlink() { - return Err(Errno::Loop); + return Err(Error::Loop); } // check if we are trying to open a file as a dir if file_type.is_file() && oflags.contains(&types::Oflags::DIRECTORY) { - return Err(Errno::Notdir); + return Err(Error::Notdir); } } Err(err) => match err.raw_os_error() { @@ -257,14 +258,14 @@ pub(crate) fn open( winerror::ERROR_INVALID_NAME => { // TODO rethink this. For now, migrate how we handled // it in `path::openat` on Windows. - return Err(Errno::Notdir); + return Err(Error::Notdir); } _ => return Err(err.into()), }; } None => { log::debug!("Inconvertible OS error: {}", err); - return Err(Errno::Io); + return Err(Error::Io); } }, } @@ -299,8 +300,8 @@ pub(crate) fn readlink(dirfd: &OsDir, path: &str, buf: &mut [u8]) -> Result 0 { let mut chars = target_path.chars(); @@ -338,12 +339,12 @@ pub(crate) fn rename( // // [std::fs::rename]: https://doc.rust-lang.org/std/fs/fn.rename.html if old_path.is_dir() && new_path.is_file() { - return Err(Errno::Notdir); + return Err(Error::Notdir); } // 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() && new_path_.ends_with('/') { - return Err(Errno::Notdir); + return Err(Error::Notdir); } // TODO handle symlinks @@ -359,7 +360,7 @@ pub(crate) fn rename( // So most likely dealing with new_path == dir. // Eliminate case old_path == file first. if old_path.is_file() { - return Err(Errno::Isdir); + return Err(Error::Isdir); } else { // Ok, let's try removing an empty dir at new_path if it exists // and is a nonempty dir. @@ -375,7 +376,7 @@ pub(crate) fn rename( strip_trailing_slashes_and_concatenate(old_dirfd, old_path_)? { if path.is_file() { - return Err(Errno::Notdir); + return Err(Error::Notdir); } } } @@ -386,7 +387,7 @@ pub(crate) fn rename( } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Errno::Io) + Err(Error::Io) } } } @@ -432,7 +433,7 @@ pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path_: &str) -> Res strip_trailing_slashes_and_concatenate(new_dirfd, new_path_)? { if path.exists() { - return Err(Errno::Exist); + return Err(Error::Exist); } } } @@ -443,7 +444,7 @@ pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path_: &str) -> Res } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Errno::Io) + Err(Error::Io) } } } @@ -478,15 +479,15 @@ pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> { } None => { log::debug!("Inconvertible OS error: {}", err); - Err(Errno::Io) + Err(Error::Io) } } } else if file_type.is_dir() { - Err(Errno::Isdir) + Err(Error::Isdir) } else if file_type.is_file() { fs::remove_file(path).map_err(Into::into) } else { - Err(Errno::Inval) + Err(Error::Inval) } } diff --git a/crates/wasi-common/src/sys/windows/poll.rs b/crates/wasi-common/src/sys/windows/poll.rs index d49524a5d5..73d6b74632 100644 --- a/crates/wasi-common/src/sys/windows/poll.rs +++ b/crates/wasi-common/src/sys/windows/poll.rs @@ -5,7 +5,8 @@ use crate::sys::osfile::OsFile; use crate::sys::osother::OsOther; use crate::sys::stdio::{Stderr, Stdin, Stdout}; use crate::sys::AsFile; -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use lazy_static::lazy_static; use log::{debug, error, trace, warn}; use std::convert::TryInto; @@ -23,7 +24,7 @@ enum PollState { Ready, NotReady, // it's not ready, but we didn't wait TimedOut, // it's not ready and a timeout has occurred - Error(Errno), + Error(Error), } enum WaitMode { @@ -79,7 +80,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(Errno::from(e)), + Err(e) => PollState::Error(Error::from(e)), }; // Notify the requestor about data in stdin. They may have already timed out, @@ -103,7 +104,7 @@ lazy_static! { fn make_rw_event(event: &FdEventData, nbytes: Result) -> types::Event { let (nbytes, error) = match nbytes { - Ok(nbytes) => (nbytes, Errno::Success), + Ok(nbytes) => (nbytes, Error::Success), Err(e) => (u64::default(), e), }; types::Event { @@ -121,7 +122,7 @@ fn make_timeout_event(timeout: &ClockEventData) -> types::Event { types::Event { userdata: timeout.userdata, type_: types::Eventtype::Clock, - error: Errno::Success, + error: Error::Success, fd_readwrite: types::EventFdReadwrite { nbytes: 0, flags: types::Eventrwflags::empty(), @@ -173,7 +174,7 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec) { out_events.push(new_event); } -fn handle_error_event(event: FdEventData, error: Errno, out_events: &mut Vec) { +fn handle_error_event(event: FdEventData, error: Error, out_events: &mut Vec) { let new_event = make_rw_event(&event, Err(error)); out_events.push(new_event); } @@ -238,11 +239,11 @@ pub(crate) fn oneoff( "poll_oneoff: unsupported file type: {}", other.get_file_type() ); - handle_error_event(event, Errno::Notsup, events); + handle_error_event(event, Error::Notsup, events); } } else { log::error!("can poll FdEvent for OS resources only"); - return Err(Errno::Badf); + return Err(Error::Badf); } } @@ -306,7 +307,7 @@ pub(crate) fn oneoff( } None => { error!("Polling only pipes with no timeout not supported on Windows."); - return Err(Errno::Notsup); + return Err(Error::Notsup); } } } diff --git a/crates/wasi-common/src/virtfs.rs b/crates/wasi-common/src/virtfs.rs index 0f20ddb509..726dad2b04 100644 --- a/crates/wasi-common/src/virtfs.rs +++ b/crates/wasi-common/src/virtfs.rs @@ -1,5 +1,6 @@ use crate::handle::{Handle, HandleRights}; -use crate::wasi::{self, types, Errno, Result, RightsExt}; +use crate::wasi::{self, types, RightsExt}; +use crate::{Error, Result}; use log::trace; use std::any::Any; use std::cell::{Cell, RefCell}; @@ -70,7 +71,7 @@ impl FileContents for VecFileContents { } fn resize(&mut self, new_size: types::Filesize) -> Result<()> { - let new_size: usize = new_size.try_into().map_err(|_| Errno::Inval)?; + let new_size: usize = new_size.try_into().map_err(|_| Error::Inval)?; self.content.resize(new_size, 0); Ok(()) } @@ -78,7 +79,7 @@ impl FileContents for VecFileContents { fn preadv(&self, iovs: &mut [io::IoSliceMut], offset: types::Filesize) -> Result { let mut read_total = 0usize; for iov in iovs.iter_mut() { - let skip: u64 = read_total.try_into().map_err(|_| Errno::Inval)?; + let skip: u64 = read_total.try_into().map_err(|_| Error::Inval)?; let read = self.pread(iov, offset + skip)?; read_total = read_total.checked_add(read).expect("FileContents::preadv must not be called when reads could total to more bytes than the return value can hold"); } @@ -88,7 +89,7 @@ impl FileContents for VecFileContents { fn pwritev(&mut self, iovs: &[io::IoSlice], offset: types::Filesize) -> Result { let mut write_total = 0usize; for iov in iovs.iter() { - let skip: u64 = write_total.try_into().map_err(|_| Errno::Inval)?; + let skip: u64 = write_total.try_into().map_err(|_| Error::Inval)?; let written = self.pwrite(iov, offset + skip)?; write_total = write_total.checked_add(written).expect("FileContents::pwritev must not be called when writes could total to more bytes than the return value can hold"); } @@ -97,7 +98,7 @@ impl FileContents for VecFileContents { fn pread(&self, buf: &mut [u8], offset: types::Filesize) -> Result { trace!(" | pread(buf.len={}, offset={})", buf.len(), offset); - let offset: usize = offset.try_into().map_err(|_| Errno::Inval)?; + let offset: usize = offset.try_into().map_err(|_| Error::Inval)?; let data_remaining = self.content.len().saturating_sub(offset); @@ -111,9 +112,9 @@ impl FileContents for VecFileContents { } fn pwrite(&mut self, buf: &[u8], offset: types::Filesize) -> Result { - let offset: usize = offset.try_into().map_err(|_| Errno::Inval)?; + let offset: usize = offset.try_into().map_err(|_| Error::Inval)?; - let write_end = offset.checked_add(buf.len()).ok_or(Errno::Fbig)?; + let write_end = offset.checked_add(buf.len()).ok_or(Error::Fbig)?; if write_end > self.content.len() { self.content.resize(write_end, 0); @@ -208,11 +209,11 @@ impl Handle for InMemoryFile { Ok(()) } fn allocate(&self, offset: types::Filesize, len: types::Filesize) -> Result<()> { - let new_limit = offset.checked_add(len).ok_or(Errno::Fbig)?; + let new_limit = offset.checked_add(len).ok_or(Error::Fbig)?; let mut data = self.data.borrow_mut(); if new_limit > data.max_size() { - return Err(Errno::Fbig); + return Err(Error::Fbig); } if new_limit > data.size() { @@ -244,7 +245,7 @@ impl Handle for InMemoryFile { fn filestat_set_size(&self, st_size: types::Filesize) -> Result<()> { let mut data = self.data.borrow_mut(); if st_size > data.max_size() { - return Err(Errno::Fbig); + return Err(Error::Fbig); } data.resize(st_size) } @@ -258,8 +259,8 @@ impl Handle for InMemoryFile { trace!("read_vectored(iovs={:?})", iovs); trace!(" | *read_start={:?}", self.cursor.get()); let read = self.data.borrow_mut().preadv(iovs, self.cursor.get())?; - let offset: u64 = read.try_into().map_err(|_| Errno::Inval)?; - let update = self.cursor.get().checked_add(offset).ok_or(Errno::Inval)?; + let offset: u64 = read.try_into().map_err(|_| Error::Inval)?; + let update = self.cursor.get().checked_add(offset).ok_or(Error::Inval)?; self.cursor.set(update); Ok(read) } @@ -271,23 +272,23 @@ impl Handle for InMemoryFile { self.cursor .get() .checked_sub(offset.wrapping_neg() as u64) - .ok_or(Errno::Inval)? + .ok_or(Error::Inval)? } else { self.cursor .get() .checked_add(offset as u64) - .ok_or(Errno::Inval)? + .ok_or(Error::Inval)? }; self.cursor.set(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(|_| Errno::Inval)?; + let offset: u64 = offset.try_into().map_err(|_| Error::Inval)?; self.cursor.set(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(|_| Errno::Inval)?; + let offset: u64 = offset.try_into().map_err(|_| Error::Inval)?; self.cursor.set(std::cmp::min(content_len, offset)); } } @@ -322,10 +323,10 @@ impl Handle for InMemoryFile { if let Some(end) = write_start.checked_add(max_size as types::Filesize) { if end > data.max_size() { - return Err(Errno::Fbig); + return Err(Error::Fbig); } } else { - return Err(Errno::Fbig); + return Err(Error::Fbig); } trace!(" | *write_start={:?}", write_start); @@ -342,7 +343,7 @@ impl Handle for InMemoryFile { } // PathOps fn create_directory(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn openat( &self, @@ -367,7 +368,7 @@ impl Handle for InMemoryFile { path ); log::trace!(" return Notdir"); - return Err(Errno::Notdir); + return Err(Error::Notdir); } if path == "." { @@ -378,7 +379,7 @@ impl Handle for InMemoryFile { None => self.try_clone().map_err(Into::into), } } else { - Err(Errno::Acces) + Err(Error::Acces) } } fn link( @@ -388,25 +389,25 @@ impl Handle for InMemoryFile { _new_path: &str, _follow: bool, ) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn readlink(&self, _path: &str, _buf: &mut [u8]) -> Result { - Err(Errno::Notdir) + Err(Error::Notdir) } fn readlinkat(&self, _path: &str) -> Result { - Err(Errno::Notdir) + Err(Error::Notdir) } fn rename(&self, _old_path: &str, _new_handle: Box, _new_path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn remove_directory(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn symlink(&self, _old_path: &str, _new_path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn unlink_file(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } } @@ -599,7 +600,7 @@ impl Handle for VirtualDir { fn create_directory(&self, path: &str) -> Result<()> { let mut entries = self.entries.borrow_mut(); match entries.entry(PathBuf::from(path)) { - Entry::Occupied(_) => Err(Errno::Exist), + Entry::Occupied(_) => Err(Error::Exist), Entry::Vacant(v) => { if self.writable { let new_dir = Box::new(Self::new(true)); @@ -607,7 +608,7 @@ impl Handle for VirtualDir { v.insert(new_dir); Ok(()) } else { - Err(Errno::Acces) + Err(Error::Acces) } } } @@ -674,7 +675,7 @@ impl Handle 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::new(path).file_name().ok_or(Errno::Inval)?; + let file_name = Path::new(path).file_name().ok_or(Error::Inval)?; let mut entries = self.entries.borrow_mut(); let entry_count = entries.len(); match entries.entry(Path::new(file_name).to_path_buf()) { @@ -683,7 +684,7 @@ impl Handle 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 Exist"); - return Err(Errno::Exist); + return Err(Error::Exist); } if oflags.contains(&types::Oflags::DIRECTORY) @@ -694,7 +695,7 @@ impl Handle for VirtualDir { file_name ); log::trace!(" return Notdir"); - return Err(Errno::Notdir); + return Err(Error::Notdir); } e.get().try_clone().map_err(Into::into) @@ -706,7 +707,7 @@ impl Handle 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(Errno::Nospc); + return Err(Error::Nospc); } log::trace!("VirtualDir::openat creating an InMemoryFile named {}", path); @@ -716,14 +717,14 @@ impl Handle for VirtualDir { file.set_parent(Some(self.try_clone().expect("can clone self"))); v.insert(file).try_clone().map_err(Into::into) } else { - Err(Errno::Acces) + Err(Error::Acces) } } } } fn readlinkat(&self, _path: &str) -> Result { // Files are not symbolic links or directories, faithfully report Notdir. - Err(Errno::Notdir) + Err(Error::Notdir) } fn remove_directory(&self, path: &str) -> Result<()> { let trimmed_path = path.trim_end_matches('/'); @@ -732,13 +733,13 @@ impl Handle for VirtualDir { Entry::Occupied(e) => { // first, does this name a directory? if e.get().get_file_type() != types::Filetype::Directory { - return Err(Errno::Notdir); + return Err(Error::Notdir); } // Okay, but is the directory empty? let iter = e.get().readdir(wasi::DIRCOOKIE_START)?; if iter.skip(RESERVED_ENTRY_COUNT as usize).next().is_some() { - return Err(Errno::Notempty); + return Err(Error::Notempty); } // Alright, it's an empty directory. We can remove it. @@ -761,7 +762,7 @@ impl Handle for VirtualDir { "VirtualDir::remove_directory failed to remove {}, no such entry", trimmed_path ); - Err(Errno::Noent) + Err(Error::Noent) } } } @@ -772,7 +773,7 @@ impl Handle for VirtualDir { // fail with Isdir, 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(Errno::Isdir); + return Err(Error::Isdir); } let mut entries = self.entries.borrow_mut(); @@ -780,7 +781,7 @@ impl Handle for VirtualDir { Entry::Occupied(e) => { // Directories must be removed through `remove_directory`, not `unlink_file`. if e.get().get_file_type() == types::Filetype::Directory { - return Err(Errno::Isdir); + return Err(Error::Isdir); } let removed = e.remove_entry(); @@ -802,7 +803,7 @@ impl Handle for VirtualDir { "VirtualDir::unlink_file failed to remove {}, no such entry", trimmed_path ); - Err(Errno::Noent) + Err(Error::Noent) } } } diff --git a/crates/wasi-common/src/virtfs/pipe.rs b/crates/wasi-common/src/virtfs/pipe.rs index ef253b72ae..87551e37f5 100644 --- a/crates/wasi-common/src/virtfs/pipe.rs +++ b/crates/wasi-common/src/virtfs/pipe.rs @@ -10,7 +10,8 @@ //! Note that `poll_oneoff` is not supported for these types, so they do not match the behavior of //! real pipes exactly. use crate::handle::{Handle, HandleRights}; -use crate::wasi::{types, Errno, Result}; +use crate::wasi::types; +use crate::{Error, Result}; use std::any::Any; use std::io::{self, Read, Write}; use std::sync::{Arc, RwLock}; @@ -132,11 +133,11 @@ impl Handle for ReadPipe { _offset: types::Filesize, _len: types::Filesize, ) -> Result<()> { - Err(Errno::Spipe) + Err(Error::Spipe) } fn allocate(&self, _offset: types::Filesize, _len: types::Filesize) -> Result<()> { - Err(Errno::Spipe) + Err(Error::Spipe) } fn fdstat_set_flags(&self, _fdflags: types::Fdflags) -> Result<()> { @@ -159,18 +160,18 @@ impl Handle for ReadPipe { } fn filestat_set_size(&self, _st_size: types::Filesize) -> Result<()> { - Err(Errno::Spipe) + Err(Error::Spipe) } fn preadv(&self, buf: &mut [io::IoSliceMut], offset: types::Filesize) -> Result { if offset != 0 { - return Err(Errno::Spipe); + return Err(Error::Spipe); } Ok(self.reader.write().unwrap().read_vectored(buf)?) } fn seek(&self, _offset: io::SeekFrom) -> Result { - Err(Errno::Spipe) + Err(Error::Spipe) } fn read_vectored(&self, iovs: &mut [io::IoSliceMut]) -> Result { @@ -178,7 +179,7 @@ impl Handle for ReadPipe { } fn create_directory(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn openat( @@ -189,7 +190,7 @@ impl Handle for ReadPipe { _oflags: types::Oflags, _fd_flags: types::Fdflags, ) -> Result> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn link( @@ -199,31 +200,31 @@ impl Handle for ReadPipe { _new_path: &str, _follow: bool, ) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn readlink(&self, _path: &str, _buf: &mut [u8]) -> Result { - Err(Errno::Notdir) + Err(Error::Notdir) } fn readlinkat(&self, _path: &str) -> Result { - Err(Errno::Notdir) + Err(Error::Notdir) } fn rename(&self, _old_path: &str, _new_handle: Box, _new_path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn remove_directory(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn symlink(&self, _old_path: &str, _new_path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn unlink_file(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } } @@ -317,11 +318,11 @@ impl Handle for WritePipe { _offset: types::Filesize, _len: types::Filesize, ) -> Result<()> { - Err(Errno::Spipe) + Err(Error::Spipe) } fn allocate(&self, _offset: types::Filesize, _len: types::Filesize) -> Result<()> { - Err(Errno::Spipe) + Err(Error::Spipe) } fn fdstat_set_flags(&self, _fdflags: types::Fdflags) -> Result<()> { @@ -344,18 +345,18 @@ impl Handle for WritePipe { } fn filestat_set_size(&self, _st_size: types::Filesize) -> Result<()> { - Err(Errno::Spipe) + Err(Error::Spipe) } fn pwritev(&self, buf: &[io::IoSlice], offset: types::Filesize) -> Result { if offset != 0 { - return Err(Errno::Spipe); + return Err(Error::Spipe); } Ok(self.writer.write().unwrap().write_vectored(buf)?) } fn seek(&self, _offset: io::SeekFrom) -> Result { - Err(Errno::Spipe) + Err(Error::Spipe) } fn write_vectored(&self, iovs: &[io::IoSlice]) -> Result { @@ -363,7 +364,7 @@ impl Handle for WritePipe { } fn create_directory(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn openat( @@ -374,7 +375,7 @@ impl Handle for WritePipe { _oflags: types::Oflags, _fd_flags: types::Fdflags, ) -> Result> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn link( @@ -384,30 +385,30 @@ impl Handle for WritePipe { _new_path: &str, _follow: bool, ) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn readlink(&self, _path: &str, _buf: &mut [u8]) -> Result { - Err(Errno::Notdir) + Err(Error::Notdir) } fn readlinkat(&self, _path: &str) -> Result { - Err(Errno::Notdir) + Err(Error::Notdir) } fn rename(&self, _old_path: &str, _new_handle: Box, _new_path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn remove_directory(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn symlink(&self, _old_path: &str, _new_path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } fn unlink_file(&self, _path: &str) -> Result<()> { - Err(Errno::Notdir) + Err(Error::Notdir) } } diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index c632461170..045a118606 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/crates/wasi-common/src/wasi.rs @@ -1,16 +1,14 @@ -//! Types and constants shared between 32-bit and 64-bit wasi. Types involving -//! pointer or `usize`-sized data are excluded here, so this file only contains -//! fixed-size types, so it's host/target independent. -use crate::WasiCtx; +use crate::{Error, Result, WasiCtx}; +use cfg_if::cfg_if; use tracing::debug; wiggle::from_witx!({ witx: ["WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx"], ctx: WasiCtx, + errors: { errno => Error }, }); -pub use types::Errno; -pub type Result = std::result::Result; +use types::Errno; impl wiggle::GuestErrorType for Errno { fn success() -> Self { @@ -25,6 +23,47 @@ impl types::GuestErrorConversion for WasiCtx { } } +impl types::UserErrorConversion for WasiCtx { + fn errno_from_error(&self, e: Error) -> Errno { + debug!("Error: {:?}", e); + e.into() + } +} + +impl From for Errno { + fn from(e: Error) -> Errno { + match e { + Error::Guest(e) => e.into(), + Error::TryFromInt(_) => Errno::Overflow, + Error::Utf8(_) => Errno::Ilseq, + Error::IoError(e) => e.into(), + Error::TooBig => Errno::TooBig, + Error::Acces => Errno::Acces, + Error::Badf => Errno::Badf, + Error::Exist => Errno::Exist, + Error::Fault => Errno::Fault, + Error::Fbig => Errno::Fbig, + Error::Ilseq => Errno::Ilseq, + Error::Inval => Errno::Inval, + Error::Io => Errno::Io, + Error::Isdir => Errno::Isdir, + Error::Loop => Errno::Loop, + Error::Mfile => Errno::Mfile, + Error::Mlink => Errno::Mlink, + Error::Nametoolong => Errno::Nametoolong, + Error::Noent => Errno::Noent, + Error::Nospc => Errno::Nospc, + Error::Notdir => Errno::Notdir, + Error::Notempty => Errno::Notempty, + Error::Notsup => Errno::Notsup, + Error::Overflow => Errno::Overflow, + Error::Perm => Errno::Perm, + Error::Spipe => Errno::Spipe, + Error::Notcapable => Errno::Notcapable, + } + } +} + impl From for Errno { fn from(err: wiggle::GuestError) -> Self { use wiggle::GuestError::*; @@ -45,24 +84,6 @@ impl From for Errno { } } -impl From for Errno { - fn from(_err: std::convert::Infallible) -> Self { - unreachable!() - } -} - -impl From for Errno { - fn from(_err: std::num::TryFromIntError) -> Self { - Self::Overflow - } -} - -impl From for Errno { - fn from(_err: std::str::Utf8Error) -> Self { - Self::Ilseq - } -} - impl From for types::Filetype { fn from(ftype: std::fs::FileType) -> Self { if ftype.is_file() { @@ -216,3 +237,144 @@ impl crate::fdpool::Fd for types::Fd { Self::from(raw_fd) } } + +// Turning an io::Error into an Errno is different on windows. +cfg_if! { + if #[cfg(windows)] { +use winapi::shared::winerror; +use std::io; +impl From for Errno { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(code) => match code as u32 { + winerror::ERROR_SUCCESS => Self::Success, + winerror::ERROR_BAD_ENVIRONMENT => Self::TooBig, + winerror::ERROR_FILE_NOT_FOUND => Self::Noent, + winerror::ERROR_PATH_NOT_FOUND => Self::Noent, + winerror::ERROR_TOO_MANY_OPEN_FILES => Self::Nfile, + winerror::ERROR_ACCESS_DENIED => Self::Acces, + winerror::ERROR_SHARING_VIOLATION => Self::Acces, + winerror::ERROR_PRIVILEGE_NOT_HELD => Self::Notcapable, + winerror::ERROR_INVALID_HANDLE => Self::Badf, + winerror::ERROR_INVALID_NAME => Self::Noent, + winerror::ERROR_NOT_ENOUGH_MEMORY => Self::Nomem, + winerror::ERROR_OUTOFMEMORY => Self::Nomem, + winerror::ERROR_DIR_NOT_EMPTY => Self::Notempty, + winerror::ERROR_NOT_READY => Self::Busy, + winerror::ERROR_BUSY => Self::Busy, + winerror::ERROR_NOT_SUPPORTED => Self::Notsup, + winerror::ERROR_FILE_EXISTS => Self::Exist, + winerror::ERROR_BROKEN_PIPE => Self::Pipe, + winerror::ERROR_BUFFER_OVERFLOW => Self::Nametoolong, + winerror::ERROR_NOT_A_REPARSE_POINT => Self::Inval, + winerror::ERROR_NEGATIVE_SEEK => Self::Inval, + winerror::ERROR_DIRECTORY => Self::Notdir, + winerror::ERROR_ALREADY_EXISTS => Self::Exist, + x => { + log::debug!("winerror: unknown error value: {}", x); + Self::Io + } + }, + None => { + log::debug!("Other I/O error: {}", err); + Self::Io + } + } + } +} + + } else { +use std::io; +impl From for Errno { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(code) => match code { + libc::EPERM => Self::Perm, + libc::ENOENT => Self::Noent, + libc::ESRCH => Self::Srch, + libc::EINTR => Self::Intr, + libc::EIO => Self::Io, + libc::ENXIO => Self::Nxio, + libc::E2BIG => Self::TooBig, + libc::ENOEXEC => Self::Noexec, + libc::EBADF => Self::Badf, + libc::ECHILD => Self::Child, + libc::EAGAIN => Self::Again, + libc::ENOMEM => Self::Nomem, + libc::EACCES => Self::Acces, + libc::EFAULT => Self::Fault, + libc::EBUSY => Self::Busy, + libc::EEXIST => Self::Exist, + libc::EXDEV => Self::Xdev, + libc::ENODEV => Self::Nodev, + libc::ENOTDIR => Self::Notdir, + libc::EISDIR => Self::Isdir, + libc::EINVAL => Self::Inval, + libc::ENFILE => Self::Nfile, + libc::EMFILE => Self::Mfile, + libc::ENOTTY => Self::Notty, + libc::ETXTBSY => Self::Txtbsy, + libc::EFBIG => Self::Fbig, + libc::ENOSPC => Self::Nospc, + libc::ESPIPE => Self::Spipe, + libc::EROFS => Self::Rofs, + libc::EMLINK => Self::Mlink, + libc::EPIPE => Self::Pipe, + libc::EDOM => Self::Dom, + libc::ERANGE => Self::Range, + libc::EDEADLK => Self::Deadlk, + libc::ENAMETOOLONG => Self::Nametoolong, + libc::ENOLCK => Self::Nolck, + libc::ENOSYS => Self::Nosys, + libc::ENOTEMPTY => Self::Notempty, + libc::ELOOP => Self::Loop, + libc::ENOMSG => Self::Nomsg, + libc::EIDRM => Self::Idrm, + libc::ENOLINK => Self::Nolink, + libc::EPROTO => Self::Proto, + libc::EMULTIHOP => Self::Multihop, + libc::EBADMSG => Self::Badmsg, + libc::EOVERFLOW => Self::Overflow, + libc::EILSEQ => Self::Ilseq, + libc::ENOTSOCK => Self::Notsock, + libc::EDESTADDRREQ => Self::Destaddrreq, + libc::EMSGSIZE => Self::Msgsize, + libc::EPROTOTYPE => Self::Prototype, + libc::ENOPROTOOPT => Self::Noprotoopt, + libc::EPROTONOSUPPORT => Self::Protonosupport, + libc::EAFNOSUPPORT => Self::Afnosupport, + libc::EADDRINUSE => Self::Addrinuse, + libc::EADDRNOTAVAIL => Self::Addrnotavail, + libc::ENETDOWN => Self::Netdown, + libc::ENETUNREACH => Self::Netunreach, + libc::ENETRESET => Self::Netreset, + libc::ECONNABORTED => Self::Connaborted, + libc::ECONNRESET => Self::Connreset, + libc::ENOBUFS => Self::Nobufs, + libc::EISCONN => Self::Isconn, + libc::ENOTCONN => Self::Notconn, + libc::ETIMEDOUT => Self::Timedout, + libc::ECONNREFUSED => Self::Connrefused, + libc::EHOSTUNREACH => Self::Hostunreach, + libc::EALREADY => Self::Already, + libc::EINPROGRESS => Self::Inprogress, + libc::ESTALE => Self::Stale, + libc::EDQUOT => Self::Dquot, + libc::ECANCELED => Self::Canceled, + libc::EOWNERDEAD => Self::Ownerdead, + libc::ENOTRECOVERABLE => Self::Notrecoverable, + libc::ENOTSUP => Self::Notsup, + x => { + log::debug!("Unknown errno value: {}", x); + Self::Io + } + }, + None => { + log::debug!("Other I/O error: {}", err); + Self::Io + } + } + } +} + } +} From 4be3b06b618d21858745979cf1bb1c277a655b9c Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 18 Aug 2020 10:55:42 -0700 Subject: [PATCH 04/13] switch from log::debug to tracing::debug this duplicates work done in #2139 on code that moves from where the switch took place in that PR. --- crates/wasi-common/src/wasi.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index 045a118606..3124dff225 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/crates/wasi-common/src/wasi.rs @@ -271,12 +271,12 @@ impl From for Errno { winerror::ERROR_DIRECTORY => Self::Notdir, winerror::ERROR_ALREADY_EXISTS => Self::Exist, x => { - log::debug!("winerror: unknown error value: {}", x); + tracing::debug!("winerror: unknown error value: {}", x); Self::Io } }, None => { - log::debug!("Other I/O error: {}", err); + tracing::debug!("Other I/O error: {}", err); Self::Io } } @@ -365,12 +365,12 @@ impl From for Errno { libc::ENOTRECOVERABLE => Self::Notrecoverable, libc::ENOTSUP => Self::Notsup, x => { - log::debug!("Unknown errno value: {}", x); + tracing::debug!("Unknown errno value: {}", x); Self::Io } }, None => { - log::debug!("Other I/O error: {}", err); + tracing::debug!("Other I/O error: {}", err); Self::Io } } From 80b884780bb39815397e6eeb43b9efc4bc131ade Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 18 Aug 2020 10:57:43 -0700 Subject: [PATCH 05/13] wasmtime-wasi: fix path to errno type --- crates/wasi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/wasi/src/lib.rs b/crates/wasi/src/lib.rs index bd12def83a..c88125dbc9 100644 --- a/crates/wasi/src/lib.rs +++ b/crates/wasi/src/lib.rs @@ -32,7 +32,7 @@ resolution.", }, }, // Error to return when caller module is missing memory export: - missing_memory: { wasi_common::wasi::Errno::Inval }, + missing_memory: { wasi_common::wasi::types::Errno::Inval }, }); pub fn is_wasi_module(name: &str) -> bool { From 3bc1f84c9d5060421f6887b09fec749b6b5abab9 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 18 Aug 2020 11:31:08 -0700 Subject: [PATCH 06/13] windows: success fixes --- crates/wasi-common/src/sys/windows/poll.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/wasi-common/src/sys/windows/poll.rs b/crates/wasi-common/src/sys/windows/poll.rs index 73d6b74632..c38a0d4d97 100644 --- a/crates/wasi-common/src/sys/windows/poll.rs +++ b/crates/wasi-common/src/sys/windows/poll.rs @@ -104,7 +104,7 @@ lazy_static! { fn make_rw_event(event: &FdEventData, nbytes: Result) -> types::Event { let (nbytes, error) = match nbytes { - Ok(nbytes) => (nbytes, Error::Success), + Ok(nbytes) => (nbytes, types::Errno::Success), Err(e) => (u64::default(), e), }; types::Event { @@ -122,7 +122,7 @@ fn make_timeout_event(timeout: &ClockEventData) -> types::Event { types::Event { userdata: timeout.userdata, type_: types::Eventtype::Clock, - error: Error::Success, + error: types::Errno::Success, fd_readwrite: types::EventFdReadwrite { nbytes: 0, flags: types::Eventrwflags::empty(), From c4fbec6387a37319c71e89efa35524bc15086456 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 18 Aug 2020 15:02:54 -0700 Subject: [PATCH 07/13] additional windows fix --- crates/wasi-common/src/sys/windows/poll.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/wasi-common/src/sys/windows/poll.rs b/crates/wasi-common/src/sys/windows/poll.rs index c38a0d4d97..b994ad9487 100644 --- a/crates/wasi-common/src/sys/windows/poll.rs +++ b/crates/wasi-common/src/sys/windows/poll.rs @@ -105,7 +105,7 @@ lazy_static! { fn make_rw_event(event: &FdEventData, nbytes: Result) -> types::Event { let (nbytes, error) = match nbytes { Ok(nbytes) => (nbytes, types::Errno::Success), - Err(e) => (u64::default(), e), + Err(e) => (u64::default(), e.into()), }; types::Event { userdata: event.userdata, From e08173da9ea884d54227219a90ea9a3b94effc66 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 18 Aug 2020 16:05:42 -0700 Subject: [PATCH 08/13] fix windows: Error is not Copy like Errno is --- crates/wasi-common/src/sys/windows/poll.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/wasi-common/src/sys/windows/poll.rs b/crates/wasi-common/src/sys/windows/poll.rs index b994ad9487..5c4d1c6f6f 100644 --- a/crates/wasi-common/src/sys/windows/poll.rs +++ b/crates/wasi-common/src/sys/windows/poll.rs @@ -102,10 +102,13 @@ lazy_static! { }; } -fn make_rw_event(event: &FdEventData, nbytes: Result) -> types::Event { +fn make_rw_event( + event: &FdEventData, + nbytes: std::result::Result, +) -> types::Event { let (nbytes, error) = match nbytes { Ok(nbytes) => (nbytes, types::Errno::Success), - Err(e) => (u64::default(), e.into()), + Err(e) => (u64::default(), e), }; types::Event { userdata: event.userdata, @@ -174,8 +177,8 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec) { out_events.push(new_event); } -fn handle_error_event(event: FdEventData, error: Error, out_events: &mut Vec) { - let new_event = make_rw_event(&event, Err(error)); +fn handle_error_event(event: FdEventData, error: &Error, out_events: &mut Vec) { + let new_event = make_rw_event(&event, Err(error.into())); out_events.push(new_event); } @@ -239,7 +242,7 @@ pub(crate) fn oneoff( "poll_oneoff: unsupported file type: {}", other.get_file_type() ); - handle_error_event(event, Error::Notsup, events); + handle_error_event(event, &Error::Notsup, events); } } else { log::error!("can poll FdEvent for OS resources only"); @@ -291,7 +294,7 @@ pub(crate) fn 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, e, events), + PollState::Error(ref e) => handle_error_event(event, e, events), } } } From 9286bb8f0879ce8ef4a807b29efd7df03bdd46e0 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 18 Aug 2020 16:22:15 -0700 Subject: [PATCH 09/13] hmm this code is challenging --- crates/wasi-common/src/sys/windows/poll.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/wasi-common/src/sys/windows/poll.rs b/crates/wasi-common/src/sys/windows/poll.rs index 5c4d1c6f6f..c84a71c7b3 100644 --- a/crates/wasi-common/src/sys/windows/poll.rs +++ b/crates/wasi-common/src/sys/windows/poll.rs @@ -24,7 +24,7 @@ enum PollState { Ready, NotReady, // it's not ready, but we didn't wait TimedOut, // it's not ready and a timeout has occurred - Error(Error), + Error(types::Errno), } enum WaitMode { @@ -80,7 +80,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)), + Err(e) => PollState::Error(types::Errno::from(Error::from(e))), }; // Notify the requestor about data in stdin. They may have already timed out, @@ -177,8 +177,8 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec) { out_events.push(new_event); } -fn handle_error_event(event: FdEventData, error: &Error, out_events: &mut Vec) { - let new_event = make_rw_event(&event, Err(error.into())); +fn handle_error_event(event: FdEventData, error: types::Errno, out_events: &mut Vec) { + let new_event = make_rw_event(&event, Err(error)); out_events.push(new_event); } @@ -242,7 +242,7 @@ pub(crate) fn oneoff( "poll_oneoff: unsupported file type: {}", other.get_file_type() ); - handle_error_event(event, &Error::Notsup, events); + handle_error_event(event, types::Errno::Notsup, events); } } else { log::error!("can poll FdEvent for OS resources only"); @@ -294,7 +294,7 @@ pub(crate) fn 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(ref e) => handle_error_event(event, e, events), + PollState::Error(e) => handle_error_event(event, e, events), } } } From 4535741d01e380c6051a50d96809a62a0fd73979 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 19 Aug 2020 11:21:44 -0700 Subject: [PATCH 10/13] refactor when we translate io::Error to an Error * a certain subset of io::Errors are expected - these we have a (platform-specific, because windows) method to translate into one of the wasi errno variants in the Error enum. * some io::Errors are unexpected - wasi-common doesnt expect them from the underlying OS. rather than preserve any fidelity in reporting those to the user (only the unix impl attempts this), lets collect those as an `Error::UnexpectedIo(#[source] std::io::Error)`. Rather than trace at the conversion site, we rely on the wiggle error conversion hooks to trace the `Error`'s `Debug` impl, and then we convert all of these unexpected into `Errno::Io` for returning to the guest. This is a different behavior from before, and I don't have any firm guarantees that nobody was depending on the old behavior, but it appears to me that none of those unexpected errnos were reasonable to expect from any of the filesystem syscalls wasi-common is making. --- crates/wasi-common/src/error.rs | 86 ++++++++++++++++++- crates/wasi-common/src/wasi.rs | 144 +------------------------------- 2 files changed, 85 insertions(+), 145 deletions(-) diff --git a/crates/wasi-common/src/error.rs b/crates/wasi-common/src/error.rs index af6d83ea3c..4a1ad031fe 100644 --- a/crates/wasi-common/src/error.rs +++ b/crates/wasi-common/src/error.rs @@ -1,3 +1,4 @@ +use cfg_if::cfg_if; use thiserror::Error; pub type Result = std::result::Result; @@ -14,8 +15,11 @@ pub enum Error { #[error("Utf8Error: {0}")] Utf8(#[from] std::str::Utf8Error), - #[error("IO: {0}")] - IoError(#[from] std::io::Error), + /// The host OS may return an io error that doesn't match one of the + /// wasi errno variants we expect. We do not expose the details of this + /// error to the user. + #[error("Unexpected IoError: {0}")] + UnexpectedIo(#[source] std::io::Error), // Below this, all variants are from the `$errno` type: /// Errno::TooBig: Argument list too long @@ -94,3 +98,81 @@ impl From for Error { unreachable!("should be impossible: From") } } + +// Turning an io::Error into an Error has platform-specific behavior +cfg_if! { + if #[cfg(windows)] { +use winapi::shared::winerror; +use std::io; +impl From for Error { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(code) => match code as u32 { + winerror::ERROR_SUCCESS => Self::Success, + winerror::ERROR_BAD_ENVIRONMENT => Self::TooBig, + winerror::ERROR_FILE_NOT_FOUND => Self::Noent, + winerror::ERROR_PATH_NOT_FOUND => Self::Noent, + winerror::ERROR_TOO_MANY_OPEN_FILES => Self::Nfile, + winerror::ERROR_ACCESS_DENIED => Self::Acces, + winerror::ERROR_SHARING_VIOLATION => Self::Acces, + winerror::ERROR_PRIVILEGE_NOT_HELD => Self::Notcapable, + winerror::ERROR_INVALID_HANDLE => Self::Badf, + winerror::ERROR_INVALID_NAME => Self::Noent, + winerror::ERROR_NOT_ENOUGH_MEMORY => Self::Nomem, + winerror::ERROR_OUTOFMEMORY => Self::Nomem, + winerror::ERROR_DIR_NOT_EMPTY => Self::Notempty, + winerror::ERROR_NOT_READY => Self::Busy, + winerror::ERROR_BUSY => Self::Busy, + winerror::ERROR_NOT_SUPPORTED => Self::Notsup, + winerror::ERROR_FILE_EXISTS => Self::Exist, + winerror::ERROR_BROKEN_PIPE => Self::Pipe, + winerror::ERROR_BUFFER_OVERFLOW => Self::Nametoolong, + winerror::ERROR_NOT_A_REPARSE_POINT => Self::Inval, + winerror::ERROR_NEGATIVE_SEEK => Self::Inval, + winerror::ERROR_DIRECTORY => Self::Notdir, + winerror::ERROR_ALREADY_EXISTS => Self::Exist, + _ => Self::UnexpectedIo(err), + }, + None => Self::UnexpectedIo(err), + } + } +} + + } else { +use std::io; +impl From for Error { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(code) => match code { + libc::EPERM => Self::Perm, + libc::ENOENT => Self::Noent, + libc::E2BIG => Self::TooBig, + libc::EIO => Self::Io, + libc::EBADF => Self::Badf, + libc::EACCES => Self::Acces, + libc::EFAULT => Self::Fault, + libc::ENOTDIR => Self::Notdir, + libc::EISDIR => Self::Isdir, + libc::EINVAL => Self::Inval, + libc::EEXIST => Self::Exist, + libc::EFBIG => Self::Fbig, + libc::ENOSPC => Self::Nospc, + libc::ESPIPE => Self::Spipe, + libc::EMFILE => Self::Mfile, + libc::EMLINK => Self::Mlink, + libc::ENAMETOOLONG => Self::Nametoolong, + libc::ENOTEMPTY => Self::Notempty, + libc::ELOOP => Self::Loop, + libc::EOVERFLOW => Self::Overflow, + libc::EILSEQ => Self::Ilseq, + libc::ENOTSUP => Self::Notsup, + _ => Self::UnexpectedIo(err), + }, + None => { + Self::UnexpectedIo(err) + } + } + } +} + } +} diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index 3124dff225..80f29e64ac 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/crates/wasi-common/src/wasi.rs @@ -1,5 +1,4 @@ use crate::{Error, Result, WasiCtx}; -use cfg_if::cfg_if; use tracing::debug; wiggle::from_witx!({ @@ -36,7 +35,7 @@ impl From for Errno { Error::Guest(e) => e.into(), Error::TryFromInt(_) => Errno::Overflow, Error::Utf8(_) => Errno::Ilseq, - Error::IoError(e) => e.into(), + Error::UnexpectedIo(_) => Errno::Io, Error::TooBig => Errno::TooBig, Error::Acces => Errno::Acces, Error::Badf => Errno::Badf, @@ -237,144 +236,3 @@ impl crate::fdpool::Fd for types::Fd { Self::from(raw_fd) } } - -// Turning an io::Error into an Errno is different on windows. -cfg_if! { - if #[cfg(windows)] { -use winapi::shared::winerror; -use std::io; -impl From for Errno { - fn from(err: io::Error) -> Self { - match err.raw_os_error() { - Some(code) => match code as u32 { - winerror::ERROR_SUCCESS => Self::Success, - winerror::ERROR_BAD_ENVIRONMENT => Self::TooBig, - winerror::ERROR_FILE_NOT_FOUND => Self::Noent, - winerror::ERROR_PATH_NOT_FOUND => Self::Noent, - winerror::ERROR_TOO_MANY_OPEN_FILES => Self::Nfile, - winerror::ERROR_ACCESS_DENIED => Self::Acces, - winerror::ERROR_SHARING_VIOLATION => Self::Acces, - winerror::ERROR_PRIVILEGE_NOT_HELD => Self::Notcapable, - winerror::ERROR_INVALID_HANDLE => Self::Badf, - winerror::ERROR_INVALID_NAME => Self::Noent, - winerror::ERROR_NOT_ENOUGH_MEMORY => Self::Nomem, - winerror::ERROR_OUTOFMEMORY => Self::Nomem, - winerror::ERROR_DIR_NOT_EMPTY => Self::Notempty, - winerror::ERROR_NOT_READY => Self::Busy, - winerror::ERROR_BUSY => Self::Busy, - winerror::ERROR_NOT_SUPPORTED => Self::Notsup, - winerror::ERROR_FILE_EXISTS => Self::Exist, - winerror::ERROR_BROKEN_PIPE => Self::Pipe, - winerror::ERROR_BUFFER_OVERFLOW => Self::Nametoolong, - winerror::ERROR_NOT_A_REPARSE_POINT => Self::Inval, - winerror::ERROR_NEGATIVE_SEEK => Self::Inval, - winerror::ERROR_DIRECTORY => Self::Notdir, - winerror::ERROR_ALREADY_EXISTS => Self::Exist, - x => { - tracing::debug!("winerror: unknown error value: {}", x); - Self::Io - } - }, - None => { - tracing::debug!("Other I/O error: {}", err); - Self::Io - } - } - } -} - - } else { -use std::io; -impl From for Errno { - fn from(err: io::Error) -> Self { - match err.raw_os_error() { - Some(code) => match code { - libc::EPERM => Self::Perm, - libc::ENOENT => Self::Noent, - libc::ESRCH => Self::Srch, - libc::EINTR => Self::Intr, - libc::EIO => Self::Io, - libc::ENXIO => Self::Nxio, - libc::E2BIG => Self::TooBig, - libc::ENOEXEC => Self::Noexec, - libc::EBADF => Self::Badf, - libc::ECHILD => Self::Child, - libc::EAGAIN => Self::Again, - libc::ENOMEM => Self::Nomem, - libc::EACCES => Self::Acces, - libc::EFAULT => Self::Fault, - libc::EBUSY => Self::Busy, - libc::EEXIST => Self::Exist, - libc::EXDEV => Self::Xdev, - libc::ENODEV => Self::Nodev, - libc::ENOTDIR => Self::Notdir, - libc::EISDIR => Self::Isdir, - libc::EINVAL => Self::Inval, - libc::ENFILE => Self::Nfile, - libc::EMFILE => Self::Mfile, - libc::ENOTTY => Self::Notty, - libc::ETXTBSY => Self::Txtbsy, - libc::EFBIG => Self::Fbig, - libc::ENOSPC => Self::Nospc, - libc::ESPIPE => Self::Spipe, - libc::EROFS => Self::Rofs, - libc::EMLINK => Self::Mlink, - libc::EPIPE => Self::Pipe, - libc::EDOM => Self::Dom, - libc::ERANGE => Self::Range, - libc::EDEADLK => Self::Deadlk, - libc::ENAMETOOLONG => Self::Nametoolong, - libc::ENOLCK => Self::Nolck, - libc::ENOSYS => Self::Nosys, - libc::ENOTEMPTY => Self::Notempty, - libc::ELOOP => Self::Loop, - libc::ENOMSG => Self::Nomsg, - libc::EIDRM => Self::Idrm, - libc::ENOLINK => Self::Nolink, - libc::EPROTO => Self::Proto, - libc::EMULTIHOP => Self::Multihop, - libc::EBADMSG => Self::Badmsg, - libc::EOVERFLOW => Self::Overflow, - libc::EILSEQ => Self::Ilseq, - libc::ENOTSOCK => Self::Notsock, - libc::EDESTADDRREQ => Self::Destaddrreq, - libc::EMSGSIZE => Self::Msgsize, - libc::EPROTOTYPE => Self::Prototype, - libc::ENOPROTOOPT => Self::Noprotoopt, - libc::EPROTONOSUPPORT => Self::Protonosupport, - libc::EAFNOSUPPORT => Self::Afnosupport, - libc::EADDRINUSE => Self::Addrinuse, - libc::EADDRNOTAVAIL => Self::Addrnotavail, - libc::ENETDOWN => Self::Netdown, - libc::ENETUNREACH => Self::Netunreach, - libc::ENETRESET => Self::Netreset, - libc::ECONNABORTED => Self::Connaborted, - libc::ECONNRESET => Self::Connreset, - libc::ENOBUFS => Self::Nobufs, - libc::EISCONN => Self::Isconn, - libc::ENOTCONN => Self::Notconn, - libc::ETIMEDOUT => Self::Timedout, - libc::ECONNREFUSED => Self::Connrefused, - libc::EHOSTUNREACH => Self::Hostunreach, - libc::EALREADY => Self::Already, - libc::EINPROGRESS => Self::Inprogress, - libc::ESTALE => Self::Stale, - libc::EDQUOT => Self::Dquot, - libc::ECANCELED => Self::Canceled, - libc::EOWNERDEAD => Self::Ownerdead, - libc::ENOTRECOVERABLE => Self::Notrecoverable, - libc::ENOTSUP => Self::Notsup, - x => { - tracing::debug!("Unknown errno value: {}", x); - Self::Io - } - }, - None => { - tracing::debug!("Other I/O error: {}", err); - Self::Io - } - } - } -} - } -} From c1aec81b84ab0d0498997e0ee90e2838a5eb47ea Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 19 Aug 2020 12:01:16 -0700 Subject: [PATCH 11/13] add enough errno variants to cover all windows codes too --- crates/wasi-common/src/error.rs | 17 ++++++++++++++++- crates/wasi-common/src/sys/windows/poll.rs | 2 +- crates/wasi-common/src/wasi.rs | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/wasi-common/src/error.rs b/crates/wasi-common/src/error.rs index 4a1ad031fe..074a61de48 100644 --- a/crates/wasi-common/src/error.rs +++ b/crates/wasi-common/src/error.rs @@ -31,6 +31,9 @@ pub enum Error { /// Errno::Badf: Bad file descriptor #[error("Badf: Bad file descriptor")] Badf, + /// Errno::Busy: Device or resource busy + #[error("Busy: Device or resource busy")] + Busy, /// Errno::Exist: File exists #[error("Exist: File exists")] Exist, @@ -64,9 +67,15 @@ pub enum Error { /// Errno::Nametoolong: Filename too long #[error("Nametoolong: Filename too long")] Nametoolong, + /// Errno::Nfile: Too many files open in system + #[error("Nfile: Too many files open in system")] + Nfile, /// Errno::Noent: No such file or directory #[error("Noent: No such file or directory")] Noent, + /// Errno::Nomem: Not enough space + #[error("Nomem: Not enough space")] + Nomem, /// Errno::Nospc: No space left on device #[error("Nospc: No space left on device")] Nospc, @@ -82,6 +91,9 @@ pub enum Error { /// Errno::Overflow: Value too large to be stored in data type. #[error("Overflow: Value too large to be stored in data type")] Overflow, + /// Errno::Pipe: Broken pipe + #[error("Pipe: Broken pipe")] + Pipe, /// Errno::Perm: Operation not permitted #[error("Perm: Operation not permitted")] Perm, @@ -108,7 +120,6 @@ impl From for Error { fn from(err: io::Error) -> Self { match err.raw_os_error() { Some(code) => match code as u32 { - winerror::ERROR_SUCCESS => Self::Success, winerror::ERROR_BAD_ENVIRONMENT => Self::TooBig, winerror::ERROR_FILE_NOT_FOUND => Self::Noent, winerror::ERROR_PATH_NOT_FOUND => Self::Noent, @@ -144,11 +155,14 @@ impl From for Error { fn from(err: io::Error) -> Self { match err.raw_os_error() { Some(code) => match code { + libc::EPIPE => Self::Pipe, libc::EPERM => Self::Perm, libc::ENOENT => Self::Noent, + libc::ENOMEM => Self::Nomem, libc::E2BIG => Self::TooBig, libc::EIO => Self::Io, libc::EBADF => Self::Badf, + libc::EBUSY => Self::Busy, libc::EACCES => Self::Acces, libc::EFAULT => Self::Fault, libc::ENOTDIR => Self::Notdir, @@ -161,6 +175,7 @@ impl From for Error { libc::EMFILE => Self::Mfile, libc::EMLINK => Self::Mlink, libc::ENAMETOOLONG => Self::Nametoolong, + libc::ENFILE => Self::Nfile, libc::ENOTEMPTY => Self::Notempty, libc::ELOOP => Self::Loop, libc::EOVERFLOW => Self::Overflow, diff --git a/crates/wasi-common/src/sys/windows/poll.rs b/crates/wasi-common/src/sys/windows/poll.rs index c84a71c7b3..dd7c6cafaa 100644 --- a/crates/wasi-common/src/sys/windows/poll.rs +++ b/crates/wasi-common/src/sys/windows/poll.rs @@ -164,7 +164,7 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec) { .as_file() .and_then(|f| f.metadata()) .map(|m| m.len()) - .map_err(Into::into) + .map_err(|ioerror| types::Errno::from(Error::from(ioerror))) } else { // The spec is unclear what nbytes should actually be for __WASI_EVENTTYPE_FD_WRITE and // the implementation on Unix just returns 0 here, so it's probably fine diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index 80f29e64ac..ca4b5bd3fe 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/crates/wasi-common/src/wasi.rs @@ -39,6 +39,7 @@ impl From for Errno { Error::TooBig => Errno::TooBig, Error::Acces => Errno::Acces, Error::Badf => Errno::Badf, + Error::Busy => Errno::Busy, Error::Exist => Errno::Exist, Error::Fault => Errno::Fault, Error::Fbig => Errno::Fbig, @@ -50,12 +51,15 @@ impl From for Errno { Error::Mfile => Errno::Mfile, Error::Mlink => Errno::Mlink, Error::Nametoolong => Errno::Nametoolong, + Error::Nfile => Errno::Nfile, Error::Noent => Errno::Noent, + Error::Nomem => Errno::Nomem, Error::Nospc => Errno::Nospc, Error::Notdir => Errno::Notdir, Error::Notempty => Errno::Notempty, Error::Notsup => Errno::Notsup, Error::Overflow => Errno::Overflow, + Error::Pipe => Errno::Pipe, Error::Perm => Errno::Perm, Error::Spipe => Errno::Spipe, Error::Notcapable => Errno::Notcapable, From e8c01ddef1a02c583e7e9fa031f424fcedd0aa4f Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 19 Aug 2020 14:29:14 -0700 Subject: [PATCH 12/13] put getrandom::Error into Error --- crates/wasi-common/src/error.rs | 2 ++ .../wasi-common/src/snapshots/wasi_snapshot_preview1.rs | 8 +++----- crates/wasi-common/src/wasi.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/wasi-common/src/error.rs b/crates/wasi-common/src/error.rs index 074a61de48..282a46734f 100644 --- a/crates/wasi-common/src/error.rs +++ b/crates/wasi-common/src/error.rs @@ -14,6 +14,8 @@ pub enum Error { TryFromInt(#[from] std::num::TryFromIntError), #[error("Utf8Error: {0}")] Utf8(#[from] std::str::Utf8Error), + #[error("GetRandom: {0}")] + GetRandom(#[from] getrandom::Error), /// The host OS may return an io error that doesn't match one of the /// wasi errno variants we expect. We do not expose the details of this diff --git a/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs b/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs index 9f2eaa1443..4c4034aa8a 100644 --- a/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs +++ b/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs @@ -5,7 +5,7 @@ use crate::wasi::wasi_snapshot_preview1::WasiSnapshotPreview1; use crate::wasi::{types, AsBytes}; use crate::{path, poll}; use crate::{Error, Result, WasiCtx}; -use log::{debug, error, trace}; +use log::{debug, trace}; use std::convert::TryInto; use std::io::{self, SeekFrom}; use wiggle::{GuestPtr, GuestSlice}; @@ -802,10 +802,8 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { fn random_get(&self, buf: &GuestPtr, buf_len: types::Size) -> Result<()> { let mut slice = buf.as_array(buf_len).as_slice()?; - getrandom::getrandom(&mut *slice).map_err(|err| { - error!("getrandom failure: {:?}", err); - Error::Io - }) + getrandom::getrandom(&mut *slice)?; + Ok(()) } fn sock_recv( diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index ca4b5bd3fe..4903a672be 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/crates/wasi-common/src/wasi.rs @@ -36,6 +36,7 @@ impl From for Errno { Error::TryFromInt(_) => Errno::Overflow, Error::Utf8(_) => Errno::Ilseq, Error::UnexpectedIo(_) => Errno::Io, + Error::GetRandom(_) => Errno::Io, Error::TooBig => Errno::TooBig, Error::Acces => Errno::Acces, Error::Badf => Errno::Badf, From 530ea50c8213b6c484c0963d29e6b5722d9593dd Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 19 Aug 2020 15:10:04 -0700 Subject: [PATCH 13/13] wasi-common: dep on getrandom requires std --- crates/wasi-common/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/wasi-common/Cargo.toml b/crates/wasi-common/Cargo.toml index f7250c25df..d42ee4d1c3 100644 --- a/crates/wasi-common/Cargo.toml +++ b/crates/wasi-common/Cargo.toml @@ -20,7 +20,7 @@ links = "wasi-common-19" anyhow = "1.0" thiserror = "1.0" libc = "0.2" -getrandom = "0.1" +getrandom = { version = "0.1.14", features = ["std"] } cfg-if = "0.1.9" log = "0.4" filetime = "0.2.7"