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
139 pub preopen: Vec<String>,
142}
143
144impl WasiState {
145 }
159
160impl WasiState {
162 pub(crate) fn fs_read_dir<P: AsRef<Path>>(
163 &self,
164 path: P,
165 ) -> Result<virtual_fs::ReadDir, Errno> {
166 self.fs
167 .root_fs
168 .read_dir(path.as_ref())
169 .map_err(fs_error_into_wasi_err)
170 }
171
172 pub(crate) fn fs_create_dir<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
173 self.fs
174 .root_fs
175 .create_dir(path.as_ref())
176 .map_err(fs_error_into_wasi_err)
177 }
178
179 pub(crate) fn fs_remove_dir<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
180 self.fs
181 .root_fs
182 .remove_dir(path.as_ref())
183 .map_err(fs_error_into_wasi_err)
184 }
185
186 pub(crate) async fn fs_rename<P: AsRef<Path>, Q: AsRef<Path>>(
187 &self,
188 from: P,
189 to: Q,
190 ) -> Result<(), Errno> {
191 self.fs
192 .root_fs
193 .rename(from.as_ref(), to.as_ref())
194 .await
195 .map_err(fs_error_into_wasi_err)
196 }
197
198 pub(crate) fn fs_remove_file<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
199 self.fs
200 .root_fs
201 .remove_file(path.as_ref())
202 .map_err(fs_error_into_wasi_err)
203 }
204
205 pub(crate) fn fs_new_open_options(&self) -> OpenOptions<'_> {
206 self.fs.root_fs.new_open_options()
207 }
208
209 pub fn stdout(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
211 self.std_dev_get(__WASI_STDOUT_FILENO)
212 }
213
214 pub fn stderr(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
216 self.std_dev_get(__WASI_STDERR_FILENO)
217 }
218
219 pub fn stdin(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
221 self.std_dev_get(__WASI_STDIN_FILENO)
222 }
223
224 fn std_dev_get(
227 &self,
228 fd: WasiFd,
229 ) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
230 let ret = WasiStateFileGuard::new(self, fd)?.map(|a| {
231 let ret = Box::new(a);
232 let ret: Box<dyn VirtualFile + Send + Sync + 'static> = ret;
233 ret
234 });
235 Ok(ret)
236 }
237
238 pub fn fork(&self) -> Self {
240 WasiState {
241 fs: self.fs.fork(),
242 secret: self.secret,
243 inodes: self.inodes.clone(),
244 futexs: Default::default(),
245 clock_offset: Mutex::new(self.clock_offset.lock().unwrap().clone()),
246 args: Mutex::new(self.args.lock().unwrap().clone()),
247 envs: Mutex::new(self.envs.lock().unwrap().clone()),
248 signals: Mutex::new(self.signals.lock().unwrap().clone()),
249 preopen: self.preopen.clone(),
250 }
251 }
252}