1#![allow(clippy::cognitive_complexity, clippy::too_many_arguments)]
17
18mod builder;
19pub mod context_switching;
20mod env;
21mod func_env;
22mod handles;
23mod linker;
24mod types;
25
26use std::{
27 collections::{BTreeMap, HashMap},
28 path::Path,
29 sync::Mutex,
30 task::Waker,
31 time::Duration,
32};
33
34use virtual_fs::{FileOpener, FileSystem, FsError, OpenOptions, VirtualFile};
35use wasmer_wasix_types::wasi::{
36 Disposition, Errno, Fd as WasiFd, Rights, Signal, Snapshot0Clockid,
37};
38
39pub use self::{
40 builder::*,
41 env::{WasiEnv, WasiEnvInit, WasiModuleInstanceHandles, WasiModuleTreeHandles},
42 func_env::WasiFunctionEnv,
43 types::*,
44};
45pub use crate::fs::{InodeGuard, InodeWeakGuard};
46use crate::{
47 fs::{WasiFs, WasiFsRoot, WasiInodes, WasiStateFileGuard, fs_error_into_wasi_err},
48 syscalls::types::*,
49 utils::WasiParkingLot,
50};
51pub(crate) use handles::*;
52pub(crate) use linker::*;
53
54pub const ALL_RIGHTS: Rights = Rights::all();
56
57#[allow(dead_code)]
58struct WasiStateOpener {
59 root_fs: WasiFsRoot,
60}
61
62impl FileOpener for WasiStateOpener {
63 fn open(
64 &self,
65 path: &Path,
66 conf: &virtual_fs::OpenOptionsConfig,
67 ) -> virtual_fs::Result<Box<dyn VirtualFile + Send + Sync + 'static>> {
68 let mut new_options = self.root_fs.new_open_options();
69 new_options.options(conf.clone());
70 new_options.open(path)
71 }
72}
73
74#[derive(Debug, Default)]
77pub struct WasiFutex {
78 pub(crate) wakers: BTreeMap<u64, Option<Waker>>,
79}
80
81#[derive(Debug, Default)]
85pub struct WasiBusState {
86 poll_waker: WasiParkingLot,
87}
88
89impl WasiBusState {
90 #[allow(dead_code)]
94 pub fn get_poll_waker(&self) -> Waker {
95 self.poll_waker.get_waker()
96 }
97
98 #[allow(dead_code)]
101 pub fn poll_wake(&self) {
102 self.poll_waker.wake()
103 }
104
105 #[allow(dead_code)]
109 pub fn poll_wait(&self, timeout: Duration) -> bool {
110 self.poll_waker.wait(timeout)
111 }
112}
113
114#[derive(Debug, Default)]
116pub(crate) struct WasiFutexState {
117 pub poller_seed: u64,
118 pub futexes: HashMap<u64, WasiFutex>,
119}
120
121#[derive(Debug)]
128pub(crate) struct WasiState {
129 pub secret: [u8; 32],
130
131 pub fs: WasiFs,
132 pub inodes: WasiInodes,
133 pub futexs: Mutex<WasiFutexState>,
134 pub clock_offset: Mutex<HashMap<Snapshot0Clockid, i64>>,
135 pub args: Mutex<Vec<String>>,
136 pub envs: Mutex<Vec<Vec<u8>>>,
137 pub signals: Mutex<HashMap<Signal, Disposition>>,
138 pub signal_handler_registered: std::sync::atomic::AtomicBool,
147
148 pub preopen: Vec<String>,
151}
152
153impl WasiState {
154 }
168
169impl WasiState {
171 pub(crate) fn fs_read_dir<P: AsRef<Path>>(
172 &self,
173 path: P,
174 ) -> Result<virtual_fs::ReadDir, Errno> {
175 self.fs
176 .root_fs
177 .read_dir(path.as_ref())
178 .map_err(fs_error_into_wasi_err)
179 }
180
181 pub(crate) fn fs_create_dir<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
182 self.fs
183 .root_fs
184 .create_dir(path.as_ref())
185 .map_err(fs_error_into_wasi_err)
186 }
187
188 pub(crate) fn fs_remove_dir<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
189 self.fs
190 .root_fs
191 .remove_dir(path.as_ref())
192 .map_err(fs_error_into_wasi_err)
193 }
194
195 pub(crate) async fn fs_rename<P: AsRef<Path>, Q: AsRef<Path>>(
196 &self,
197 from: P,
198 to: Q,
199 ) -> Result<(), Errno> {
200 self.fs
201 .root_fs
202 .rename(from.as_ref(), to.as_ref())
203 .await
204 .map_err(fs_error_into_wasi_err)
205 }
206
207 pub(crate) fn fs_remove_file<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
208 self.fs
209 .root_fs
210 .remove_file(path.as_ref())
211 .map_err(fs_error_into_wasi_err)
212 }
213
214 pub(crate) fn fs_new_open_options(&self) -> OpenOptions<'_> {
215 self.fs.root_fs.new_open_options()
216 }
217
218 pub fn stdout(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
220 self.std_dev_get(__WASI_STDOUT_FILENO)
221 }
222
223 pub fn stderr(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
225 self.std_dev_get(__WASI_STDERR_FILENO)
226 }
227
228 pub fn stdin(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
230 self.std_dev_get(__WASI_STDIN_FILENO)
231 }
232
233 fn std_dev_get(
236 &self,
237 fd: WasiFd,
238 ) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
239 let ret = WasiStateFileGuard::new(self, fd)?.map(|a| {
240 let ret = Box::new(a);
241 let ret: Box<dyn VirtualFile + Send + Sync + 'static> = ret;
242 ret
243 });
244 Ok(ret)
245 }
246
247 pub fn fork(&self) -> Self {
249 WasiState {
250 fs: self.fs.fork(),
251 secret: self.secret,
252 inodes: self.inodes.clone(),
253 futexs: Default::default(),
254 clock_offset: Mutex::new(self.clock_offset.lock().unwrap().clone()),
255 args: Mutex::new(self.args.lock().unwrap().clone()),
256 envs: Mutex::new(self.envs.lock().unwrap().clone()),
257 signals: Mutex::new(self.signals.lock().unwrap().clone()),
258 signal_handler_registered: std::sync::atomic::AtomicBool::new(false),
260 preopen: self.preopen.clone(),
261 }
262 }
263}