wasi-c2: rewrite wasi-common in terms of system-interface
This commit is contained in:
49
Cargo.lock
generated
49
Cargo.lock
generated
@@ -1458,6 +1458,19 @@ version = "0.1.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
|
checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "posish"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a81e5017f1c873447782cd776e6ec307af670ecad29e934042005a0dec6864dd"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"errno",
|
||||||
|
"itoa",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
@@ -1992,6 +2005,16 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-interface"
|
||||||
|
version = "0.0.1-alpha.0"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"posish",
|
||||||
|
"winapi",
|
||||||
|
"winx 0.20.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "target-lexicon"
|
name = "target-lexicon"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@@ -2283,6 +2306,19 @@ version = "0.10.0+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi-c2"
|
||||||
|
version = "0.21.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"getrandom 0.2.0",
|
||||||
|
"libc",
|
||||||
|
"system-interface",
|
||||||
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
|
"wiggle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi-common"
|
name = "wasi-common"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
@@ -2298,7 +2334,7 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
"wiggle",
|
"wiggle",
|
||||||
"winapi",
|
"winapi",
|
||||||
"winx",
|
"winx 0.21.0",
|
||||||
"yanix",
|
"yanix",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2810,6 +2846,17 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winx"
|
||||||
|
version = "0.20.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b25e4ae373f2f2f7f5f187974ed315719ce74160859027c80deb1f68b3c0c966"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cvt",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winx"
|
name = "winx"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ members = [
|
|||||||
"crates/misc/rust",
|
"crates/misc/rust",
|
||||||
"crates/wiggle",
|
"crates/wiggle",
|
||||||
"crates/wiggle/wasmtime",
|
"crates/wiggle/wasmtime",
|
||||||
|
"crates/wasi-c2",
|
||||||
"examples/fib-debug/wasm",
|
"examples/fib-debug/wasm",
|
||||||
"examples/wasi/wasm",
|
"examples/wasi/wasm",
|
||||||
"examples/wasi-fs/wasm",
|
"examples/wasi-fs/wasm",
|
||||||
|
|||||||
35
crates/wasi-c2/Cargo.toml
Normal file
35
crates/wasi-c2/Cargo.toml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasi-c2"
|
||||||
|
version = "0.21.0"
|
||||||
|
authors = ["The Wasmtime Project Developers"]
|
||||||
|
description = "WASI implementation in Rust"
|
||||||
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
categories = ["wasm"]
|
||||||
|
keywords = ["webassembly", "wasm"]
|
||||||
|
repository = "https://github.com/bytecodealliance/wasmtime"
|
||||||
|
readme = "README.md"
|
||||||
|
edition = "2018"
|
||||||
|
include = ["src/**/*", "LICENSE", "build.rs"]
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
|
thiserror = "1.0"
|
||||||
|
libc = "0.2"
|
||||||
|
getrandom = { version = "0.2.0", features = ["std"] }
|
||||||
|
wiggle = { path = "../wiggle", default-features = false, version = "0.21.0" }
|
||||||
|
tracing = "0.1.19"
|
||||||
|
system-interface = { path = "../../../system-interface" }
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
maintenance = { status = "actively-developed" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["trace_log"]
|
||||||
|
# This feature enables the `tracing` logs in the calls to target the `log`
|
||||||
|
# ecosystem of backends (e.g. `env_logger`. Disable this if you want to use
|
||||||
|
# `tracing-subscriber`.
|
||||||
|
trace_log = [ "wiggle/tracing_log", "tracing/log" ]
|
||||||
|
# Need to make the wiggle_metadata feature available to consumers of this
|
||||||
|
# crate if they want the snapshots to have metadata available.
|
||||||
|
wiggle_metadata = ["wiggle/wiggle_metadata"]
|
||||||
8
crates/wasi-c2/build.rs
Normal file
8
crates/wasi-c2/build.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Tell any dependencies, if necessary, where our WASI submodule is so they can
|
||||||
|
// use the same witx files if they want.
|
||||||
|
fn main() {
|
||||||
|
let cwd = std::env::current_dir().unwrap();
|
||||||
|
let wasi = cwd.join("..").join("wasi-common").join("WASI");
|
||||||
|
println!("cargo:wasi={}", wasi.display());
|
||||||
|
println!("cargo:rustc-env=WASI_ROOT={}", wasi.display());
|
||||||
|
}
|
||||||
26
crates/wasi-c2/src/ctx.rs
Normal file
26
crates/wasi-c2/src/ctx.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
use crate::table::Table;
|
||||||
|
use std::cell::{RefCell, RefMut};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct WasiCtx {
|
||||||
|
table: Rc<RefCell<Table>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiCtx {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
WasiCtx {
|
||||||
|
table: Rc::new(RefCell::new(Table::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn table(&self) -> RefMut<Table> {
|
||||||
|
self.table.borrow_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WasiDir {}
|
||||||
|
|
||||||
|
pub(crate) struct DirEntry {
|
||||||
|
pub(crate) flags: u32,
|
||||||
|
pub(crate) dir: Box<dyn WasiDir>,
|
||||||
|
}
|
||||||
151
crates/wasi-c2/src/error.rs
Normal file
151
crates/wasi-c2/src/error.rs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
use crate::file::FileCaps;
|
||||||
|
use thiserror::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),
|
||||||
|
|
||||||
|
/// Errno::Notcapable: Extension: Capabilities insufficient
|
||||||
|
#[error("File not capable: {0}")]
|
||||||
|
FileNotCapable(FileCaps),
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::convert::Infallible> for Error {
|
||||||
|
fn from(_err: std::convert::Infallible) -> Self {
|
||||||
|
unreachable!("should be impossible: From<Infallible>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
crates/wasi-c2/src/file.rs
Normal file
53
crates/wasi-c2/src/file.rs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
use crate::Error;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use system_interface::fs::FileIoExt;
|
||||||
|
|
||||||
|
pub trait WasiFile: FileIoExt {}
|
||||||
|
|
||||||
|
pub(crate) struct FileEntry {
|
||||||
|
pub(crate) base_caps: FileCaps,
|
||||||
|
pub(crate) inheriting_caps: FileCaps,
|
||||||
|
pub(crate) file: Box<dyn WasiFile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileEntry {
|
||||||
|
pub fn get_cap(&self, caps: FileCaps) -> Result<&dyn WasiFile, Error> {
|
||||||
|
if self.base_caps.contains(&caps) && self.inheriting_caps.contains(&caps) {
|
||||||
|
Ok(self.file.deref())
|
||||||
|
} else {
|
||||||
|
Err(Error::FileNotCapable(caps))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct FileCaps {
|
||||||
|
flags: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileCaps {
|
||||||
|
pub fn empty() -> Self {
|
||||||
|
FileCaps { flags: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if `other` is a subset of those capabilties:
|
||||||
|
pub fn contains(&self, other: &Self) -> bool {
|
||||||
|
self.flags & other.flags == other.flags
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const DATASYNC: Self = FileCaps { flags: 1 };
|
||||||
|
pub const READ: Self = FileCaps { flags: 2 };
|
||||||
|
pub const SEEK: Self = FileCaps { flags: 4 };
|
||||||
|
pub const FDSTAT_SET_FLAGS: Self = FileCaps { flags: 8 };
|
||||||
|
pub const SYNC: Self = FileCaps { flags: 16 };
|
||||||
|
pub const TELL: Self = FileCaps { flags: 32 };
|
||||||
|
pub const WRITE: Self = FileCaps { flags: 64 };
|
||||||
|
pub const ADVISE: Self = FileCaps { flags: 128 };
|
||||||
|
pub const ALLOCATE: Self = FileCaps { flags: 256 };
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for FileCaps {
|
||||||
|
fn fmt(&self, _f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
8
crates/wasi-c2/src/lib.rs
Normal file
8
crates/wasi-c2/src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
mod ctx;
|
||||||
|
mod error;
|
||||||
|
mod file;
|
||||||
|
pub mod snapshots;
|
||||||
|
pub mod table;
|
||||||
|
|
||||||
|
pub use ctx::WasiCtx;
|
||||||
|
pub use error::Error;
|
||||||
1
crates/wasi-c2/src/snapshots/mod.rs
Normal file
1
crates/wasi-c2/src/snapshots/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod preview_1;
|
||||||
424
crates/wasi-c2/src/snapshots/preview_1.rs
Normal file
424
crates/wasi-c2/src/snapshots/preview_1.rs
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
#![allow(unused_variables)]
|
||||||
|
use crate::file::{FileCaps, FileEntry};
|
||||||
|
use crate::{Error, WasiCtx};
|
||||||
|
use std::cell::RefMut;
|
||||||
|
use tracing::debug;
|
||||||
|
use wiggle::GuestPtr;
|
||||||
|
|
||||||
|
wiggle::from_witx!({
|
||||||
|
witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
|
||||||
|
ctx: WasiCtx,
|
||||||
|
errors: { errno => Error },
|
||||||
|
});
|
||||||
|
|
||||||
|
impl wiggle::GuestErrorType for types::Errno {
|
||||||
|
fn success() -> Self {
|
||||||
|
Self::Success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl types::GuestErrorConversion for WasiCtx {
|
||||||
|
fn into_errno(&self, e: wiggle::GuestError) -> types::Errno {
|
||||||
|
debug!("Guest error: {:?}", e);
|
||||||
|
e.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl types::UserErrorConversion for WasiCtx {
|
||||||
|
fn errno_from_error(&self, e: Error) -> types::Errno {
|
||||||
|
debug!("Error: {:?}", e);
|
||||||
|
e.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Error> for types::Errno {
|
||||||
|
fn from(e: Error) -> types::Errno {
|
||||||
|
use types::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::FileNotCapable { .. } => Errno::Notcapable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 { .. } => Self::Inval,
|
||||||
|
InDataField { .. } => Self::Inval,
|
||||||
|
SliceLengthsDiffer { .. } => Self::Fault,
|
||||||
|
BorrowCheckerOutOfHandles { .. } => Self::Fault,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
||||||
|
fn args_get<'b>(
|
||||||
|
&self,
|
||||||
|
argv: &GuestPtr<'b, GuestPtr<'b, u8>>,
|
||||||
|
argv_buf: &GuestPtr<'b, u8>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn args_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn environ_get<'b>(
|
||||||
|
&self,
|
||||||
|
environ: &GuestPtr<'b, GuestPtr<'b, u8>>,
|
||||||
|
environ_buf: &GuestPtr<'b, u8>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn environ_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clock_res_get(&self, id: types::Clockid) -> Result<types::Timestamp, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clock_time_get(
|
||||||
|
&self,
|
||||||
|
id: types::Clockid,
|
||||||
|
_precision: types::Timestamp,
|
||||||
|
) -> Result<types::Timestamp, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_advise(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
offset: types::Filesize,
|
||||||
|
len: types::Filesize,
|
||||||
|
advice: types::Advice,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let table = self.table();
|
||||||
|
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?;
|
||||||
|
let f = file_entry.get_cap(FileCaps::ADVISE)?;
|
||||||
|
f.advise(offset, len, advice.into())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_allocate(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
offset: types::Filesize,
|
||||||
|
len: types::Filesize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_close(&self, fd: types::Fd) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_datasync(&self, fd: types::Fd) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_fdstat_get(&self, fd: types::Fd) -> Result<types::Fdstat, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_fdstat_set_rights(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
fs_rights_base: types::Rights,
|
||||||
|
fs_rights_inheriting: types::Rights,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_filestat_set_times(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
atim: types::Timestamp,
|
||||||
|
mtim: types::Timestamp,
|
||||||
|
fst_flags: types::Fstflags,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_pread(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
iovs: &types::IovecArray<'_>,
|
||||||
|
offset: types::Filesize,
|
||||||
|
) -> Result<types::Size, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_write(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
ciovs: &types::CiovecArray<'_>,
|
||||||
|
) -> Result<types::Size, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_pwrite(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
ciovs: &types::CiovecArray<'_>,
|
||||||
|
offset: types::Filesize,
|
||||||
|
) -> Result<types::Size, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_prestat_get(&self, fd: types::Fd) -> Result<types::Prestat, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_prestat_dir_name(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
path: &GuestPtr<u8>,
|
||||||
|
path_len: types::Size,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_readdir(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
buf: &GuestPtr<u8>,
|
||||||
|
buf_len: types::Size,
|
||||||
|
cookie: types::Dircookie,
|
||||||
|
) -> Result<types::Size, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_renumber(&self, from: types::Fd, to: types::Fd) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_seek(
|
||||||
|
&self,
|
||||||
|
fd: types::Fd,
|
||||||
|
offset: types::Filedelta,
|
||||||
|
whence: types::Whence,
|
||||||
|
) -> Result<types::Filesize, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_sync(&self, fd: types::Fd) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_create_directory(
|
||||||
|
&self,
|
||||||
|
dirfd: types::Fd,
|
||||||
|
path: &GuestPtr<'_, str>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_filestat_get(
|
||||||
|
&self,
|
||||||
|
dirfd: types::Fd,
|
||||||
|
flags: types::Lookupflags,
|
||||||
|
path: &GuestPtr<'_, str>,
|
||||||
|
) -> Result<types::Filestat, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_filestat_set_times(
|
||||||
|
&self,
|
||||||
|
dirfd: types::Fd,
|
||||||
|
flags: types::Lookupflags,
|
||||||
|
path: &GuestPtr<'_, str>,
|
||||||
|
atim: types::Timestamp,
|
||||||
|
mtim: types::Timestamp,
|
||||||
|
fst_flags: types::Fstflags,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_link(
|
||||||
|
&self,
|
||||||
|
old_fd: types::Fd,
|
||||||
|
old_flags: types::Lookupflags,
|
||||||
|
old_path: &GuestPtr<'_, str>,
|
||||||
|
new_fd: types::Fd,
|
||||||
|
new_path: &GuestPtr<'_, str>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_open(
|
||||||
|
&self,
|
||||||
|
dirfd: types::Fd,
|
||||||
|
dirflags: types::Lookupflags,
|
||||||
|
path: &GuestPtr<'_, str>,
|
||||||
|
oflags: types::Oflags,
|
||||||
|
fs_rights_base: types::Rights,
|
||||||
|
fs_rights_inheriting: types::Rights,
|
||||||
|
fdflags: types::Fdflags,
|
||||||
|
) -> Result<types::Fd, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_readlink(
|
||||||
|
&self,
|
||||||
|
dirfd: types::Fd,
|
||||||
|
path: &GuestPtr<'_, str>,
|
||||||
|
buf: &GuestPtr<u8>,
|
||||||
|
buf_len: types::Size,
|
||||||
|
) -> Result<types::Size, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_remove_directory(
|
||||||
|
&self,
|
||||||
|
dirfd: types::Fd,
|
||||||
|
path: &GuestPtr<'_, str>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_rename(
|
||||||
|
&self,
|
||||||
|
old_fd: types::Fd,
|
||||||
|
old_path: &GuestPtr<'_, str>,
|
||||||
|
new_fd: types::Fd,
|
||||||
|
new_path: &GuestPtr<'_, str>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_symlink(
|
||||||
|
&self,
|
||||||
|
old_path: &GuestPtr<'_, str>,
|
||||||
|
dirfd: types::Fd,
|
||||||
|
new_path: &GuestPtr<'_, str>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_unlink_file(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_oneoff(
|
||||||
|
&self,
|
||||||
|
subs: &GuestPtr<types::Subscription>,
|
||||||
|
events: &GuestPtr<types::Event>,
|
||||||
|
nsubscriptions: types::Size,
|
||||||
|
) -> Result<types::Size, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn proc_exit(&self, _rval: types::Exitcode) -> Result<(), ()> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn proc_raise(&self, _sig: types::Signal) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sched_yield(&self) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random_get(&self, buf: &GuestPtr<u8>, buf_len: types::Size) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sock_recv(
|
||||||
|
&self,
|
||||||
|
_fd: types::Fd,
|
||||||
|
_ri_data: &types::IovecArray<'_>,
|
||||||
|
_ri_flags: types::Riflags,
|
||||||
|
) -> Result<(types::Size, types::Roflags), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sock_send(
|
||||||
|
&self,
|
||||||
|
_fd: types::Fd,
|
||||||
|
_si_data: &types::CiovecArray<'_>,
|
||||||
|
_si_flags: types::Siflags,
|
||||||
|
) -> Result<types::Size, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sock_shutdown(&self, _fd: types::Fd, _how: types::Sdflags) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<types::Advice> for system_interface::fs::Advice {
|
||||||
|
fn from(advice: types::Advice) -> system_interface::fs::Advice {
|
||||||
|
match advice {
|
||||||
|
types::Advice::Normal => system_interface::fs::Advice::Normal,
|
||||||
|
types::Advice::Sequential => system_interface::fs::Advice::Sequential,
|
||||||
|
types::Advice::Random => system_interface::fs::Advice::Random,
|
||||||
|
types::Advice::Willneed => system_interface::fs::Advice::WillNeed,
|
||||||
|
types::Advice::Dontneed => system_interface::fs::Advice::DontNeed,
|
||||||
|
types::Advice::Noreuse => system_interface::fs::Advice::NoReuse,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
crates/wasi-c2/src/table.rs
Normal file
46
crates/wasi-c2/src/table.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use crate::Error;
|
||||||
|
use std::any::Any;
|
||||||
|
use std::cell::{RefCell, RefMut};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub struct Table {
|
||||||
|
map: HashMap<u32, RefCell<Box<dyn Any>>>,
|
||||||
|
next_key: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Table {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Table {
|
||||||
|
map: HashMap::new(),
|
||||||
|
next_key: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, a: impl Any + Sized) -> u32 {
|
||||||
|
let key = self.next_key;
|
||||||
|
self.next_key += 1;
|
||||||
|
self.map.insert(key, RefCell::new(Box::new(a)));
|
||||||
|
key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo: we can refine these errors and translate them to Exist at abi
|
||||||
|
pub fn get<T: Any + Sized>(&self, key: u32) -> Result<RefMut<T>, Error> {
|
||||||
|
if let Some(refcell) = self.map.get(&key) {
|
||||||
|
if let Ok(refmut) = refcell.try_borrow_mut() {
|
||||||
|
if refmut.is::<T>() {
|
||||||
|
Ok(RefMut::map(refmut, |r| r.downcast_mut::<T>().unwrap()))
|
||||||
|
} else {
|
||||||
|
Err(Error::Exist) // Exists at another type
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(Error::Exist) // Does exist, but borrowed
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(Error::Exist) // Does not exist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete(&mut self, key: u32) -> Option<Box<dyn Any>> {
|
||||||
|
self.map.remove(&key).map(|rc| RefCell::into_inner(rc))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user