#![allow(clippy::cognitive_complexity, clippy::too_many_arguments)]
mod builder;
pub mod context_switching;
mod env;
mod func_env;
mod handles;
mod linker;
mod types;
use std::{
collections::{BTreeMap, HashMap},
path::Path,
sync::Mutex,
task::Waker,
time::Duration,
};
use virtual_fs::{FileOpener, FileSystem, FsError, OpenOptions, VirtualFile};
use wasmer_wasix_types::wasi::{
Disposition, Errno, Fd as WasiFd, Rights, Signal, Snapshot0Clockid,
};
pub use self::{
builder::*,
env::{WasiEnv, WasiEnvInit, WasiModuleInstanceHandles, WasiModuleTreeHandles},
func_env::WasiFunctionEnv,
types::*,
};
pub use crate::fs::{InodeGuard, InodeWeakGuard};
use crate::{
fs::{WasiFs, WasiFsRoot, WasiInodes, WasiStateFileGuard, fs_error_into_wasi_err},
syscalls::types::*,
utils::WasiParkingLot,
};
pub(crate) use handles::*;
pub(crate) use linker::*;
pub const ALL_RIGHTS: Rights = Rights::all();
#[allow(dead_code)]
struct WasiStateOpener {
root_fs: WasiFsRoot,
}
impl FileOpener for WasiStateOpener {
fn open(
&self,
path: &Path,
conf: &virtual_fs::OpenOptionsConfig,
) -> virtual_fs::Result<Box<dyn VirtualFile + Send + Sync + 'static>> {
let mut new_options = self.root_fs.new_open_options();
new_options.options(conf.clone());
new_options.open(path)
}
}
#[derive(Debug, Default)]
pub struct WasiFutex {
pub(crate) wakers: BTreeMap<u64, Option<Waker>>,
}
#[derive(Debug, Default)]
pub struct WasiBusState {
poll_waker: WasiParkingLot,
}
impl WasiBusState {
#[allow(dead_code)]
pub fn get_poll_waker(&self) -> Waker {
self.poll_waker.get_waker()
}
#[allow(dead_code)]
pub fn poll_wake(&self) {
self.poll_waker.wake()
}
#[allow(dead_code)]
pub fn poll_wait(&self, timeout: Duration) -> bool {
self.poll_waker.wait(timeout)
}
}
#[derive(Debug, Default)]
pub(crate) struct WasiFutexState {
pub poller_seed: u64,
pub futexes: HashMap<u64, WasiFutex>,
}
#[derive(Debug)]
pub(crate) struct WasiState {
pub secret: [u8; 32],
pub fs: WasiFs,
pub inodes: WasiInodes,
pub futexs: Mutex<WasiFutexState>,
pub clock_offset: Mutex<HashMap<Snapshot0Clockid, i64>>,
pub args: Mutex<Vec<String>>,
pub envs: Mutex<Vec<Vec<u8>>>,
pub signals: Mutex<HashMap<Signal, Disposition>>,
pub preopen: Vec<String>,
}
impl WasiState {
}
impl WasiState {
pub(crate) fn fs_read_dir<P: AsRef<Path>>(
&self,
path: P,
) -> Result<virtual_fs::ReadDir, Errno> {
self.fs
.root_fs
.read_dir(path.as_ref())
.map_err(fs_error_into_wasi_err)
}
pub(crate) fn fs_create_dir<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
self.fs
.root_fs
.create_dir(path.as_ref())
.map_err(fs_error_into_wasi_err)
}
pub(crate) fn fs_remove_dir<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
self.fs
.root_fs
.remove_dir(path.as_ref())
.map_err(fs_error_into_wasi_err)
}
pub(crate) async fn fs_rename<P: AsRef<Path>, Q: AsRef<Path>>(
&self,
from: P,
to: Q,
) -> Result<(), Errno> {
self.fs
.root_fs
.rename(from.as_ref(), to.as_ref())
.await
.map_err(fs_error_into_wasi_err)
}
pub(crate) fn fs_remove_file<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
self.fs
.root_fs
.remove_file(path.as_ref())
.map_err(fs_error_into_wasi_err)
}
pub(crate) fn fs_new_open_options(&self) -> OpenOptions<'_> {
self.fs.root_fs.new_open_options()
}
pub fn stdout(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
self.std_dev_get(__WASI_STDOUT_FILENO)
}
pub fn stderr(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
self.std_dev_get(__WASI_STDERR_FILENO)
}
pub fn stdin(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
self.std_dev_get(__WASI_STDIN_FILENO)
}
fn std_dev_get(
&self,
fd: WasiFd,
) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
let ret = WasiStateFileGuard::new(self, fd)?.map(|a| {
let ret = Box::new(a);
let ret: Box<dyn VirtualFile + Send + Sync + 'static> = ret;
ret
});
Ok(ret)
}
pub fn fork(&self) -> Self {
WasiState {
fs: self.fs.fork(),
secret: self.secret,
inodes: self.inodes.clone(),
futexs: Default::default(),
clock_offset: Mutex::new(self.clock_offset.lock().unwrap().clone()),
args: Mutex::new(self.args.lock().unwrap().clone()),
envs: Mutex::new(self.envs.lock().unwrap().clone()),
signals: Mutex::new(self.signals.lock().unwrap().clone()),
preopen: self.preopen.clone(),
}
}
}