Use wiggle "trappable error" to implement wasi-common (#5279)
* convert wasi-common from defining its own error to using wiggle trappable error * wasi-common impl crates: switch error strategy * wasmtime-wasi: error is trappable, and no longer requires UserErrorConversion * docs * typo * readdir: windows fixes * fix windows scheduler errors fun fact! the Send and Recv errors here that just had a `.context` on them were previously not being captured in the downcasting either. They need to be traps, and would have ended up that way by ommission, but you'd never actually know that by reading the code!
This commit is contained in:
@@ -138,6 +138,19 @@ impl WasiDir for Dir {
|
|||||||
&self,
|
&self,
|
||||||
cursor: ReaddirCursor,
|
cursor: ReaddirCursor,
|
||||||
) -> Result<Box<dyn Iterator<Item = Result<ReaddirEntity, Error>> + Send>, Error> {
|
) -> Result<Box<dyn Iterator<Item = Result<ReaddirEntity, Error>> + Send>, Error> {
|
||||||
|
// We need to keep a full-fidelity io Error around to check for a special failure mode
|
||||||
|
// on windows, but also this function can fail due to an illegal byte sequence in a
|
||||||
|
// filename, which we can't construct an io Error to represent.
|
||||||
|
enum ReaddirError {
|
||||||
|
Io(std::io::Error),
|
||||||
|
IllegalSequence,
|
||||||
|
}
|
||||||
|
impl From<std::io::Error> for ReaddirError {
|
||||||
|
fn from(e: std::io::Error) -> ReaddirError {
|
||||||
|
ReaddirError::Io(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// cap_std's read_dir does not include . and .., we should prepend these.
|
// cap_std's read_dir does not include . and .., we should prepend these.
|
||||||
// Why does the Ok contain a tuple? We can't construct a cap_std::fs::DirEntry, and we don't
|
// Why does the Ok contain a tuple? We can't construct a cap_std::fs::DirEntry, and we don't
|
||||||
// have enough info to make a ReaddirEntity yet.
|
// have enough info to make a ReaddirEntity yet.
|
||||||
@@ -145,7 +158,7 @@ impl WasiDir for Dir {
|
|||||||
let rd = vec![
|
let rd = vec![
|
||||||
{
|
{
|
||||||
let name = ".".to_owned();
|
let name = ".".to_owned();
|
||||||
Ok((FileType::Directory, dir_meta.ino(), name))
|
Ok::<_, ReaddirError>((FileType::Directory, dir_meta.ino(), name))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
let name = "..".to_owned();
|
let name = "..".to_owned();
|
||||||
@@ -163,26 +176,24 @@ impl WasiDir for Dir {
|
|||||||
let name = entry
|
let name = entry
|
||||||
.file_name()
|
.file_name()
|
||||||
.into_string()
|
.into_string()
|
||||||
.map_err(|_| Error::illegal_byte_sequence().context("filename"))?;
|
.map_err(|_| ReaddirError::IllegalSequence)?;
|
||||||
Ok((filetype, inode, name))
|
Ok((filetype, inode, name))
|
||||||
});
|
});
|
||||||
|
|
||||||
// On Windows, filter out files like `C:\DumpStack.log.tmp` which we
|
// On Windows, filter out files like `C:\DumpStack.log.tmp` which we
|
||||||
// can't get a full metadata for.
|
// can't get a full metadata for.
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let entries = entries.filter(|entry: &Result<_, wasi_common::Error>| {
|
let entries = entries.filter(|entry| {
|
||||||
use windows_sys::Win32::Foundation::{
|
use windows_sys::Win32::Foundation::{
|
||||||
ERROR_ACCESS_DENIED, ERROR_SHARING_VIOLATION,
|
ERROR_ACCESS_DENIED, ERROR_SHARING_VIOLATION,
|
||||||
};
|
};
|
||||||
if let Err(err) = entry {
|
if let Err(ReaddirError::Io(err)) = entry {
|
||||||
if let Some(err) = err.downcast_ref::<std::io::Error>() {
|
|
||||||
if err.raw_os_error() == Some(ERROR_SHARING_VIOLATION as i32)
|
if err.raw_os_error() == Some(ERROR_SHARING_VIOLATION as i32)
|
||||||
|| err.raw_os_error() == Some(ERROR_ACCESS_DENIED as i32)
|
|| err.raw_os_error() == Some(ERROR_ACCESS_DENIED as i32)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -197,7 +208,8 @@ impl WasiDir for Dir {
|
|||||||
inode,
|
inode,
|
||||||
name,
|
name,
|
||||||
}),
|
}),
|
||||||
Err(e) => Err(e),
|
Err(ReaddirError::Io(e)) => Err(e.into()),
|
||||||
|
Err(ReaddirError::IllegalSequence) => Err(Error::illegal_byte_sequence()),
|
||||||
})
|
})
|
||||||
.skip(u64::from(cursor) as usize);
|
.skip(u64::from(cursor) as usize);
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ pub async fn poll_oneoff<'a>(poll: &mut Poll<'a>) -> Result<(), Error> {
|
|||||||
match rustix::io::poll(&mut pollfds, poll_timeout) {
|
match rustix::io::poll(&mut pollfds, poll_timeout) {
|
||||||
Ok(ready) => break ready,
|
Ok(ready) => break ready,
|
||||||
Err(rustix::io::Errno::INTR) => continue,
|
Err(rustix::io::Errno::INTR) => continue,
|
||||||
Err(err) => return Err(err.into()),
|
Err(err) => return Err(std::io::Error::from(err).into()),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if ready > 0 {
|
if ready > 0 {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
// We suspect there are bugs in this scheduler, however, we have not
|
// We suspect there are bugs in this scheduler, however, we have not
|
||||||
// taken the time to improve it. See bug #2880.
|
// taken the time to improve it. See bug #2880.
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::mpsc::{self, Receiver, RecvTimeoutError, Sender, TryRecvError};
|
use std::sync::mpsc::{self, Receiver, RecvTimeoutError, Sender, TryRecvError};
|
||||||
@@ -73,7 +72,7 @@ pub async fn poll_oneoff_<'a>(
|
|||||||
if !stdin_read_subs.is_empty() {
|
if !stdin_read_subs.is_empty() {
|
||||||
let state = STDIN_POLL
|
let state = STDIN_POLL
|
||||||
.lock()
|
.lock()
|
||||||
.map_err(|_| Error::trap("failed to take lock of STDIN_POLL"))?
|
.map_err(|_| Error::trap(anyhow::Error::msg("failed to take lock of STDIN_POLL")))?
|
||||||
.poll(waitmode)?;
|
.poll(waitmode)?;
|
||||||
for readsub in stdin_read_subs.into_iter() {
|
for readsub in stdin_read_subs.into_iter() {
|
||||||
match state {
|
match state {
|
||||||
@@ -167,34 +166,36 @@ impl StdinPoll {
|
|||||||
// Clean up possibly unread result from previous poll.
|
// Clean up possibly unread result from previous poll.
|
||||||
Ok(_) | Err(TryRecvError::Empty) => {}
|
Ok(_) | Err(TryRecvError::Empty) => {}
|
||||||
Err(TryRecvError::Disconnected) => {
|
Err(TryRecvError::Disconnected) => {
|
||||||
return Err(Error::trap("StdinPoll notify_rx channel closed"))
|
return Err(Error::trap(anyhow::Error::msg(
|
||||||
|
"StdinPoll notify_rx channel closed",
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify the worker thread to poll stdin
|
// Notify the worker thread to poll stdin
|
||||||
self.request_tx
|
self.request_tx
|
||||||
.send(())
|
.send(())
|
||||||
.context("request_tx channel closed")?;
|
.map_err(|_| Error::trap(anyhow::Error::msg("request_tx channel closed")))?;
|
||||||
|
|
||||||
// Wait for the worker thread to send a readiness notification
|
// Wait for the worker thread to send a readiness notification
|
||||||
match wait_mode {
|
match wait_mode {
|
||||||
WaitMode::Timeout(timeout) => match self.notify_rx.recv_timeout(timeout) {
|
WaitMode::Timeout(timeout) => match self.notify_rx.recv_timeout(timeout) {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
Err(RecvTimeoutError::Timeout) => Ok(PollState::TimedOut),
|
Err(RecvTimeoutError::Timeout) => Ok(PollState::TimedOut),
|
||||||
Err(RecvTimeoutError::Disconnected) => {
|
Err(RecvTimeoutError::Disconnected) => Err(Error::trap(anyhow::Error::msg(
|
||||||
Err(Error::trap("StdinPoll notify_rx channel closed"))
|
"StdinPoll notify_rx channel closed",
|
||||||
}
|
))),
|
||||||
},
|
},
|
||||||
WaitMode::Infinite => self
|
WaitMode::Infinite => self
|
||||||
.notify_rx
|
.notify_rx
|
||||||
.recv()
|
.recv()
|
||||||
.context("StdinPoll notify_rx channel closed"),
|
.map_err(|_| Error::trap(anyhow::Error::msg("StdinPoll notify_rx channel closed"))),
|
||||||
WaitMode::Immediate => match self.notify_rx.try_recv() {
|
WaitMode::Immediate => match self.notify_rx.try_recv() {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
Err(TryRecvError::Empty) => Ok(PollState::NotReady),
|
Err(TryRecvError::Empty) => Ok(PollState::NotReady),
|
||||||
Err(TryRecvError::Disconnected) => {
|
Err(TryRecvError::Disconnected) => Err(Error::trap(anyhow::Error::msg(
|
||||||
Err(Error::trap("StdinPoll notify_rx channel closed"))
|
"StdinPoll notify_rx channel closed",
|
||||||
}
|
))),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,9 @@ macro_rules! wasi_file_write_impl {
|
|||||||
}
|
}
|
||||||
async fn write_vectored<'a>(&mut self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
|
async fn write_vectored<'a>(&mut self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
|
||||||
let n = (&*self.0.as_filelike_view::<File>()).write_vectored(bufs)?;
|
let n = (&*self.0.as_filelike_view::<File>()).write_vectored(bufs)?;
|
||||||
Ok(n.try_into().map_err(|c| Error::range().context(c))?)
|
Ok(n.try_into().map_err(|_| {
|
||||||
|
Error::range().context("converting write_vectored total length")
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
async fn write_vectored_at<'a>(
|
async fn write_vectored_at<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -1,145 +1,15 @@
|
|||||||
//! `wasi_common::Error` is now `anyhow::Error`.
|
//! wasi-common uses an [`Error`] type which represents either a preview 1 [`Errno`] enum, on
|
||||||
|
//! [`anyhow::Error`] for trapping execution.
|
||||||
//!
|
//!
|
||||||
//! Snapshots (right now only `wasi_common::snapshots::preview_1`) contains
|
//! The user can construct an [`Error`] out of an [`Errno`] using the `From`/`Into` traits.
|
||||||
//! all of the logic for transforming an `Error` into the snapshot's own
|
//! They may also use [`Error::trap`] to construct an error that traps execution. The contents
|
||||||
//! `Errno`. They may do so by downcasting the error into any of:
|
//! can be inspected with [`Error::downcast`] and [`Error::downcast_ref`]. Additional context
|
||||||
//! * `std::io::Error` - these are thrown by `std`, `cap_std`, etc for most of
|
//! can be provided with the [`Error::context`] method. This context is only observable with the
|
||||||
//! the operations WASI is concerned with.
|
//! `Display` and `Debug` impls of the error.
|
||||||
//! * `wasi_common::ErrorKind` - these are a subset of the Errnos, and are
|
|
||||||
//! constructed directly by wasi-common or an impl rather than coming from the
|
|
||||||
//! OS or some library which doesn't know about WASI.
|
|
||||||
//! * `wiggle::GuestError`
|
|
||||||
//! * `std::num::TryFromIntError`
|
|
||||||
//! * `std::str::Utf8Error`
|
|
||||||
//! and then applying specialized logic to translate each of those into
|
|
||||||
//! `Errno`s.
|
|
||||||
//!
|
|
||||||
//! The `wasi_common::ErrorExt` trait provides human-friendly constructors for
|
|
||||||
//! the `wasi_common::ErrorKind` variants .
|
|
||||||
//!
|
|
||||||
//! If you throw an error that does not downcast to one of those, it will turn
|
|
||||||
//! into a `wiggle::Trap` and terminate execution.
|
|
||||||
//!
|
|
||||||
//! The real value of using `anyhow::Error` here is being able to use
|
|
||||||
//! `anyhow::Result::context` to aid in debugging of errors.
|
|
||||||
|
|
||||||
pub use anyhow::{Context, Error};
|
pub use crate::snapshots::preview_1::error::{Errno, Error, ErrorExt};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// Internal error type for the `wasi-common` crate.
|
|
||||||
///
|
|
||||||
/// This Contains variants of the WASI `$errno` type that are used internally
|
|
||||||
/// by the crate, and which aren't one-to-one with a `std::io::ErrorKind`
|
|
||||||
/// error.
|
|
||||||
///
|
|
||||||
/// When the Rust [io_error_more] feature is stabilized, that will enable
|
|
||||||
/// us to replace several more of these codes with `std::io::ErrorKind` codes.
|
|
||||||
///
|
|
||||||
/// [io_error_more]: https://doc.rust-lang.org/beta/unstable-book/library-features/io-error-more.html
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, thiserror::Error)]
|
|
||||||
#[non_exhaustive]
|
|
||||||
pub enum ErrorKind {
|
|
||||||
/// Errno::TooBig: Argument list too long
|
|
||||||
#[error("TooBig: Argument list too long")]
|
|
||||||
TooBig,
|
|
||||||
/// Errno::Badf: Bad file descriptor
|
|
||||||
#[error("Badf: Bad file descriptor")]
|
|
||||||
Badf,
|
|
||||||
/// Errno::Ilseq: Illegal byte sequence
|
|
||||||
#[error("Ilseq: Illegal byte sequence")]
|
|
||||||
Ilseq,
|
|
||||||
/// Errno::Io: I/O error
|
|
||||||
#[error("Io: I/O error")]
|
|
||||||
Io,
|
|
||||||
/// Errno::Nametoolong: Filename too long
|
|
||||||
#[error("Nametoolong: Filename too long")]
|
|
||||||
Nametoolong,
|
|
||||||
/// 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::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::Range: Result too large
|
|
||||||
#[error("Range: Result too large")]
|
|
||||||
Range,
|
|
||||||
/// Errno::Spipe: Invalid seek
|
|
||||||
#[error("Spipe: Invalid seek")]
|
|
||||||
Spipe,
|
|
||||||
/// Errno::Perm: Permission denied
|
|
||||||
#[error("Permission denied")]
|
|
||||||
Perm,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ErrorExt {
|
|
||||||
fn trap(msg: impl Into<String>) -> Self;
|
|
||||||
fn not_found() -> Self;
|
|
||||||
fn too_big() -> Self;
|
|
||||||
fn badf() -> Self;
|
|
||||||
fn exist() -> Self;
|
|
||||||
fn illegal_byte_sequence() -> Self;
|
|
||||||
fn invalid_argument() -> Self;
|
|
||||||
fn io() -> Self;
|
|
||||||
fn name_too_long() -> Self;
|
|
||||||
fn not_dir() -> Self;
|
|
||||||
fn not_supported() -> Self;
|
|
||||||
fn overflow() -> Self;
|
|
||||||
fn range() -> Self;
|
|
||||||
fn seek_pipe() -> Self;
|
|
||||||
fn perm() -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ErrorExt for Error {
|
|
||||||
fn trap(msg: impl Into<String>) -> Self {
|
|
||||||
anyhow::anyhow!(msg.into())
|
|
||||||
}
|
|
||||||
fn not_found() -> Self {
|
|
||||||
std::io::Error::from(std::io::ErrorKind::NotFound).into()
|
|
||||||
}
|
|
||||||
fn too_big() -> Self {
|
|
||||||
ErrorKind::TooBig.into()
|
|
||||||
}
|
|
||||||
fn badf() -> Self {
|
|
||||||
ErrorKind::Badf.into()
|
|
||||||
}
|
|
||||||
fn exist() -> Self {
|
|
||||||
std::io::Error::from(std::io::ErrorKind::AlreadyExists).into()
|
|
||||||
}
|
|
||||||
fn illegal_byte_sequence() -> Self {
|
|
||||||
ErrorKind::Ilseq.into()
|
|
||||||
}
|
|
||||||
fn invalid_argument() -> Self {
|
|
||||||
std::io::Error::from(std::io::ErrorKind::InvalidInput).into()
|
|
||||||
}
|
|
||||||
fn io() -> Self {
|
|
||||||
ErrorKind::Io.into()
|
|
||||||
}
|
|
||||||
fn name_too_long() -> Self {
|
|
||||||
ErrorKind::Nametoolong.into()
|
|
||||||
}
|
|
||||||
fn not_dir() -> Self {
|
|
||||||
ErrorKind::Notdir.into()
|
|
||||||
}
|
|
||||||
fn not_supported() -> Self {
|
|
||||||
ErrorKind::Notsup.into()
|
|
||||||
}
|
|
||||||
fn overflow() -> Self {
|
|
||||||
ErrorKind::Overflow.into()
|
|
||||||
}
|
|
||||||
fn range() -> Self {
|
|
||||||
ErrorKind::Range.into()
|
|
||||||
}
|
|
||||||
fn seek_pipe() -> Self {
|
|
||||||
ErrorKind::Spipe.into()
|
|
||||||
}
|
|
||||||
fn perm() -> Self {
|
|
||||||
ErrorKind::Perm.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An error returned from the `proc_exit` host syscall.
|
/// An error returned from the `proc_exit` host syscall.
|
||||||
///
|
///
|
||||||
/// Embedders can test if an error returned from wasm is this error, in which
|
/// Embedders can test if an error returned from wasm is this error, in which
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ pub use cap_rand::RngCore;
|
|||||||
pub use clocks::{SystemTimeSpec, WasiClocks, WasiMonotonicClock, WasiSystemClock};
|
pub use clocks::{SystemTimeSpec, WasiClocks, WasiMonotonicClock, WasiSystemClock};
|
||||||
pub use ctx::WasiCtx;
|
pub use ctx::WasiCtx;
|
||||||
pub use dir::WasiDir;
|
pub use dir::WasiDir;
|
||||||
pub use error::{Context, Error, ErrorExt, ErrorKind, I32Exit};
|
pub use error::{Error, ErrorExt, I32Exit};
|
||||||
pub use file::WasiFile;
|
pub use file::WasiFile;
|
||||||
pub use sched::{Poll, WasiSched};
|
pub use sched::{Poll, WasiSched};
|
||||||
pub use string_array::StringArrayError;
|
pub use string_array::StringArrayError;
|
||||||
|
|||||||
@@ -5,42 +5,92 @@ use crate::sched::{
|
|||||||
};
|
};
|
||||||
use crate::snapshots::preview_1::types as snapshot1_types;
|
use crate::snapshots::preview_1::types as snapshot1_types;
|
||||||
use crate::snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1 as Snapshot1;
|
use crate::snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1 as Snapshot1;
|
||||||
use crate::{Error, ErrorExt, WasiCtx};
|
use crate::{ErrorExt, WasiCtx};
|
||||||
use anyhow::Result;
|
|
||||||
use cap_std::time::Duration;
|
use cap_std::time::Duration;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::io::{IoSlice, IoSliceMut};
|
use std::io::{IoSlice, IoSliceMut};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use tracing::debug;
|
|
||||||
use wiggle::GuestPtr;
|
use wiggle::GuestPtr;
|
||||||
|
|
||||||
wiggle::from_witx!({
|
wiggle::from_witx!({
|
||||||
witx: ["$WASI_ROOT/phases/old/snapshot_0/witx/wasi_unstable.witx"],
|
witx: ["$WASI_ROOT/phases/old/snapshot_0/witx/wasi_unstable.witx"],
|
||||||
errors: { errno => Error },
|
errors: { errno => trappable Error },
|
||||||
async: *,
|
async: *,
|
||||||
wasmtime: false,
|
wasmtime: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
use types::Error;
|
||||||
|
|
||||||
|
impl ErrorExt for Error {
|
||||||
|
fn not_found() -> Self {
|
||||||
|
types::Errno::Noent.into()
|
||||||
|
}
|
||||||
|
fn too_big() -> Self {
|
||||||
|
types::Errno::TooBig.into()
|
||||||
|
}
|
||||||
|
fn badf() -> Self {
|
||||||
|
types::Errno::Badf.into()
|
||||||
|
}
|
||||||
|
fn exist() -> Self {
|
||||||
|
types::Errno::Exist.into()
|
||||||
|
}
|
||||||
|
fn illegal_byte_sequence() -> Self {
|
||||||
|
types::Errno::Ilseq.into()
|
||||||
|
}
|
||||||
|
fn invalid_argument() -> Self {
|
||||||
|
types::Errno::Inval.into()
|
||||||
|
}
|
||||||
|
fn io() -> Self {
|
||||||
|
types::Errno::Io.into()
|
||||||
|
}
|
||||||
|
fn name_too_long() -> Self {
|
||||||
|
types::Errno::Nametoolong.into()
|
||||||
|
}
|
||||||
|
fn not_dir() -> Self {
|
||||||
|
types::Errno::Notdir.into()
|
||||||
|
}
|
||||||
|
fn not_supported() -> Self {
|
||||||
|
types::Errno::Notsup.into()
|
||||||
|
}
|
||||||
|
fn overflow() -> Self {
|
||||||
|
types::Errno::Overflow.into()
|
||||||
|
}
|
||||||
|
fn range() -> Self {
|
||||||
|
types::Errno::Range.into()
|
||||||
|
}
|
||||||
|
fn seek_pipe() -> Self {
|
||||||
|
types::Errno::Spipe.into()
|
||||||
|
}
|
||||||
|
fn perm() -> Self {
|
||||||
|
types::Errno::Perm.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl wiggle::GuestErrorType for types::Errno {
|
impl wiggle::GuestErrorType for types::Errno {
|
||||||
fn success() -> Self {
|
fn success() -> Self {
|
||||||
Self::Success
|
Self::Success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl types::UserErrorConversion for WasiCtx {
|
impl From<wiggle::GuestError> for Error {
|
||||||
fn errno_from_error(&mut self, e: Error) -> Result<types::Errno> {
|
fn from(err: wiggle::GuestError) -> Error {
|
||||||
debug!("Error: {:?}", e);
|
snapshot1_types::Error::from(err).into()
|
||||||
let errno = e.try_into()?;
|
|
||||||
Ok(errno)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Error> for types::Errno {
|
impl From<snapshot1_types::Error> for Error {
|
||||||
type Error = Error;
|
fn from(error: snapshot1_types::Error) -> Error {
|
||||||
fn try_from(e: Error) -> Result<types::Errno, Error> {
|
match error.downcast() {
|
||||||
let snapshot1_errno: snapshot1_types::Errno = e.try_into()?;
|
Ok(errno) => Error::from(types::Errno::from(errno)),
|
||||||
Ok(snapshot1_errno.into())
|
Err(trap) => Error::trap(trap),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::num::TryFromIntError> for Error {
|
||||||
|
fn from(_err: std::num::TryFromIntError) -> Error {
|
||||||
|
types::Errno::Overflow.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,11 +393,13 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
argv: &GuestPtr<'a, GuestPtr<'a, u8>>,
|
argv: &GuestPtr<'a, GuestPtr<'a, u8>>,
|
||||||
argv_buf: &GuestPtr<'a, u8>,
|
argv_buf: &GuestPtr<'a, u8>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::args_get(self, argv, argv_buf).await
|
Snapshot1::args_get(self, argv, argv_buf).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn args_sizes_get(&mut self) -> Result<(types::Size, types::Size), Error> {
|
async fn args_sizes_get(&mut self) -> Result<(types::Size, types::Size), Error> {
|
||||||
Snapshot1::args_sizes_get(self).await
|
let s = Snapshot1::args_sizes_get(self).await?;
|
||||||
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn environ_get<'a>(
|
async fn environ_get<'a>(
|
||||||
@@ -355,15 +407,18 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
environ: &GuestPtr<'a, GuestPtr<'a, u8>>,
|
environ: &GuestPtr<'a, GuestPtr<'a, u8>>,
|
||||||
environ_buf: &GuestPtr<'a, u8>,
|
environ_buf: &GuestPtr<'a, u8>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::environ_get(self, environ, environ_buf).await
|
Snapshot1::environ_get(self, environ, environ_buf).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn environ_sizes_get(&mut self) -> Result<(types::Size, types::Size), Error> {
|
async fn environ_sizes_get(&mut self) -> Result<(types::Size, types::Size), Error> {
|
||||||
Snapshot1::environ_sizes_get(self).await
|
let s = Snapshot1::environ_sizes_get(self).await?;
|
||||||
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn clock_res_get(&mut self, id: types::Clockid) -> Result<types::Timestamp, Error> {
|
async fn clock_res_get(&mut self, id: types::Clockid) -> Result<types::Timestamp, Error> {
|
||||||
Snapshot1::clock_res_get(self, id.into()).await
|
let t = Snapshot1::clock_res_get(self, id.into()).await?;
|
||||||
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn clock_time_get(
|
async fn clock_time_get(
|
||||||
@@ -371,7 +426,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
id: types::Clockid,
|
id: types::Clockid,
|
||||||
precision: types::Timestamp,
|
precision: types::Timestamp,
|
||||||
) -> Result<types::Timestamp, Error> {
|
) -> Result<types::Timestamp, Error> {
|
||||||
Snapshot1::clock_time_get(self, id.into(), precision).await
|
let t = Snapshot1::clock_time_get(self, id.into(), precision).await?;
|
||||||
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_advise(
|
async fn fd_advise(
|
||||||
@@ -381,7 +437,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
len: types::Filesize,
|
len: types::Filesize,
|
||||||
advice: types::Advice,
|
advice: types::Advice,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::fd_advise(self, fd.into(), offset, len, advice.into()).await
|
Snapshot1::fd_advise(self, fd.into(), offset, len, advice.into()).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_allocate(
|
async fn fd_allocate(
|
||||||
@@ -390,15 +447,18 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
offset: types::Filesize,
|
offset: types::Filesize,
|
||||||
len: types::Filesize,
|
len: types::Filesize,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::fd_allocate(self, fd.into(), offset, len).await
|
Snapshot1::fd_allocate(self, fd.into(), offset, len).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_close(&mut self, fd: types::Fd) -> Result<(), Error> {
|
async fn fd_close(&mut self, fd: types::Fd) -> Result<(), Error> {
|
||||||
Snapshot1::fd_close(self, fd.into()).await
|
Snapshot1::fd_close(self, fd.into()).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_datasync(&mut self, fd: types::Fd) -> Result<(), Error> {
|
async fn fd_datasync(&mut self, fd: types::Fd) -> Result<(), Error> {
|
||||||
Snapshot1::fd_datasync(self, fd.into()).await
|
Snapshot1::fd_datasync(self, fd.into()).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_fdstat_get(&mut self, fd: types::Fd) -> Result<types::Fdstat, Error> {
|
async fn fd_fdstat_get(&mut self, fd: types::Fd) -> Result<types::Fdstat, Error> {
|
||||||
@@ -410,7 +470,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
fd: types::Fd,
|
fd: types::Fd,
|
||||||
flags: types::Fdflags,
|
flags: types::Fdflags,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::fd_fdstat_set_flags(self, fd.into(), flags.into()).await
|
Snapshot1::fd_fdstat_set_flags(self, fd.into(), flags.into()).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_fdstat_set_rights(
|
async fn fd_fdstat_set_rights(
|
||||||
@@ -425,7 +486,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
fs_rights_base.into(),
|
fs_rights_base.into(),
|
||||||
fs_rights_inheriting.into(),
|
fs_rights_inheriting.into(),
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_filestat_get(&mut self, fd: types::Fd) -> Result<types::Filestat, Error> {
|
async fn fd_filestat_get(&mut self, fd: types::Fd) -> Result<types::Filestat, Error> {
|
||||||
@@ -437,7 +499,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
fd: types::Fd,
|
fd: types::Fd,
|
||||||
size: types::Filesize,
|
size: types::Filesize,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::fd_filestat_set_size(self, fd.into(), size).await
|
Snapshot1::fd_filestat_set_size(self, fd.into(), size).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_filestat_set_times(
|
async fn fd_filestat_set_times(
|
||||||
@@ -447,7 +510,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
mtim: types::Timestamp,
|
mtim: types::Timestamp,
|
||||||
fst_flags: types::Fstflags,
|
fst_flags: types::Fstflags,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::fd_filestat_set_times(self, fd.into(), atim, mtim, fst_flags.into()).await
|
Snapshot1::fd_filestat_set_times(self, fd.into(), atim, mtim, fst_flags.into()).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE on fd_read, fd_pread, fd_write, fd_pwrite implementations:
|
// NOTE on fd_read, fd_pread, fd_write, fd_pwrite implementations:
|
||||||
@@ -594,11 +658,13 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
path: &GuestPtr<'a, u8>,
|
path: &GuestPtr<'a, u8>,
|
||||||
path_max_len: types::Size,
|
path_max_len: types::Size,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::fd_prestat_dir_name(self, fd.into(), path, path_max_len).await
|
Snapshot1::fd_prestat_dir_name(self, fd.into(), path, path_max_len).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_renumber(&mut self, from: types::Fd, to: types::Fd) -> Result<(), Error> {
|
async fn fd_renumber(&mut self, from: types::Fd, to: types::Fd) -> Result<(), Error> {
|
||||||
Snapshot1::fd_renumber(self, from.into(), to.into()).await
|
Snapshot1::fd_renumber(self, from.into(), to.into()).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_seek(
|
async fn fd_seek(
|
||||||
@@ -607,15 +673,16 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
offset: types::Filedelta,
|
offset: types::Filedelta,
|
||||||
whence: types::Whence,
|
whence: types::Whence,
|
||||||
) -> Result<types::Filesize, Error> {
|
) -> Result<types::Filesize, Error> {
|
||||||
Snapshot1::fd_seek(self, fd.into(), offset, whence.into()).await
|
Ok(Snapshot1::fd_seek(self, fd.into(), offset, whence.into()).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_sync(&mut self, fd: types::Fd) -> Result<(), Error> {
|
async fn fd_sync(&mut self, fd: types::Fd) -> Result<(), Error> {
|
||||||
Snapshot1::fd_sync(self, fd.into()).await
|
Snapshot1::fd_sync(self, fd.into()).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_tell(&mut self, fd: types::Fd) -> Result<types::Filesize, Error> {
|
async fn fd_tell(&mut self, fd: types::Fd) -> Result<types::Filesize, Error> {
|
||||||
Snapshot1::fd_tell(self, fd.into()).await
|
Ok(Snapshot1::fd_tell(self, fd.into()).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fd_readdir<'a>(
|
async fn fd_readdir<'a>(
|
||||||
@@ -625,7 +692,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
buf_len: types::Size,
|
buf_len: types::Size,
|
||||||
cookie: types::Dircookie,
|
cookie: types::Dircookie,
|
||||||
) -> Result<types::Size, Error> {
|
) -> Result<types::Size, Error> {
|
||||||
Snapshot1::fd_readdir(self, fd.into(), buf, buf_len, cookie).await
|
Ok(Snapshot1::fd_readdir(self, fd.into(), buf, buf_len, cookie).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn path_create_directory<'a>(
|
async fn path_create_directory<'a>(
|
||||||
@@ -633,7 +700,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
dirfd: types::Fd,
|
dirfd: types::Fd,
|
||||||
path: &GuestPtr<'a, str>,
|
path: &GuestPtr<'a, str>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::path_create_directory(self, dirfd.into(), path).await
|
Snapshot1::path_create_directory(self, dirfd.into(), path).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn path_filestat_get<'a>(
|
async fn path_filestat_get<'a>(
|
||||||
@@ -667,7 +735,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
mtim,
|
mtim,
|
||||||
fst_flags.into(),
|
fst_flags.into(),
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn path_link<'a>(
|
async fn path_link<'a>(
|
||||||
@@ -686,7 +755,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
target_fd.into(),
|
target_fd.into(),
|
||||||
target_path,
|
target_path,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn path_open<'a>(
|
async fn path_open<'a>(
|
||||||
@@ -720,7 +790,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
buf: &GuestPtr<'a, u8>,
|
buf: &GuestPtr<'a, u8>,
|
||||||
buf_len: types::Size,
|
buf_len: types::Size,
|
||||||
) -> Result<types::Size, Error> {
|
) -> Result<types::Size, Error> {
|
||||||
Snapshot1::path_readlink(self, dirfd.into(), path, buf, buf_len).await
|
Ok(Snapshot1::path_readlink(self, dirfd.into(), path, buf, buf_len).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn path_remove_directory<'a>(
|
async fn path_remove_directory<'a>(
|
||||||
@@ -728,7 +798,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
dirfd: types::Fd,
|
dirfd: types::Fd,
|
||||||
path: &GuestPtr<'a, str>,
|
path: &GuestPtr<'a, str>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::path_remove_directory(self, dirfd.into(), path).await
|
Snapshot1::path_remove_directory(self, dirfd.into(), path).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn path_rename<'a>(
|
async fn path_rename<'a>(
|
||||||
@@ -738,7 +809,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
dest_fd: types::Fd,
|
dest_fd: types::Fd,
|
||||||
dest_path: &GuestPtr<'a, str>,
|
dest_path: &GuestPtr<'a, str>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::path_rename(self, src_fd.into(), src_path, dest_fd.into(), dest_path).await
|
Snapshot1::path_rename(self, src_fd.into(), src_path, dest_fd.into(), dest_path).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn path_symlink<'a>(
|
async fn path_symlink<'a>(
|
||||||
@@ -747,7 +819,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
dirfd: types::Fd,
|
dirfd: types::Fd,
|
||||||
dest_path: &GuestPtr<'a, str>,
|
dest_path: &GuestPtr<'a, str>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::path_symlink(self, src_path, dirfd.into(), dest_path).await
|
Snapshot1::path_symlink(self, src_path, dirfd.into(), dest_path).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn path_unlink_file<'a>(
|
async fn path_unlink_file<'a>(
|
||||||
@@ -755,7 +828,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
dirfd: types::Fd,
|
dirfd: types::Fd,
|
||||||
path: &GuestPtr<'a, str>,
|
path: &GuestPtr<'a, str>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::path_unlink_file(self, dirfd.into(), path).await
|
Snapshot1::path_unlink_file(self, dirfd.into(), path).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE on poll_oneoff implementation:
|
// NOTE on poll_oneoff implementation:
|
||||||
@@ -901,7 +975,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
},
|
},
|
||||||
Err(e) => types::Event {
|
Err(e) => types::Event {
|
||||||
userdata,
|
userdata,
|
||||||
error: e.try_into().expect("non-trapping"),
|
error: types::Errno::from(e.downcast().map_err(Error::trap)?),
|
||||||
type_,
|
type_,
|
||||||
fd_readwrite: fd_readwrite_empty(),
|
fd_readwrite: fd_readwrite_empty(),
|
||||||
},
|
},
|
||||||
@@ -921,7 +995,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
},
|
},
|
||||||
Err(e) => types::Event {
|
Err(e) => types::Event {
|
||||||
userdata,
|
userdata,
|
||||||
error: e.try_into()?,
|
error: types::Errno::from(e.downcast().map_err(Error::trap)?),
|
||||||
type_,
|
type_,
|
||||||
fd_readwrite: fd_readwrite_empty(),
|
fd_readwrite: fd_readwrite_empty(),
|
||||||
},
|
},
|
||||||
@@ -933,7 +1007,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
userdata,
|
userdata,
|
||||||
error: match r {
|
error: match r {
|
||||||
Ok(()) => types::Errno::Success,
|
Ok(()) => types::Errno::Success,
|
||||||
Err(e) => e.try_into()?,
|
Err(e) => types::Errno::from(e.downcast().map_err(Error::trap)?),
|
||||||
},
|
},
|
||||||
type_,
|
type_,
|
||||||
fd_readwrite: fd_readwrite_empty(),
|
fd_readwrite: fd_readwrite_empty(),
|
||||||
@@ -950,11 +1024,12 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn proc_raise(&mut self, _sig: types::Signal) -> Result<(), Error> {
|
async fn proc_raise(&mut self, _sig: types::Signal) -> Result<(), Error> {
|
||||||
Err(Error::trap("proc_raise unsupported"))
|
Err(Error::trap(anyhow::Error::msg("proc_raise unsupported")))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sched_yield(&mut self) -> Result<(), Error> {
|
async fn sched_yield(&mut self) -> Result<(), Error> {
|
||||||
Snapshot1::sched_yield(self).await
|
Snapshot1::sched_yield(self).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn random_get<'a>(
|
async fn random_get<'a>(
|
||||||
@@ -962,7 +1037,8 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
buf: &GuestPtr<'a, u8>,
|
buf: &GuestPtr<'a, u8>,
|
||||||
buf_len: types::Size,
|
buf_len: types::Size,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Snapshot1::random_get(self, buf, buf_len).await
|
Snapshot1::random_get(self, buf, buf_len).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sock_recv<'a>(
|
async fn sock_recv<'a>(
|
||||||
@@ -971,7 +1047,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
_ri_data: &types::IovecArray<'a>,
|
_ri_data: &types::IovecArray<'a>,
|
||||||
_ri_flags: types::Riflags,
|
_ri_flags: types::Riflags,
|
||||||
) -> Result<(types::Size, types::Roflags), Error> {
|
) -> Result<(types::Size, types::Roflags), Error> {
|
||||||
Err(Error::trap("sock_recv unsupported"))
|
Err(Error::trap(anyhow::Error::msg("sock_recv unsupported")))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sock_send<'a>(
|
async fn sock_send<'a>(
|
||||||
@@ -980,11 +1056,11 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
|
|||||||
_si_data: &types::CiovecArray<'a>,
|
_si_data: &types::CiovecArray<'a>,
|
||||||
_si_flags: types::Siflags,
|
_si_flags: types::Siflags,
|
||||||
) -> Result<types::Size, Error> {
|
) -> Result<types::Size, Error> {
|
||||||
Err(Error::trap("sock_send unsupported"))
|
Err(Error::trap(anyhow::Error::msg("sock_send unsupported")))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sock_shutdown(&mut self, _fd: types::Fd, _how: types::Sdflags) -> Result<(), Error> {
|
async fn sock_shutdown(&mut self, _fd: types::Fd, _how: types::Sdflags) -> Result<(), Error> {
|
||||||
Err(Error::trap("sock_shutdown unsupported"))
|
Err(Error::trap(anyhow::Error::msg("sock_shutdown unsupported")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,19 +8,20 @@ use crate::{
|
|||||||
subscription::{RwEventFlags, SubscriptionResult},
|
subscription::{RwEventFlags, SubscriptionResult},
|
||||||
Poll, Userdata,
|
Poll, Userdata,
|
||||||
},
|
},
|
||||||
Error, ErrorExt, ErrorKind, I32Exit, SystemTimeSpec, WasiCtx,
|
I32Exit, SystemTimeSpec, WasiCtx,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context, Result};
|
|
||||||
use cap_std::time::{Duration, SystemClock};
|
use cap_std::time::{Duration, SystemClock};
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::io::{IoSlice, IoSliceMut};
|
use std::io::{IoSlice, IoSliceMut};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use tracing::debug;
|
|
||||||
use wiggle::GuestPtr;
|
use wiggle::GuestPtr;
|
||||||
|
|
||||||
|
pub mod error;
|
||||||
|
use error::{Error, ErrorExt};
|
||||||
|
|
||||||
wiggle::from_witx!({
|
wiggle::from_witx!({
|
||||||
witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
|
witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
|
||||||
errors: { errno => Error },
|
errors: { errno => trappable Error },
|
||||||
// Note: not every function actually needs to be async, however, nearly all of them do, and
|
// Note: not every function actually needs to be async, however, nearly all of them do, and
|
||||||
// keeping that set the same in this macro and the wasmtime_wiggle / lucet_wiggle macros is
|
// keeping that set the same in this macro and the wasmtime_wiggle / lucet_wiggle macros is
|
||||||
// tedious, and there is no cost to having a sync function be async in this case.
|
// tedious, and there is no cost to having a sync function be async in this case.
|
||||||
@@ -34,235 +35,6 @@ impl wiggle::GuestErrorType for types::Errno {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl types::UserErrorConversion for WasiCtx {
|
|
||||||
fn errno_from_error(&mut self, e: Error) -> Result<types::Errno> {
|
|
||||||
debug!("Error: {:?}", e);
|
|
||||||
let errno = e.try_into()?;
|
|
||||||
Ok(errno)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<Error> for types::Errno {
|
|
||||||
type Error = Error;
|
|
||||||
fn try_from(e: Error) -> Result<types::Errno, Error> {
|
|
||||||
use types::Errno;
|
|
||||||
if e.is::<ErrorKind>() {
|
|
||||||
let e = e.downcast::<ErrorKind>().unwrap();
|
|
||||||
Ok(e.into())
|
|
||||||
} else if e.is::<std::io::Error>() {
|
|
||||||
let e = e.downcast::<std::io::Error>().unwrap();
|
|
||||||
e.try_into()
|
|
||||||
} else if e.is::<wiggle::GuestError>() {
|
|
||||||
let e = e.downcast::<wiggle::GuestError>().unwrap();
|
|
||||||
Ok(e.into())
|
|
||||||
} else if e.is::<std::num::TryFromIntError>() {
|
|
||||||
Ok(Errno::Overflow)
|
|
||||||
} else if e.is::<std::str::Utf8Error>() {
|
|
||||||
Ok(Errno::Ilseq)
|
|
||||||
} else {
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ErrorKind> for types::Errno {
|
|
||||||
fn from(e: ErrorKind) -> types::Errno {
|
|
||||||
use types::Errno;
|
|
||||||
match e {
|
|
||||||
ErrorKind::TooBig => Errno::TooBig,
|
|
||||||
ErrorKind::Badf => Errno::Badf,
|
|
||||||
ErrorKind::Ilseq => Errno::Ilseq,
|
|
||||||
ErrorKind::Io => Errno::Io,
|
|
||||||
ErrorKind::Nametoolong => Errno::Nametoolong,
|
|
||||||
ErrorKind::Notdir => Errno::Notdir,
|
|
||||||
ErrorKind::Notsup => Errno::Notsup,
|
|
||||||
ErrorKind::Overflow => Errno::Overflow,
|
|
||||||
ErrorKind::Range => Errno::Range,
|
|
||||||
ErrorKind::Spipe => Errno::Spipe,
|
|
||||||
ErrorKind::Perm => Errno::Perm,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<wiggle::GuestError> for types::Errno {
|
|
||||||
fn from(err: wiggle::GuestError) -> Self {
|
|
||||||
use wiggle::GuestError::*;
|
|
||||||
match err {
|
|
||||||
InvalidFlagValue { .. } => Self::Inval,
|
|
||||||
InvalidEnumValue { .. } => Self::Inval,
|
|
||||||
PtrOverflow { .. } => Self::Fault,
|
|
||||||
PtrOutOfBounds { .. } => Self::Fault,
|
|
||||||
PtrNotAligned { .. } => Self::Inval,
|
|
||||||
PtrBorrowed { .. } => Self::Fault,
|
|
||||||
InvalidUtf8 { .. } => Self::Ilseq,
|
|
||||||
TryFromIntError { .. } => Self::Overflow,
|
|
||||||
InFunc { err, .. } => types::Errno::from(*err),
|
|
||||||
SliceLengthsDiffer { .. } => Self::Fault,
|
|
||||||
BorrowCheckerOutOfHandles { .. } => Self::Fault,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<std::io::Error> for types::Errno {
|
|
||||||
type Error = Error;
|
|
||||||
fn try_from(err: std::io::Error) -> Result<types::Errno, Error> {
|
|
||||||
#[cfg(unix)]
|
|
||||||
fn raw_error_code(err: &std::io::Error) -> Option<types::Errno> {
|
|
||||||
use rustix::io::Errno;
|
|
||||||
match Errno::from_io_error(err) {
|
|
||||||
Some(Errno::AGAIN) => Some(types::Errno::Again),
|
|
||||||
Some(Errno::PIPE) => Some(types::Errno::Pipe),
|
|
||||||
Some(Errno::PERM) => Some(types::Errno::Perm),
|
|
||||||
Some(Errno::NOENT) => Some(types::Errno::Noent),
|
|
||||||
Some(Errno::NOMEM) => Some(types::Errno::Nomem),
|
|
||||||
Some(Errno::TOOBIG) => Some(types::Errno::TooBig),
|
|
||||||
Some(Errno::IO) => Some(types::Errno::Io),
|
|
||||||
Some(Errno::BADF) => Some(types::Errno::Badf),
|
|
||||||
Some(Errno::BUSY) => Some(types::Errno::Busy),
|
|
||||||
Some(Errno::ACCESS) => Some(types::Errno::Acces),
|
|
||||||
Some(Errno::FAULT) => Some(types::Errno::Fault),
|
|
||||||
Some(Errno::NOTDIR) => Some(types::Errno::Notdir),
|
|
||||||
Some(Errno::ISDIR) => Some(types::Errno::Isdir),
|
|
||||||
Some(Errno::INVAL) => Some(types::Errno::Inval),
|
|
||||||
Some(Errno::EXIST) => Some(types::Errno::Exist),
|
|
||||||
Some(Errno::FBIG) => Some(types::Errno::Fbig),
|
|
||||||
Some(Errno::NOSPC) => Some(types::Errno::Nospc),
|
|
||||||
Some(Errno::SPIPE) => Some(types::Errno::Spipe),
|
|
||||||
Some(Errno::MFILE) => Some(types::Errno::Mfile),
|
|
||||||
Some(Errno::MLINK) => Some(types::Errno::Mlink),
|
|
||||||
Some(Errno::NAMETOOLONG) => Some(types::Errno::Nametoolong),
|
|
||||||
Some(Errno::NFILE) => Some(types::Errno::Nfile),
|
|
||||||
Some(Errno::NOTEMPTY) => Some(types::Errno::Notempty),
|
|
||||||
Some(Errno::LOOP) => Some(types::Errno::Loop),
|
|
||||||
Some(Errno::OVERFLOW) => Some(types::Errno::Overflow),
|
|
||||||
Some(Errno::ILSEQ) => Some(types::Errno::Ilseq),
|
|
||||||
Some(Errno::NOTSUP) => Some(types::Errno::Notsup),
|
|
||||||
Some(Errno::ADDRINUSE) => Some(types::Errno::Addrinuse),
|
|
||||||
Some(Errno::CANCELED) => Some(types::Errno::Canceled),
|
|
||||||
Some(Errno::ADDRNOTAVAIL) => Some(types::Errno::Addrnotavail),
|
|
||||||
Some(Errno::AFNOSUPPORT) => Some(types::Errno::Afnosupport),
|
|
||||||
Some(Errno::ALREADY) => Some(types::Errno::Already),
|
|
||||||
Some(Errno::CONNABORTED) => Some(types::Errno::Connaborted),
|
|
||||||
Some(Errno::CONNREFUSED) => Some(types::Errno::Connrefused),
|
|
||||||
Some(Errno::CONNRESET) => Some(types::Errno::Connreset),
|
|
||||||
Some(Errno::DESTADDRREQ) => Some(types::Errno::Destaddrreq),
|
|
||||||
Some(Errno::DQUOT) => Some(types::Errno::Dquot),
|
|
||||||
Some(Errno::HOSTUNREACH) => Some(types::Errno::Hostunreach),
|
|
||||||
Some(Errno::INPROGRESS) => Some(types::Errno::Inprogress),
|
|
||||||
Some(Errno::INTR) => Some(types::Errno::Intr),
|
|
||||||
Some(Errno::ISCONN) => Some(types::Errno::Isconn),
|
|
||||||
Some(Errno::MSGSIZE) => Some(types::Errno::Msgsize),
|
|
||||||
Some(Errno::NETDOWN) => Some(types::Errno::Netdown),
|
|
||||||
Some(Errno::NETRESET) => Some(types::Errno::Netreset),
|
|
||||||
Some(Errno::NETUNREACH) => Some(types::Errno::Netunreach),
|
|
||||||
Some(Errno::NOBUFS) => Some(types::Errno::Nobufs),
|
|
||||||
Some(Errno::NOPROTOOPT) => Some(types::Errno::Noprotoopt),
|
|
||||||
Some(Errno::NOTCONN) => Some(types::Errno::Notconn),
|
|
||||||
Some(Errno::NOTSOCK) => Some(types::Errno::Notsock),
|
|
||||||
Some(Errno::PROTONOSUPPORT) => Some(types::Errno::Protonosupport),
|
|
||||||
Some(Errno::PROTOTYPE) => Some(types::Errno::Prototype),
|
|
||||||
Some(Errno::STALE) => Some(types::Errno::Stale),
|
|
||||||
Some(Errno::TIMEDOUT) => Some(types::Errno::Timedout),
|
|
||||||
|
|
||||||
// On some platforms, these have the same value as other errno values.
|
|
||||||
#[allow(unreachable_patterns)]
|
|
||||||
Some(Errno::WOULDBLOCK) => Some(types::Errno::Again),
|
|
||||||
#[allow(unreachable_patterns)]
|
|
||||||
Some(Errno::OPNOTSUPP) => Some(types::Errno::Notsup),
|
|
||||||
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(windows)]
|
|
||||||
fn raw_error_code(err: &std::io::Error) -> Option<types::Errno> {
|
|
||||||
use windows_sys::Win32::Foundation;
|
|
||||||
use windows_sys::Win32::Networking::WinSock;
|
|
||||||
|
|
||||||
match err.raw_os_error().map(|code| code as u32) {
|
|
||||||
Some(Foundation::ERROR_BAD_ENVIRONMENT) => return Some(types::Errno::TooBig),
|
|
||||||
Some(Foundation::ERROR_FILE_NOT_FOUND) => return Some(types::Errno::Noent),
|
|
||||||
Some(Foundation::ERROR_PATH_NOT_FOUND) => return Some(types::Errno::Noent),
|
|
||||||
Some(Foundation::ERROR_TOO_MANY_OPEN_FILES) => return Some(types::Errno::Nfile),
|
|
||||||
Some(Foundation::ERROR_ACCESS_DENIED) => return Some(types::Errno::Acces),
|
|
||||||
Some(Foundation::ERROR_SHARING_VIOLATION) => return Some(types::Errno::Acces),
|
|
||||||
Some(Foundation::ERROR_PRIVILEGE_NOT_HELD) => return Some(types::Errno::Perm),
|
|
||||||
Some(Foundation::ERROR_INVALID_HANDLE) => return Some(types::Errno::Badf),
|
|
||||||
Some(Foundation::ERROR_INVALID_NAME) => return Some(types::Errno::Noent),
|
|
||||||
Some(Foundation::ERROR_NOT_ENOUGH_MEMORY) => return Some(types::Errno::Nomem),
|
|
||||||
Some(Foundation::ERROR_OUTOFMEMORY) => return Some(types::Errno::Nomem),
|
|
||||||
Some(Foundation::ERROR_DIR_NOT_EMPTY) => return Some(types::Errno::Notempty),
|
|
||||||
Some(Foundation::ERROR_NOT_READY) => return Some(types::Errno::Busy),
|
|
||||||
Some(Foundation::ERROR_BUSY) => return Some(types::Errno::Busy),
|
|
||||||
Some(Foundation::ERROR_NOT_SUPPORTED) => return Some(types::Errno::Notsup),
|
|
||||||
Some(Foundation::ERROR_FILE_EXISTS) => return Some(types::Errno::Exist),
|
|
||||||
Some(Foundation::ERROR_BROKEN_PIPE) => return Some(types::Errno::Pipe),
|
|
||||||
Some(Foundation::ERROR_BUFFER_OVERFLOW) => return Some(types::Errno::Nametoolong),
|
|
||||||
Some(Foundation::ERROR_NOT_A_REPARSE_POINT) => return Some(types::Errno::Inval),
|
|
||||||
Some(Foundation::ERROR_NEGATIVE_SEEK) => return Some(types::Errno::Inval),
|
|
||||||
Some(Foundation::ERROR_DIRECTORY) => return Some(types::Errno::Notdir),
|
|
||||||
Some(Foundation::ERROR_ALREADY_EXISTS) => return Some(types::Errno::Exist),
|
|
||||||
Some(Foundation::ERROR_STOPPED_ON_SYMLINK) => return Some(types::Errno::Loop),
|
|
||||||
Some(Foundation::ERROR_DIRECTORY_NOT_SUPPORTED) => {
|
|
||||||
return Some(types::Errno::Isdir)
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
match err.raw_os_error() {
|
|
||||||
Some(WinSock::WSAEWOULDBLOCK) => Some(types::Errno::Again),
|
|
||||||
Some(WinSock::WSAECANCELLED) => Some(types::Errno::Canceled),
|
|
||||||
Some(WinSock::WSA_E_CANCELLED) => Some(types::Errno::Canceled),
|
|
||||||
Some(WinSock::WSAEBADF) => Some(types::Errno::Badf),
|
|
||||||
Some(WinSock::WSAEFAULT) => Some(types::Errno::Fault),
|
|
||||||
Some(WinSock::WSAEINVAL) => Some(types::Errno::Inval),
|
|
||||||
Some(WinSock::WSAEMFILE) => Some(types::Errno::Mfile),
|
|
||||||
Some(WinSock::WSAENAMETOOLONG) => Some(types::Errno::Nametoolong),
|
|
||||||
Some(WinSock::WSAENOTEMPTY) => Some(types::Errno::Notempty),
|
|
||||||
Some(WinSock::WSAELOOP) => Some(types::Errno::Loop),
|
|
||||||
Some(WinSock::WSAEOPNOTSUPP) => Some(types::Errno::Notsup),
|
|
||||||
Some(WinSock::WSAEADDRINUSE) => Some(types::Errno::Addrinuse),
|
|
||||||
Some(WinSock::WSAEACCES) => Some(types::Errno::Acces),
|
|
||||||
Some(WinSock::WSAEADDRNOTAVAIL) => Some(types::Errno::Addrnotavail),
|
|
||||||
Some(WinSock::WSAEAFNOSUPPORT) => Some(types::Errno::Afnosupport),
|
|
||||||
Some(WinSock::WSAEALREADY) => Some(types::Errno::Already),
|
|
||||||
Some(WinSock::WSAECONNABORTED) => Some(types::Errno::Connaborted),
|
|
||||||
Some(WinSock::WSAECONNREFUSED) => Some(types::Errno::Connrefused),
|
|
||||||
Some(WinSock::WSAECONNRESET) => Some(types::Errno::Connreset),
|
|
||||||
Some(WinSock::WSAEDESTADDRREQ) => Some(types::Errno::Destaddrreq),
|
|
||||||
Some(WinSock::WSAEDQUOT) => Some(types::Errno::Dquot),
|
|
||||||
Some(WinSock::WSAEHOSTUNREACH) => Some(types::Errno::Hostunreach),
|
|
||||||
Some(WinSock::WSAEINPROGRESS) => Some(types::Errno::Inprogress),
|
|
||||||
Some(WinSock::WSAEINTR) => Some(types::Errno::Intr),
|
|
||||||
Some(WinSock::WSAEISCONN) => Some(types::Errno::Isconn),
|
|
||||||
Some(WinSock::WSAEMSGSIZE) => Some(types::Errno::Msgsize),
|
|
||||||
Some(WinSock::WSAENETDOWN) => Some(types::Errno::Netdown),
|
|
||||||
Some(WinSock::WSAENETRESET) => Some(types::Errno::Netreset),
|
|
||||||
Some(WinSock::WSAENETUNREACH) => Some(types::Errno::Netunreach),
|
|
||||||
Some(WinSock::WSAENOBUFS) => Some(types::Errno::Nobufs),
|
|
||||||
Some(WinSock::WSAENOPROTOOPT) => Some(types::Errno::Noprotoopt),
|
|
||||||
Some(WinSock::WSAENOTCONN) => Some(types::Errno::Notconn),
|
|
||||||
Some(WinSock::WSAENOTSOCK) => Some(types::Errno::Notsock),
|
|
||||||
Some(WinSock::WSAEPROTONOSUPPORT) => Some(types::Errno::Protonosupport),
|
|
||||||
Some(WinSock::WSAEPROTOTYPE) => Some(types::Errno::Prototype),
|
|
||||||
Some(WinSock::WSAESTALE) => Some(types::Errno::Stale),
|
|
||||||
Some(WinSock::WSAETIMEDOUT) => Some(types::Errno::Timedout),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match raw_error_code(&err) {
|
|
||||||
Some(errno) => Ok(errno),
|
|
||||||
None => match err.kind() {
|
|
||||||
std::io::ErrorKind::NotFound => Ok(types::Errno::Noent),
|
|
||||||
std::io::ErrorKind::PermissionDenied => Ok(types::Errno::Perm),
|
|
||||||
std::io::ErrorKind::AlreadyExists => Ok(types::Errno::Exist),
|
|
||||||
std::io::ErrorKind::InvalidInput => Ok(types::Errno::Inval),
|
|
||||||
_ => Err(anyhow::anyhow!(err).context(format!("Unknown OS error"))),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wiggle::async_trait]
|
#[wiggle::async_trait]
|
||||||
impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
||||||
async fn args_get<'b>(
|
async fn args_get<'b>(
|
||||||
@@ -311,7 +83,9 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let now = self.clocks.system.now(precision).into_std();
|
let now = self.clocks.system.now(precision).into_std();
|
||||||
let d = now
|
let d = now
|
||||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||||
.map_err(|_| Error::trap("current time before unix epoch"))?;
|
.map_err(|_| {
|
||||||
|
Error::trap(anyhow::Error::msg("current time before unix epoch"))
|
||||||
|
})?;
|
||||||
Ok(d.as_nanos().try_into()?)
|
Ok(d.as_nanos().try_into()?)
|
||||||
}
|
}
|
||||||
types::Clockid::Monotonic => {
|
types::Clockid::Monotonic => {
|
||||||
@@ -489,8 +263,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let set_mtim = fst_flags.contains(types::Fstflags::MTIM);
|
let set_mtim = fst_flags.contains(types::Fstflags::MTIM);
|
||||||
let set_mtim_now = fst_flags.contains(types::Fstflags::MTIM_NOW);
|
let set_mtim_now = fst_flags.contains(types::Fstflags::MTIM_NOW);
|
||||||
|
|
||||||
let atim = systimespec(set_atim, atim, set_atim_now).context("atim")?;
|
let atim = systimespec(set_atim, atim, set_atim_now).map_err(|e| e.context("atim"))?;
|
||||||
let mtim = systimespec(set_mtim, mtim, set_mtim_now).context("mtim")?;
|
let mtim = systimespec(set_mtim, mtim, set_mtim_now).map_err(|e| e.context("mtim"))?;
|
||||||
|
|
||||||
if table.is::<FileEntry>(fd) {
|
if table.is::<FileEntry>(fd) {
|
||||||
table
|
table
|
||||||
@@ -839,8 +613,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let set_mtim = fst_flags.contains(types::Fstflags::MTIM);
|
let set_mtim = fst_flags.contains(types::Fstflags::MTIM);
|
||||||
let set_mtim_now = fst_flags.contains(types::Fstflags::MTIM_NOW);
|
let set_mtim_now = fst_flags.contains(types::Fstflags::MTIM_NOW);
|
||||||
|
|
||||||
let atim = systimespec(set_atim, atim, set_atim_now).context("atim")?;
|
let atim = systimespec(set_atim, atim, set_atim_now).map_err(|e| e.context("atim"))?;
|
||||||
let mtim = systimespec(set_mtim, mtim, set_mtim_now).context("mtim")?;
|
let mtim = systimespec(set_mtim, mtim, set_mtim_now).map_err(|e| e.context("mtim"))?;
|
||||||
self.table()
|
self.table()
|
||||||
.get_dir(u32::from(dirfd))?
|
.get_dir(u32::from(dirfd))?
|
||||||
.get_cap(DirCaps::PATH_FILESTAT_SET_TIMES)?
|
.get_cap(DirCaps::PATH_FILESTAT_SET_TIMES)?
|
||||||
@@ -1189,7 +963,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
},
|
},
|
||||||
Err(e) => types::Event {
|
Err(e) => types::Event {
|
||||||
userdata,
|
userdata,
|
||||||
error: e.try_into().expect("non-trapping"),
|
error: e.downcast().map_err(Error::trap)?,
|
||||||
type_,
|
type_,
|
||||||
fd_readwrite: fd_readwrite_empty(),
|
fd_readwrite: fd_readwrite_empty(),
|
||||||
},
|
},
|
||||||
@@ -1209,7 +983,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
},
|
},
|
||||||
Err(e) => types::Event {
|
Err(e) => types::Event {
|
||||||
userdata,
|
userdata,
|
||||||
error: e.try_into()?,
|
error: e.downcast().map_err(Error::trap)?,
|
||||||
type_,
|
type_,
|
||||||
fd_readwrite: fd_readwrite_empty(),
|
fd_readwrite: fd_readwrite_empty(),
|
||||||
},
|
},
|
||||||
@@ -1221,7 +995,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
userdata,
|
userdata,
|
||||||
error: match r {
|
error: match r {
|
||||||
Ok(()) => types::Errno::Success,
|
Ok(()) => types::Errno::Success,
|
||||||
Err(e) => e.try_into()?,
|
Err(e) => e.downcast().map_err(Error::trap)?,
|
||||||
},
|
},
|
||||||
type_,
|
type_,
|
||||||
fd_readwrite: fd_readwrite_empty(),
|
fd_readwrite: fd_readwrite_empty(),
|
||||||
@@ -1238,12 +1012,12 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
if status < 126 {
|
if status < 126 {
|
||||||
I32Exit(status as i32).into()
|
I32Exit(status as i32).into()
|
||||||
} else {
|
} else {
|
||||||
anyhow!("exit with invalid exit status outside of [0..126)")
|
anyhow::Error::msg("exit with invalid exit status outside of [0..126)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn proc_raise(&mut self, _sig: types::Signal) -> Result<(), Error> {
|
async fn proc_raise(&mut self, _sig: types::Signal) -> Result<(), Error> {
|
||||||
Err(Error::trap("proc_raise unsupported"))
|
Err(Error::trap(anyhow::Error::msg("proc_raise unsupported")))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sched_yield(&mut self) -> Result<(), Error> {
|
async fn sched_yield(&mut self) -> Result<(), Error> {
|
||||||
|
|||||||
255
crates/wasi-common/src/snapshots/preview_1/error.rs
Normal file
255
crates/wasi-common/src/snapshots/preview_1/error.rs
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
pub use super::types::{Errno, Error};
|
||||||
|
|
||||||
|
pub trait ErrorExt {
|
||||||
|
fn not_found() -> Self;
|
||||||
|
fn too_big() -> Self;
|
||||||
|
fn badf() -> Self;
|
||||||
|
fn exist() -> Self;
|
||||||
|
fn illegal_byte_sequence() -> Self;
|
||||||
|
fn invalid_argument() -> Self;
|
||||||
|
fn io() -> Self;
|
||||||
|
fn name_too_long() -> Self;
|
||||||
|
fn not_dir() -> Self;
|
||||||
|
fn not_supported() -> Self;
|
||||||
|
fn overflow() -> Self;
|
||||||
|
fn range() -> Self;
|
||||||
|
fn seek_pipe() -> Self;
|
||||||
|
fn perm() -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ErrorExt for Error {
|
||||||
|
fn not_found() -> Self {
|
||||||
|
Errno::Noent.into()
|
||||||
|
}
|
||||||
|
fn too_big() -> Self {
|
||||||
|
Errno::TooBig.into()
|
||||||
|
}
|
||||||
|
fn badf() -> Self {
|
||||||
|
Errno::Badf.into()
|
||||||
|
}
|
||||||
|
fn exist() -> Self {
|
||||||
|
Errno::Exist.into()
|
||||||
|
}
|
||||||
|
fn illegal_byte_sequence() -> Self {
|
||||||
|
Errno::Ilseq.into()
|
||||||
|
}
|
||||||
|
fn invalid_argument() -> Self {
|
||||||
|
Errno::Inval.into()
|
||||||
|
}
|
||||||
|
fn io() -> Self {
|
||||||
|
Errno::Io.into()
|
||||||
|
}
|
||||||
|
fn name_too_long() -> Self {
|
||||||
|
Errno::Nametoolong.into()
|
||||||
|
}
|
||||||
|
fn not_dir() -> Self {
|
||||||
|
Errno::Notdir.into()
|
||||||
|
}
|
||||||
|
fn not_supported() -> Self {
|
||||||
|
Errno::Notsup.into()
|
||||||
|
}
|
||||||
|
fn overflow() -> Self {
|
||||||
|
Errno::Overflow.into()
|
||||||
|
}
|
||||||
|
fn range() -> Self {
|
||||||
|
Errno::Range.into()
|
||||||
|
}
|
||||||
|
fn seek_pipe() -> Self {
|
||||||
|
Errno::Spipe.into()
|
||||||
|
}
|
||||||
|
fn perm() -> Self {
|
||||||
|
Errno::Perm.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn from_raw_os_error(err: Option<i32>) -> Option<Error> {
|
||||||
|
use rustix::io::Errno as RustixErrno;
|
||||||
|
if err.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(match RustixErrno::from_raw_os_error(err.unwrap()) {
|
||||||
|
RustixErrno::AGAIN => Errno::Again.into(),
|
||||||
|
RustixErrno::PIPE => Errno::Pipe.into(),
|
||||||
|
RustixErrno::PERM => Errno::Perm.into(),
|
||||||
|
RustixErrno::NOENT => Errno::Noent.into(),
|
||||||
|
RustixErrno::NOMEM => Errno::Nomem.into(),
|
||||||
|
RustixErrno::TOOBIG => Errno::TooBig.into(),
|
||||||
|
RustixErrno::IO => Errno::Io.into(),
|
||||||
|
RustixErrno::BADF => Errno::Badf.into(),
|
||||||
|
RustixErrno::BUSY => Errno::Busy.into(),
|
||||||
|
RustixErrno::ACCESS => Errno::Acces.into(),
|
||||||
|
RustixErrno::FAULT => Errno::Fault.into(),
|
||||||
|
RustixErrno::NOTDIR => Errno::Notdir.into(),
|
||||||
|
RustixErrno::ISDIR => Errno::Isdir.into(),
|
||||||
|
RustixErrno::INVAL => Errno::Inval.into(),
|
||||||
|
RustixErrno::EXIST => Errno::Exist.into(),
|
||||||
|
RustixErrno::FBIG => Errno::Fbig.into(),
|
||||||
|
RustixErrno::NOSPC => Errno::Nospc.into(),
|
||||||
|
RustixErrno::SPIPE => Errno::Spipe.into(),
|
||||||
|
RustixErrno::MFILE => Errno::Mfile.into(),
|
||||||
|
RustixErrno::MLINK => Errno::Mlink.into(),
|
||||||
|
RustixErrno::NAMETOOLONG => Errno::Nametoolong.into(),
|
||||||
|
RustixErrno::NFILE => Errno::Nfile.into(),
|
||||||
|
RustixErrno::NOTEMPTY => Errno::Notempty.into(),
|
||||||
|
RustixErrno::LOOP => Errno::Loop.into(),
|
||||||
|
RustixErrno::OVERFLOW => Errno::Overflow.into(),
|
||||||
|
RustixErrno::ILSEQ => Errno::Ilseq.into(),
|
||||||
|
RustixErrno::NOTSUP => Errno::Notsup.into(),
|
||||||
|
RustixErrno::ADDRINUSE => Errno::Addrinuse.into(),
|
||||||
|
RustixErrno::CANCELED => Errno::Canceled.into(),
|
||||||
|
RustixErrno::ADDRNOTAVAIL => Errno::Addrnotavail.into(),
|
||||||
|
RustixErrno::AFNOSUPPORT => Errno::Afnosupport.into(),
|
||||||
|
RustixErrno::ALREADY => Errno::Already.into(),
|
||||||
|
RustixErrno::CONNABORTED => Errno::Connaborted.into(),
|
||||||
|
RustixErrno::CONNREFUSED => Errno::Connrefused.into(),
|
||||||
|
RustixErrno::CONNRESET => Errno::Connreset.into(),
|
||||||
|
RustixErrno::DESTADDRREQ => Errno::Destaddrreq.into(),
|
||||||
|
RustixErrno::DQUOT => Errno::Dquot.into(),
|
||||||
|
RustixErrno::HOSTUNREACH => Errno::Hostunreach.into(),
|
||||||
|
RustixErrno::INPROGRESS => Errno::Inprogress.into(),
|
||||||
|
RustixErrno::INTR => Errno::Intr.into(),
|
||||||
|
RustixErrno::ISCONN => Errno::Isconn.into(),
|
||||||
|
RustixErrno::MSGSIZE => Errno::Msgsize.into(),
|
||||||
|
RustixErrno::NETDOWN => Errno::Netdown.into(),
|
||||||
|
RustixErrno::NETRESET => Errno::Netreset.into(),
|
||||||
|
RustixErrno::NETUNREACH => Errno::Netunreach.into(),
|
||||||
|
RustixErrno::NOBUFS => Errno::Nobufs.into(),
|
||||||
|
RustixErrno::NOPROTOOPT => Errno::Noprotoopt.into(),
|
||||||
|
RustixErrno::NOTCONN => Errno::Notconn.into(),
|
||||||
|
RustixErrno::NOTSOCK => Errno::Notsock.into(),
|
||||||
|
RustixErrno::PROTONOSUPPORT => Errno::Protonosupport.into(),
|
||||||
|
RustixErrno::PROTOTYPE => Errno::Prototype.into(),
|
||||||
|
RustixErrno::STALE => Errno::Stale.into(),
|
||||||
|
RustixErrno::TIMEDOUT => Errno::Timedout.into(),
|
||||||
|
|
||||||
|
// On some platforms.into(), these have the same value as other errno values.
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
RustixErrno::WOULDBLOCK => Errno::Again.into(),
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
RustixErrno::OPNOTSUPP => Errno::Notsup.into(),
|
||||||
|
|
||||||
|
_ => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn from_raw_os_error(raw_os_error: Option<i32>) -> Option<Error> {
|
||||||
|
use windows_sys::Win32::Foundation;
|
||||||
|
use windows_sys::Win32::Networking::WinSock;
|
||||||
|
|
||||||
|
match raw_os_error.map(|code| code as u32) {
|
||||||
|
Some(Foundation::ERROR_BAD_ENVIRONMENT) => return Some(Errno::TooBig.into()),
|
||||||
|
Some(Foundation::ERROR_FILE_NOT_FOUND) => return Some(Errno::Noent.into()),
|
||||||
|
Some(Foundation::ERROR_PATH_NOT_FOUND) => return Some(Errno::Noent.into()),
|
||||||
|
Some(Foundation::ERROR_TOO_MANY_OPEN_FILES) => return Some(Errno::Nfile.into()),
|
||||||
|
Some(Foundation::ERROR_ACCESS_DENIED) => return Some(Errno::Acces.into()),
|
||||||
|
Some(Foundation::ERROR_SHARING_VIOLATION) => return Some(Errno::Acces.into()),
|
||||||
|
Some(Foundation::ERROR_PRIVILEGE_NOT_HELD) => return Some(Errno::Perm.into()),
|
||||||
|
Some(Foundation::ERROR_INVALID_HANDLE) => return Some(Errno::Badf.into()),
|
||||||
|
Some(Foundation::ERROR_INVALID_NAME) => return Some(Errno::Noent.into()),
|
||||||
|
Some(Foundation::ERROR_NOT_ENOUGH_MEMORY) => return Some(Errno::Nomem.into()),
|
||||||
|
Some(Foundation::ERROR_OUTOFMEMORY) => return Some(Errno::Nomem.into()),
|
||||||
|
Some(Foundation::ERROR_DIR_NOT_EMPTY) => return Some(Errno::Notempty.into()),
|
||||||
|
Some(Foundation::ERROR_NOT_READY) => return Some(Errno::Busy.into()),
|
||||||
|
Some(Foundation::ERROR_BUSY) => return Some(Errno::Busy.into()),
|
||||||
|
Some(Foundation::ERROR_NOT_SUPPORTED) => return Some(Errno::Notsup.into()),
|
||||||
|
Some(Foundation::ERROR_FILE_EXISTS) => return Some(Errno::Exist.into()),
|
||||||
|
Some(Foundation::ERROR_BROKEN_PIPE) => return Some(Errno::Pipe.into()),
|
||||||
|
Some(Foundation::ERROR_BUFFER_OVERFLOW) => return Some(Errno::Nametoolong.into()),
|
||||||
|
Some(Foundation::ERROR_NOT_A_REPARSE_POINT) => return Some(Errno::Inval.into()),
|
||||||
|
Some(Foundation::ERROR_NEGATIVE_SEEK) => return Some(Errno::Inval.into()),
|
||||||
|
Some(Foundation::ERROR_DIRECTORY) => return Some(Errno::Notdir.into()),
|
||||||
|
Some(Foundation::ERROR_ALREADY_EXISTS) => return Some(Errno::Exist.into()),
|
||||||
|
Some(Foundation::ERROR_STOPPED_ON_SYMLINK) => return Some(Errno::Loop.into()),
|
||||||
|
Some(Foundation::ERROR_DIRECTORY_NOT_SUPPORTED) => return Some(Errno::Isdir.into()),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match raw_os_error {
|
||||||
|
Some(WinSock::WSAEWOULDBLOCK) => Some(Errno::Again.into()),
|
||||||
|
Some(WinSock::WSAECANCELLED) => Some(Errno::Canceled.into()),
|
||||||
|
Some(WinSock::WSA_E_CANCELLED) => Some(Errno::Canceled.into()),
|
||||||
|
Some(WinSock::WSAEBADF) => Some(Errno::Badf.into()),
|
||||||
|
Some(WinSock::WSAEFAULT) => Some(Errno::Fault.into()),
|
||||||
|
Some(WinSock::WSAEINVAL) => Some(Errno::Inval.into()),
|
||||||
|
Some(WinSock::WSAEMFILE) => Some(Errno::Mfile.into()),
|
||||||
|
Some(WinSock::WSAENAMETOOLONG) => Some(Errno::Nametoolong.into()),
|
||||||
|
Some(WinSock::WSAENOTEMPTY) => Some(Errno::Notempty.into()),
|
||||||
|
Some(WinSock::WSAELOOP) => Some(Errno::Loop.into()),
|
||||||
|
Some(WinSock::WSAEOPNOTSUPP) => Some(Errno::Notsup.into()),
|
||||||
|
Some(WinSock::WSAEADDRINUSE) => Some(Errno::Addrinuse.into()),
|
||||||
|
Some(WinSock::WSAEACCES) => Some(Errno::Acces.into()),
|
||||||
|
Some(WinSock::WSAEADDRNOTAVAIL) => Some(Errno::Addrnotavail.into()),
|
||||||
|
Some(WinSock::WSAEAFNOSUPPORT) => Some(Errno::Afnosupport.into()),
|
||||||
|
Some(WinSock::WSAEALREADY) => Some(Errno::Already.into()),
|
||||||
|
Some(WinSock::WSAECONNABORTED) => Some(Errno::Connaborted.into()),
|
||||||
|
Some(WinSock::WSAECONNREFUSED) => Some(Errno::Connrefused.into()),
|
||||||
|
Some(WinSock::WSAECONNRESET) => Some(Errno::Connreset.into()),
|
||||||
|
Some(WinSock::WSAEDESTADDRREQ) => Some(Errno::Destaddrreq.into()),
|
||||||
|
Some(WinSock::WSAEDQUOT) => Some(Errno::Dquot.into()),
|
||||||
|
Some(WinSock::WSAEHOSTUNREACH) => Some(Errno::Hostunreach.into()),
|
||||||
|
Some(WinSock::WSAEINPROGRESS) => Some(Errno::Inprogress.into()),
|
||||||
|
Some(WinSock::WSAEINTR) => Some(Errno::Intr.into()),
|
||||||
|
Some(WinSock::WSAEISCONN) => Some(Errno::Isconn.into()),
|
||||||
|
Some(WinSock::WSAEMSGSIZE) => Some(Errno::Msgsize.into()),
|
||||||
|
Some(WinSock::WSAENETDOWN) => Some(Errno::Netdown.into()),
|
||||||
|
Some(WinSock::WSAENETRESET) => Some(Errno::Netreset.into()),
|
||||||
|
Some(WinSock::WSAENETUNREACH) => Some(Errno::Netunreach.into()),
|
||||||
|
Some(WinSock::WSAENOBUFS) => Some(Errno::Nobufs.into()),
|
||||||
|
Some(WinSock::WSAENOPROTOOPT) => Some(Errno::Noprotoopt.into()),
|
||||||
|
Some(WinSock::WSAENOTCONN) => Some(Errno::Notconn.into()),
|
||||||
|
Some(WinSock::WSAENOTSOCK) => Some(Errno::Notsock.into()),
|
||||||
|
Some(WinSock::WSAEPROTONOSUPPORT) => Some(Errno::Protonosupport.into()),
|
||||||
|
Some(WinSock::WSAEPROTOTYPE) => Some(Errno::Prototype.into()),
|
||||||
|
Some(WinSock::WSAESTALE) => Some(Errno::Stale.into()),
|
||||||
|
Some(WinSock::WSAETIMEDOUT) => Some(Errno::Timedout.into()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
fn from(err: std::io::Error) -> Error {
|
||||||
|
match from_raw_os_error(err.raw_os_error()) {
|
||||||
|
Some(errno) => errno,
|
||||||
|
None => match err.kind() {
|
||||||
|
std::io::ErrorKind::NotFound => Errno::Noent.into(),
|
||||||
|
std::io::ErrorKind::PermissionDenied => Errno::Perm.into(),
|
||||||
|
std::io::ErrorKind::AlreadyExists => Errno::Exist.into(),
|
||||||
|
std::io::ErrorKind::InvalidInput => Errno::Inval.into(),
|
||||||
|
_ => Error::trap(anyhow::anyhow!(err).context("Unknown OS error")),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<cap_rand::Error> for Error {
|
||||||
|
fn from(err: cap_rand::Error) -> Error {
|
||||||
|
// I picked Error::Io as a 'reasonable default', FIXME dan is this ok?
|
||||||
|
from_raw_os_error(err.raw_os_error()).unwrap_or_else(|| Error::from(Errno::Io))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<wiggle::GuestError> for Error {
|
||||||
|
fn from(err: wiggle::GuestError) -> Error {
|
||||||
|
use wiggle::GuestError::*;
|
||||||
|
match err {
|
||||||
|
InvalidFlagValue { .. } => Errno::Inval.into(),
|
||||||
|
InvalidEnumValue { .. } => Errno::Inval.into(),
|
||||||
|
PtrOverflow { .. } => Errno::Fault.into(),
|
||||||
|
PtrOutOfBounds { .. } => Errno::Fault.into(),
|
||||||
|
PtrNotAligned { .. } => Errno::Inval.into(),
|
||||||
|
PtrBorrowed { .. } => Errno::Fault.into(),
|
||||||
|
InvalidUtf8 { .. } => Errno::Ilseq.into(),
|
||||||
|
TryFromIntError { .. } => Errno::Overflow.into(),
|
||||||
|
SliceLengthsDiffer { .. } => Errno::Fault.into(),
|
||||||
|
BorrowCheckerOutOfHandles { .. } => Errno::Fault.into(),
|
||||||
|
InFunc { err, .. } => Error::from(*err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::num::TryFromIntError> for Error {
|
||||||
|
fn from(_err: std::num::TryFromIntError) -> Error {
|
||||||
|
Errno::Overflow.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ impl Table {
|
|||||||
// NOTE: The performance of this new key calculation could be very bad once keys wrap
|
// NOTE: The performance of this new key calculation could be very bad once keys wrap
|
||||||
// around.
|
// around.
|
||||||
if self.map.len() == u32::MAX as usize {
|
if self.map.len() == u32::MAX as usize {
|
||||||
return Err(Error::trap("table has no free keys"));
|
return Err(Error::trap(anyhow::Error::msg("table has no free keys")));
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
let key = self.next_key;
|
let key = self.next_key;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use wasi_common::{
|
|||||||
subscription::{RwEventFlags, Subscription},
|
subscription::{RwEventFlags, Subscription},
|
||||||
Poll,
|
Poll,
|
||||||
},
|
},
|
||||||
Context as _, Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FirstReady<'a, T>(Vec<Pin<Box<dyn Future<Output = T> + Send + 'a>>>);
|
struct FirstReady<'a, T>(Vec<Pin<Box<dyn Future<Output = T> + Send + 'a>>>);
|
||||||
@@ -56,12 +56,15 @@ pub async fn poll_oneoff<'a>(poll: &mut Poll<'a>) -> Result<(), Error> {
|
|||||||
match s {
|
match s {
|
||||||
Subscription::Read(f) => {
|
Subscription::Read(f) => {
|
||||||
futures.push(async move {
|
futures.push(async move {
|
||||||
f.file.readable().await.context("readable future")?;
|
f.file
|
||||||
|
.readable()
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.context("readable future"))?;
|
||||||
f.complete(
|
f.complete(
|
||||||
f.file
|
f.file
|
||||||
.num_ready_bytes()
|
.num_ready_bytes()
|
||||||
.await
|
.await
|
||||||
.context("read num_ready_bytes")?,
|
.map_err(|e| e.context("read num_ready_bytes"))?,
|
||||||
RwEventFlags::empty(),
|
RwEventFlags::empty(),
|
||||||
);
|
);
|
||||||
Ok::<(), Error>(())
|
Ok::<(), Error>(())
|
||||||
@@ -70,7 +73,10 @@ pub async fn poll_oneoff<'a>(poll: &mut Poll<'a>) -> Result<(), Error> {
|
|||||||
|
|
||||||
Subscription::Write(f) => {
|
Subscription::Write(f) => {
|
||||||
futures.push(async move {
|
futures.push(async move {
|
||||||
f.file.writable().await.context("writable future")?;
|
f.file
|
||||||
|
.writable()
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.context("writable future"))?;
|
||||||
f.complete(0, RwEventFlags::empty());
|
f.complete(0, RwEventFlags::empty());
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ pub fn add_to_linker<T, U>(
|
|||||||
) -> anyhow::Result<()>
|
) -> anyhow::Result<()>
|
||||||
where U: Send
|
where U: Send
|
||||||
+ wasi_common::snapshots::preview_0::wasi_unstable::WasiUnstable
|
+ wasi_common::snapshots::preview_0::wasi_unstable::WasiUnstable
|
||||||
+ wasi_common::snapshots::preview_0::types::UserErrorConversion
|
+ wasi_common::snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1,
|
||||||
+ wasi_common::snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1
|
|
||||||
+ wasi_common::snapshots::preview_1::types::UserErrorConversion,
|
|
||||||
$($bounds)*
|
$($bounds)*
|
||||||
{
|
{
|
||||||
snapshots::preview_1::add_wasi_snapshot_preview1_to_linker(linker, get_cx)?;
|
snapshots::preview_1::add_wasi_snapshot_preview1_to_linker(linker, get_cx)?;
|
||||||
@@ -66,7 +64,7 @@ pub mod snapshots {
|
|||||||
// This must be the same witx document as used above. This should be ensured by
|
// This must be the same witx document as used above. This should be ensured by
|
||||||
// the `WASI_ROOT` env variable, which is set in wasi-common's `build.rs`.
|
// the `WASI_ROOT` env variable, which is set in wasi-common's `build.rs`.
|
||||||
witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
|
witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
|
||||||
errors: { errno => Error },
|
errors: { errno => trappable Error },
|
||||||
$async_mode: *
|
$async_mode: *
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -77,7 +75,7 @@ pub mod snapshots {
|
|||||||
// This must be the same witx document as used above. This should be ensured by
|
// This must be the same witx document as used above. This should be ensured by
|
||||||
// the `WASI_ROOT` env variable, which is set in wasi-common's `build.rs`.
|
// the `WASI_ROOT` env variable, which is set in wasi-common's `build.rs`.
|
||||||
witx: ["$WASI_ROOT/phases/old/snapshot_0/witx/wasi_unstable.witx"],
|
witx: ["$WASI_ROOT/phases/old/snapshot_0/witx/wasi_unstable.witx"],
|
||||||
errors: { errno => Error },
|
errors: { errno => trappable Error },
|
||||||
$async_mode: *
|
$async_mode: *
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user