Merge pull request #2140 from bytecodealliance/pch/wasi_error_handling
wasi-common: refactor error types
This commit is contained in:
12
Cargo.lock
generated
12
Cargo.lock
generated
@@ -2117,9 +2117,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",
|
||||
@@ -2129,9 +2129,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",
|
||||
@@ -2140,9 +2140,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",
|
||||
]
|
||||
|
||||
@@ -20,13 +20,13 @@ 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"
|
||||
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.15"
|
||||
tracing = "0.1.19"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
yanix = { path = "yanix", version = "0.19.0" }
|
||||
|
||||
@@ -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;
|
||||
@@ -469,7 +469,7 @@ impl WasiCtx {
|
||||
pub(crate) fn get_entry(&self, fd: types::Fd) -> Result<Rc<Entry>> {
|
||||
match self.entries.borrow().get(&fd) {
|
||||
Some(entry) => Ok(entry),
|
||||
None => Err(Errno::Badf),
|
||||
None => Err(Error::Badf),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,7 +478,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<types::Fd> {
|
||||
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`
|
||||
@@ -489,6 +489,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<Rc<Entry>> {
|
||||
self.entries.borrow_mut().remove(fd).ok_or(Errno::Badf)
|
||||
self.entries.borrow_mut().remove(fd).ok_or(Error::Badf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -77,7 +77,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<EntryHandle> {
|
||||
self.validate_rights(rights)?;
|
||||
@@ -87,7 +87,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) {
|
||||
@@ -98,7 +98,7 @@ impl Entry {
|
||||
actual = tracing::field::display(this_rights),
|
||||
"validate_rights failed",
|
||||
);
|
||||
Err(Errno::Notcapable)
|
||||
Err(Error::Notcapable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
195
crates/wasi-common/src/error.rs
Normal file
195
crates/wasi-common/src/error.rs
Normal file
@@ -0,0 +1,195 @@
|
||||
use cfg_if::cfg_if;
|
||||
use thiserror::Error;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// 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("Wiggle GuestError: {0}")]
|
||||
Guest(#[from] wiggle::GuestError),
|
||||
#[error("TryFromIntError: {0}")]
|
||||
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
|
||||
/// 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
|
||||
#[error("TooBig: Argument list too long")]
|
||||
TooBig,
|
||||
/// Errno::Acces: Permission denied
|
||||
#[error("Acces: Permission denied")]
|
||||
Acces,
|
||||
/// 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,
|
||||
/// Errno::Fault: Bad address
|
||||
#[error("Fault: Bad address")]
|
||||
Fault,
|
||||
/// Errno::Fbig: File too large
|
||||
#[error("Fbig: File too large")]
|
||||
Fbig,
|
||||
/// Errno::Ilseq: Illegal byte sequence
|
||||
#[error("Ilseq: Illegal byte sequence")]
|
||||
Ilseq,
|
||||
/// Errno::Inval: Invalid argument
|
||||
#[error("Inval: Invalid argument")]
|
||||
Inval,
|
||||
/// Errno::Io: I/O error
|
||||
#[error("Io: I/o error")]
|
||||
Io,
|
||||
/// Errno::Isdir: Is a directory
|
||||
#[error("Isdir: Is a directory")]
|
||||
Isdir,
|
||||
/// Errno::Loop: Too many levels of symbolic links
|
||||
#[error("Loop: Too many levels of symbolic links")]
|
||||
Loop,
|
||||
/// Errno::Mfile: File descriptor value too large
|
||||
#[error("Mfile: File descriptor value too large")]
|
||||
Mfile,
|
||||
/// Errno::Mlink: Too many links
|
||||
#[error("Mlink: Too many links")]
|
||||
Mlink,
|
||||
/// 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,
|
||||
/// 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("Notempty: Directory not empty")]
|
||||
Notempty,
|
||||
/// Errno::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("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,
|
||||
/// Errno::Spipe: Invalid seek
|
||||
#[error("Spipe: Invalid seek")]
|
||||
Spipe,
|
||||
/// Errno::Notcapable: Extension: Capabilities insufficient
|
||||
#[error("Notcapable: cabailities insufficient")]
|
||||
Notcapable,
|
||||
}
|
||||
|
||||
impl From<std::convert::Infallible> for Error {
|
||||
fn from(_err: std::convert::Infallible) -> Self {
|
||||
unreachable!("should be impossible: From<Infallible>")
|
||||
}
|
||||
}
|
||||
|
||||
// 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<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self {
|
||||
match err.raw_os_error() {
|
||||
Some(code) => match code as u32 {
|
||||
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<io::Error> 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,
|
||||
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::ENFILE => Self::Nfile,
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<types::Fdflags> {
|
||||
Ok(types::Fdflags::empty())
|
||||
}
|
||||
fn fdstat_set_flags(&self, _fdflags: types::Fdflags) -> Result<()> {
|
||||
Err(Errno::Badf)
|
||||
Err(Error::Badf)
|
||||
}
|
||||
fn filestat_get(&self) -> Result<types::Filestat> {
|
||||
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<usize> {
|
||||
Err(Errno::Badf)
|
||||
Err(Error::Badf)
|
||||
}
|
||||
fn pwritev(&self, _buf: &[io::IoSlice], _offset: u64) -> Result<usize> {
|
||||
Err(Errno::Badf)
|
||||
Err(Error::Badf)
|
||||
}
|
||||
fn read_vectored(&self, _iovs: &mut [io::IoSliceMut]) -> Result<usize> {
|
||||
Err(Errno::Badf)
|
||||
Err(Error::Badf)
|
||||
}
|
||||
fn readdir<'a>(
|
||||
&'a self,
|
||||
_cookie: types::Dircookie,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<(types::Dirent, String)>> + 'a>> {
|
||||
Err(Errno::Badf)
|
||||
Err(Error::Badf)
|
||||
}
|
||||
fn seek(&self, _offset: SeekFrom) -> Result<u64> {
|
||||
Err(Errno::Badf)
|
||||
Err(Error::Badf)
|
||||
}
|
||||
fn sync(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn write_vectored(&self, _iovs: &[io::IoSlice]) -> Result<usize> {
|
||||
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<types::Filestat> {
|
||||
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<Box<dyn Handle>> {
|
||||
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<usize> {
|
||||
Err(Errno::Acces)
|
||||
Err(Error::Acces)
|
||||
}
|
||||
fn readlinkat(&self, _path: &str) -> Result<String> {
|
||||
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<dyn Handle>, _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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(".")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,11 @@ 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::{path, poll};
|
||||
use crate::wasi::{types, AsBytes};
|
||||
use crate::{path, poll, Error, Result, WasiCtx};
|
||||
use std::convert::TryInto;
|
||||
use std::io::{self, SeekFrom};
|
||||
use tracing::{debug, error, trace};
|
||||
use tracing::{debug, trace};
|
||||
use wiggle::{GuestPtr, GuestSlice};
|
||||
|
||||
impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
@@ -36,7 +35,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 +65,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 +113,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 +155,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(())
|
||||
@@ -206,7 +205,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 = {
|
||||
@@ -225,9 +224,9 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
fn fd_prestat_get(&self, fd: types::Fd) -> Result<types::Prestat> {
|
||||
// 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())?;
|
||||
@@ -245,16 +244,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);
|
||||
@@ -283,7 +282,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 = {
|
||||
@@ -339,7 +338,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 {
|
||||
@@ -356,7 +355,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.
|
||||
@@ -364,12 +363,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)?;
|
||||
@@ -672,7 +671,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
nsubscriptions: types::Size,
|
||||
) -> Result<types::Size> {
|
||||
if u64::from(nsubscriptions) > types::Filesize::max_value() {
|
||||
return Err(Errno::Inval);
|
||||
return Err(Error::Inval);
|
||||
}
|
||||
|
||||
let mut subscriptions = Vec::new();
|
||||
@@ -690,7 +689,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 {
|
||||
@@ -721,7 +720,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,
|
||||
@@ -747,7 +746,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,10 +803,8 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
|
||||
fn random_get(&self, buf: &GuestPtr<u8>, buf_len: types::Size) -> Result<()> {
|
||||
let mut slice = buf.as_array(buf_len).as_slice()?;
|
||||
getrandom::getrandom(&mut *slice).map_err(|err| {
|
||||
error!(error = tracing::field::display(err), "getrandom failure");
|
||||
Errno::Io
|
||||
})
|
||||
getrandom::getrandom(&mut *slice)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sock_recv(
|
||||
|
||||
@@ -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<u128> {
|
||||
}
|
||||
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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 std::any::Any;
|
||||
use std::io;
|
||||
use std::ops::Deref;
|
||||
@@ -102,7 +103,7 @@ impl Handle for OsDir {
|
||||
let new_handle = match new_handle.as_any().downcast_ref::<Self>() {
|
||||
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::<Self>() {
|
||||
None => {
|
||||
error!("Tried to rename with handle that's not an OsDir");
|
||||
return Err(Errno::Badf);
|
||||
return Err(Error::Badf);
|
||||
}
|
||||
Some(handle) => handle,
|
||||
};
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) => {
|
||||
tracing::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) => {
|
||||
|
||||
@@ -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<types::Timestamp> {
|
||||
@@ -11,11 +12,11 @@ pub(crate) fn res_get(clock_id: types::Clockid) -> Result<types::Timestamp> {
|
||||
(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<types::Timestamp> {
|
||||
(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)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<()> {
|
||||
|
||||
@@ -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;
|
||||
@@ -144,98 +145,6 @@ impl From<types::Clockid> for ClockId {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<types::Fdflags> for OFlags {
|
||||
fn from(fdflags: types::Fdflags) -> Self {
|
||||
let mut nix_flags = Self::empty();
|
||||
@@ -300,13 +209,13 @@ impl From<types::Oflags> for OFlags {
|
||||
}
|
||||
|
||||
impl TryFrom<libc::stat> for types::Filestat {
|
||||
type Error = Errno;
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(filestat: libc::stat) -> Result<Self> {
|
||||
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<types::Timestamp> {
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
@@ -147,7 +148,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) => {
|
||||
@@ -166,7 +167,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) => {
|
||||
@@ -180,7 +181,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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -244,7 +245,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 {
|
||||
|
||||
@@ -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;
|
||||
@@ -67,7 +68,7 @@ pub(crate) fn oneoff(
|
||||
fn handle_timeout_event(timeout: ClockEventData, events: &mut Vec<types::Event>) {
|
||||
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(),
|
||||
@@ -114,7 +115,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,
|
||||
@@ -124,7 +125,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,
|
||||
@@ -134,7 +135,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,
|
||||
@@ -144,7 +145,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()?,
|
||||
|
||||
@@ -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<Duration> {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map_err(|_| Errno::Fault)
|
||||
.map_err(|_| Error::Fault)
|
||||
}
|
||||
|
||||
fn get_proc_cputime() -> Result<Duration> {
|
||||
|
||||
@@ -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 std::convert::TryInto;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::os::windows::fs::OpenOptionsExt;
|
||||
|
||||
@@ -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<T: AsRawHandle> AsFile for T {
|
||||
@@ -106,47 +106,7 @@ pub(crate) fn file_serial_no(file: &File) -> io::Result<u64> {
|
||||
Ok(no)
|
||||
}
|
||||
|
||||
impl From<io::Error> 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<string::FromUtf16Error> for Errno {
|
||||
impl From<string::FromUtf16Error> for Error {
|
||||
fn from(_err: string::FromUtf16Error) -> Self {
|
||||
Self::Ilseq
|
||||
}
|
||||
@@ -166,14 +126,14 @@ fn change_time(file: &File) -> io::Result<i64> {
|
||||
|
||||
fn systemtime_to_timestamp(st: SystemTime) -> Result<u64> {
|
||||
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<Self> {
|
||||
let metadata = file.metadata()?;
|
||||
|
||||
@@ -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<P: AsRef<Path>>(file: &OsDir, path: P) -> Result<PathBuf> {
|
||||
// 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<String> {
|
||||
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<String> {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +179,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(),
|
||||
})?;
|
||||
}
|
||||
@@ -193,7 +194,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,7 +218,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,11 +243,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() {
|
||||
@@ -260,14 +261,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 => {
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
return Err(Errno::Io);
|
||||
return Err(Error::Io);
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -302,8 +303,8 @@ pub(crate) fn readlink(dirfd: &OsDir, path: &str, buf: &mut [u8]) -> Result<usiz
|
||||
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||
let target_path = target_path
|
||||
.strip_prefix(dir_path)
|
||||
.map_err(|_| Errno::Notcapable)
|
||||
.and_then(|path| path.to_str().map(String::from).ok_or(Errno::Ilseq))?;
|
||||
.map_err(|_| Error::Notcapable)
|
||||
.and_then(|path| path.to_str().map(String::from).ok_or(Error::Ilseq))?;
|
||||
|
||||
if buf.len() > 0 {
|
||||
let mut chars = target_path.chars();
|
||||
@@ -341,12 +342,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
|
||||
@@ -362,7 +363,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.
|
||||
@@ -378,7 +379,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -389,7 +390,7 @@ pub(crate) fn rename(
|
||||
}
|
||||
None => {
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
Err(Errno::Io)
|
||||
Err(Error::Io)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -435,7 +436,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -446,7 +447,7 @@ pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path_: &str) -> Res
|
||||
}
|
||||
None => {
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
Err(Errno::Io)
|
||||
Err(Error::Io)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -481,15 +482,15 @@ pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> {
|
||||
}
|
||||
None => {
|
||||
tracing::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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 std::convert::TryInto;
|
||||
use std::sync::mpsc::{self, Receiver, RecvTimeoutError, Sender, TryRecvError};
|
||||
@@ -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(types::Errno),
|
||||
}
|
||||
|
||||
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(types::Errno::from(Error::from(e))),
|
||||
};
|
||||
|
||||
// Notify the requestor about data in stdin. They may have already timed out,
|
||||
@@ -101,9 +102,12 @@ lazy_static! {
|
||||
};
|
||||
}
|
||||
|
||||
fn make_rw_event(event: &FdEventData, nbytes: Result<u64>) -> types::Event {
|
||||
fn make_rw_event(
|
||||
event: &FdEventData,
|
||||
nbytes: std::result::Result<u64, types::Errno>,
|
||||
) -> types::Event {
|
||||
let (nbytes, error) = match nbytes {
|
||||
Ok(nbytes) => (nbytes, Errno::Success),
|
||||
Ok(nbytes) => (nbytes, types::Errno::Success),
|
||||
Err(e) => (u64::default(), e),
|
||||
};
|
||||
types::Event {
|
||||
@@ -121,7 +125,7 @@ fn make_timeout_event(timeout: &ClockEventData) -> types::Event {
|
||||
types::Event {
|
||||
userdata: timeout.userdata,
|
||||
type_: types::Eventtype::Clock,
|
||||
error: Errno::Success,
|
||||
error: types::Errno::Success,
|
||||
fd_readwrite: types::EventFdReadwrite {
|
||||
nbytes: 0,
|
||||
flags: types::Eventrwflags::empty(),
|
||||
@@ -160,7 +164,7 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec<types::Event>) {
|
||||
.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
|
||||
@@ -173,7 +177,7 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec<types::Event>) {
|
||||
out_events.push(new_event);
|
||||
}
|
||||
|
||||
fn handle_error_event(event: FdEventData, error: Errno, out_events: &mut Vec<types::Event>) {
|
||||
fn handle_error_event(event: FdEventData, error: types::Errno, out_events: &mut Vec<types::Event>) {
|
||||
let new_event = make_rw_event(&event, Err(error));
|
||||
out_events.push(new_event);
|
||||
}
|
||||
@@ -238,11 +242,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, types::Errno::Notsup, events);
|
||||
}
|
||||
} else {
|
||||
tracing::error!("can poll FdEvent for OS resources only");
|
||||
return Err(Errno::Badf);
|
||||
return Err(Error::Badf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +310,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 std::any::Any;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::hash_map::Entry;
|
||||
@@ -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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
trace!(buffer_length = buf.len(), offset = offset, "pread");
|
||||
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);
|
||||
|
||||
@@ -109,9 +110,9 @@ impl FileContents for VecFileContents {
|
||||
}
|
||||
|
||||
fn pwrite(&mut self, buf: &[u8], offset: types::Filesize) -> Result<usize> {
|
||||
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);
|
||||
@@ -206,11 +207,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() {
|
||||
@@ -242,7 +243,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)
|
||||
}
|
||||
@@ -256,8 +257,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)
|
||||
}
|
||||
@@ -269,23 +270,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));
|
||||
}
|
||||
}
|
||||
@@ -320,10 +321,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);
|
||||
@@ -340,7 +341,7 @@ impl Handle for InMemoryFile {
|
||||
}
|
||||
// PathOps
|
||||
fn create_directory(&self, _path: &str) -> Result<()> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
fn openat(
|
||||
&self,
|
||||
@@ -355,7 +356,7 @@ impl Handle for InMemoryFile {
|
||||
"InMemoryFile::openat was passed oflags DIRECTORY, but {:?} is a file.",
|
||||
path
|
||||
);
|
||||
return Err(Errno::Notdir);
|
||||
return Err(Error::Notdir);
|
||||
}
|
||||
|
||||
if path == "." {
|
||||
@@ -366,7 +367,7 @@ impl Handle for InMemoryFile {
|
||||
None => self.try_clone().map_err(Into::into),
|
||||
}
|
||||
} else {
|
||||
Err(Errno::Acces)
|
||||
Err(Error::Acces)
|
||||
}
|
||||
}
|
||||
fn link(
|
||||
@@ -376,25 +377,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<usize> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
fn readlinkat(&self, _path: &str) -> Result<String> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
fn rename(&self, _old_path: &str, _new_handle: Box<dyn Handle>, _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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,7 +588,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));
|
||||
@@ -595,7 +596,7 @@ impl Handle for VirtualDir {
|
||||
v.insert(new_dir);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Errno::Acces)
|
||||
Err(Error::Acces)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -653,7 +654,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()) {
|
||||
@@ -661,7 +662,7 @@ impl Handle for VirtualDir {
|
||||
let creat_excl_mask = types::Oflags::CREAT | types::Oflags::EXCL;
|
||||
if (oflags & creat_excl_mask) == creat_excl_mask {
|
||||
tracing::trace!("VirtualDir::openat was passed oflags CREAT|EXCL, but the file {:?} exists.", file_name);
|
||||
return Err(Errno::Exist);
|
||||
return Err(Error::Exist);
|
||||
}
|
||||
|
||||
if oflags.contains(&types::Oflags::DIRECTORY)
|
||||
@@ -671,7 +672,7 @@ impl Handle for VirtualDir {
|
||||
"VirtualDir::openat was passed oflags DIRECTORY, but {:?} is a file.",
|
||||
file_name
|
||||
);
|
||||
return Err(Errno::Notdir);
|
||||
return Err(Error::Notdir);
|
||||
}
|
||||
|
||||
e.get().try_clone().map_err(Into::into)
|
||||
@@ -683,7 +684,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);
|
||||
}
|
||||
|
||||
tracing::trace!("VirtualDir::openat creating an InMemoryFile named {}", path);
|
||||
@@ -693,14 +694,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<String> {
|
||||
// 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('/');
|
||||
@@ -709,13 +710,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.
|
||||
@@ -738,7 +739,7 @@ impl Handle for VirtualDir {
|
||||
"VirtualDir::remove_directory failed to remove {}, no such entry",
|
||||
trimmed_path
|
||||
);
|
||||
Err(Errno::Noent)
|
||||
Err(Error::Noent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -749,7 +750,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();
|
||||
@@ -757,7 +758,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();
|
||||
@@ -779,7 +780,7 @@ impl Handle for VirtualDir {
|
||||
"VirtualDir::unlink_file failed to remove {}, no such entry",
|
||||
trimmed_path
|
||||
);
|
||||
Err(Errno::Noent)
|
||||
Err(Error::Noent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<R: Read + Any> Handle for ReadPipe<R> {
|
||||
_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<R: Read + Any> Handle for ReadPipe<R> {
|
||||
}
|
||||
|
||||
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<usize> {
|
||||
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<types::Filesize> {
|
||||
Err(Errno::Spipe)
|
||||
Err(Error::Spipe)
|
||||
}
|
||||
|
||||
fn read_vectored(&self, iovs: &mut [io::IoSliceMut]) -> Result<usize> {
|
||||
@@ -178,7 +179,7 @@ impl<R: Read + Any> Handle for ReadPipe<R> {
|
||||
}
|
||||
|
||||
fn create_directory(&self, _path: &str) -> Result<()> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn openat(
|
||||
@@ -189,7 +190,7 @@ impl<R: Read + Any> Handle for ReadPipe<R> {
|
||||
_oflags: types::Oflags,
|
||||
_fd_flags: types::Fdflags,
|
||||
) -> Result<Box<dyn Handle>> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn link(
|
||||
@@ -199,31 +200,31 @@ impl<R: Read + Any> Handle for ReadPipe<R> {
|
||||
_new_path: &str,
|
||||
_follow: bool,
|
||||
) -> Result<()> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn readlink(&self, _path: &str, _buf: &mut [u8]) -> Result<usize> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn readlinkat(&self, _path: &str) -> Result<String> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn rename(&self, _old_path: &str, _new_handle: Box<dyn Handle>, _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<W: Write + Any> Handle for WritePipe<W> {
|
||||
_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<W: Write + Any> Handle for WritePipe<W> {
|
||||
}
|
||||
|
||||
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<usize> {
|
||||
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<types::Filesize> {
|
||||
Err(Errno::Spipe)
|
||||
Err(Error::Spipe)
|
||||
}
|
||||
|
||||
fn write_vectored(&self, iovs: &[io::IoSlice]) -> Result<usize> {
|
||||
@@ -363,7 +364,7 @@ impl<W: Write + Any> Handle for WritePipe<W> {
|
||||
}
|
||||
|
||||
fn create_directory(&self, _path: &str) -> Result<()> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn openat(
|
||||
@@ -374,7 +375,7 @@ impl<W: Write + Any> Handle for WritePipe<W> {
|
||||
_oflags: types::Oflags,
|
||||
_fd_flags: types::Fdflags,
|
||||
) -> Result<Box<dyn Handle>> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn link(
|
||||
@@ -384,30 +385,30 @@ impl<W: Write + Any> Handle for WritePipe<W> {
|
||||
_new_path: &str,
|
||||
_follow: bool,
|
||||
) -> Result<()> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn readlink(&self, _path: &str, _buf: &mut [u8]) -> Result<usize> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn readlinkat(&self, _path: &str) -> Result<String> {
|
||||
Err(Errno::Notdir)
|
||||
Err(Error::Notdir)
|
||||
}
|
||||
|
||||
fn rename(&self, _old_path: &str, _new_handle: Box<dyn Handle>, _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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
//! 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 tracing::debug;
|
||||
|
||||
wiggle::from_witx!({
|
||||
witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
|
||||
ctx: WasiCtx,
|
||||
errors: { errno => Error },
|
||||
});
|
||||
|
||||
pub use types::Errno;
|
||||
pub type Result<T> = std::result::Result<T, Errno>;
|
||||
use types::Errno;
|
||||
|
||||
impl wiggle::GuestErrorType for Errno {
|
||||
fn success() -> Self {
|
||||
@@ -19,9 +17,54 @@ 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()
|
||||
}
|
||||
}
|
||||
|
||||
impl types::UserErrorConversion for WasiCtx {
|
||||
fn errno_from_error(&self, e: Error) -> Errno {
|
||||
debug!("Error: {:?}", e);
|
||||
e.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for Errno {
|
||||
fn from(e: Error) -> Errno {
|
||||
match e {
|
||||
Error::Guest(e) => e.into(),
|
||||
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,
|
||||
Error::Busy => Errno::Busy,
|
||||
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::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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,24 +88,6 @@ impl From<wiggle::GuestError> for Errno {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::convert::Infallible> for Errno {
|
||||
fn from(_err: std::convert::Infallible) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::num::TryFromIntError> for Errno {
|
||||
fn from(_err: std::num::TryFromIntError) -> Self {
|
||||
Self::Overflow
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::str::Utf8Error> for Errno {
|
||||
fn from(_err: std::str::Utf8Error) -> Self {
|
||||
Self::Ilseq
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::fs::FileType> for types::Filetype {
|
||||
fn from(ftype: std::fs::FileType) -> Self {
|
||||
if ftype.is_file() {
|
||||
|
||||
@@ -33,7 +33,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 {
|
||||
|
||||
Reference in New Issue
Block a user