From e8160c9a6b8a58fad313bbce4c7a5ea4dc93a43b Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Mon, 17 Aug 2020 18:45:33 -0700 Subject: [PATCH] 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 + } + } + } +} + } +}