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