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
34#[cfg(feature = "enable-serde")]
35use serde::{Deserialize, Serialize};
36use virtual_fs::{FileOpener, FileSystem, FsError, OpenOptions, VirtualFile};
37use wasmer_wasix_types::wasi::{
38 Disposition, Errno, Fd as WasiFd, Rights, Signal, Snapshot0Clockid,
39};
40
41pub use self::{
42 builder::*,
43 env::{WasiEnv, WasiEnvInit, WasiModuleInstanceHandles, WasiModuleTreeHandles},
44 func_env::WasiFunctionEnv,
45 types::*,
46};
47pub use crate::fs::{InodeGuard, InodeWeakGuard};
48use crate::{
49 fs::{WasiFs, WasiFsRoot, WasiInodes, WasiStateFileGuard, fs_error_into_wasi_err},
50 syscalls::types::*,
51 utils::WasiParkingLot,
52};
53pub(crate) use handles::*;
54pub(crate) use linker::*;
55
56pub const ALL_RIGHTS: Rights = Rights::all();
58
59#[allow(dead_code)]
60struct WasiStateOpener {
61 root_fs: WasiFsRoot,
62}
63
64impl FileOpener for WasiStateOpener {
65 fn open(
66 &self,
67 path: &Path,
68 conf: &virtual_fs::OpenOptionsConfig,
69 ) -> virtual_fs::Result<Box<dyn VirtualFile + Send + Sync + 'static>> {
70 let mut new_options = self.root_fs.new_open_options();
71 new_options.options(conf.clone());
72 new_options.open(path)
73 }
74}
75
76#[derive(Debug, Default)]
79pub struct WasiFutex {
80 pub(crate) wakers: BTreeMap<u64, Option<Waker>>,
81}
82
83#[derive(Debug, Default)]
87pub struct WasiBusState {
88 poll_waker: WasiParkingLot,
89}
90
91impl WasiBusState {
92 #[allow(dead_code)]
96 pub fn get_poll_waker(&self) -> Waker {
97 self.poll_waker.get_waker()
98 }
99
100 #[allow(dead_code)]
103 pub fn poll_wake(&self) {
104 self.poll_waker.wake()
105 }
106
107 #[allow(dead_code)]
111 pub fn poll_wait(&self, timeout: Duration) -> bool {
112 self.poll_waker.wait(timeout)
113 }
114}
115
116#[derive(Debug, Default)]
118#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
119pub(crate) struct WasiFutexState {
120 pub poller_seed: u64,
121 pub futexes: HashMap<u64, WasiFutex>,
122}
123
124#[derive(Debug)]
131#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
132pub(crate) struct WasiState {
133 pub secret: [u8; 32],
134
135 pub fs: WasiFs,
136 pub inodes: WasiInodes,
137 pub futexs: Mutex<WasiFutexState>,
138 pub clock_offset: Mutex<HashMap<Snapshot0Clockid, i64>>,
139 pub args: Mutex<Vec<String>>,
140 pub envs: Mutex<Vec<Vec<u8>>>,
141 pub signals: Mutex<HashMap<Signal, Disposition>>,
142
143 pub preopen: Vec<String>,
146}
147
148impl WasiState {
149 }
163
164impl WasiState {
166 pub(crate) fn fs_read_dir<P: AsRef<Path>>(
167 &self,
168 path: P,
169 ) -> Result<virtual_fs::ReadDir, Errno> {
170 self.fs
171 .root_fs
172 .read_dir(path.as_ref())
173 .map_err(fs_error_into_wasi_err)
174 }
175
176 pub(crate) fn fs_create_dir<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
177 self.fs
178 .root_fs
179 .create_dir(path.as_ref())
180 .map_err(fs_error_into_wasi_err)
181 }
182
183 pub(crate) fn fs_remove_dir<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
184 self.fs
185 .root_fs
186 .remove_dir(path.as_ref())
187 .map_err(fs_error_into_wasi_err)
188 }
189
190 pub(crate) async fn fs_rename<P: AsRef<Path>, Q: AsRef<Path>>(
191 &self,
192 from: P,
193 to: Q,
194 ) -> Result<(), Errno> {
195 self.fs
196 .root_fs
197 .rename(from.as_ref(), to.as_ref())
198 .await
199 .map_err(fs_error_into_wasi_err)
200 }
201
202 pub(crate) fn fs_remove_file<P: AsRef<Path>>(&self, path: P) -> Result<(), Errno> {
203 self.fs
204 .root_fs
205 .remove_file(path.as_ref())
206 .map_err(fs_error_into_wasi_err)
207 }
208
209 pub(crate) fn fs_new_open_options(&self) -> OpenOptions<'_> {
210 self.fs.root_fs.new_open_options()
211 }
212
213 #[cfg(feature = "enable-serde")]
215 pub fn freeze(&self) -> Option<Vec<u8>> {
216 bincode::serialize(self).ok()
217 }
218
219 #[cfg(feature = "enable-serde")]
221 pub fn unfreeze(bytes: &[u8]) -> Option<Self> {
222 bincode::deserialize(bytes).ok()
223 }
224
225 pub fn stdout(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
227 self.std_dev_get(__WASI_STDOUT_FILENO)
228 }
229
230 pub fn stderr(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
232 self.std_dev_get(__WASI_STDERR_FILENO)
233 }
234
235 pub fn stdin(&self) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
237 self.std_dev_get(__WASI_STDIN_FILENO)
238 }
239
240 fn std_dev_get(
243 &self,
244 fd: WasiFd,
245 ) -> Result<Option<Box<dyn VirtualFile + Send + Sync + 'static>>, FsError> {
246 let ret = WasiStateFileGuard::new(self, fd)?.map(|a| {
247 let ret = Box::new(a);
248 let ret: Box<dyn VirtualFile + Send + Sync + 'static> = ret;
249 ret
250 });
251 Ok(ret)
252 }
253
254 pub fn fork(&self) -> Self {
256 WasiState {
257 fs: self.fs.fork(),
258 secret: self.secret,
259 inodes: self.inodes.clone(),
260 futexs: Default::default(),
261 clock_offset: Mutex::new(self.clock_offset.lock().unwrap().clone()),
262 args: Mutex::new(self.args.lock().unwrap().clone()),
263 envs: Mutex::new(self.envs.lock().unwrap().clone()),
264 signals: Mutex::new(self.signals.lock().unwrap().clone()),
265 preopen: self.preopen.clone(),
266 }
267 }
268}