wasi_common/sync/
mod.rs

1//! The `wasi-cap-std-sync` crate provides impl of `WasiFile` and `WasiDir` in
2//! terms of `cap_std::fs::{File, Dir}`. These types provide sandboxed access
3//! to the local filesystem on both Unix and Windows.
4//!
5//! All syscalls are hidden behind the `cap-std` hierarchy, with the lone
6//! exception of the `sched` implementation, which is provided for both unix
7//! and windows in separate modules.
8//!
9//! Any `wasi_common::{WasiCtx, WasiCtxBuilder}` is interoperable with the
10//! implementations provided in `wasi_common::sync`. However, for convenience,
11//! this module provides its own `WasiCtxBuilder` that hooks up to all of the
12//! crate's components, i.e. it fills in all of the arguments to
13//! `WasiCtx::builder(...)`, presents `preopen_dir` in terms of
14//! `cap_std::fs::Dir`, and provides convenience methods for inheriting the
15//! parent process's stdio, args, and env.
16
17pub mod clocks;
18pub mod dir;
19pub mod file;
20pub mod net;
21pub mod sched;
22pub mod stdio;
23
24pub use cap_std::ambient_authority;
25pub use cap_std::fs::Dir;
26pub use cap_std::net::TcpListener;
27pub use clocks::clocks_ctx;
28pub use sched::sched_ctx;
29
30use self::net::Socket;
31use crate::{file::FileAccessMode, table::Table, Error, WasiCtx, WasiFile};
32use cap_rand::{Rng, RngCore, SeedableRng};
33use std::mem;
34use std::path::Path;
35
36pub struct WasiCtxBuilder {
37    ctx: WasiCtx,
38    built: bool,
39}
40
41impl WasiCtxBuilder {
42    pub fn new() -> Self {
43        WasiCtxBuilder {
44            ctx: WasiCtx::new(random_ctx(), clocks_ctx(), sched_ctx(), Table::new()),
45            built: false,
46        }
47    }
48    pub fn env(&mut self, var: &str, value: &str) -> Result<&mut Self, crate::StringArrayError> {
49        self.ctx.push_env(var, value)?;
50        Ok(self)
51    }
52    pub fn envs(&mut self, env: &[(String, String)]) -> Result<&mut Self, crate::StringArrayError> {
53        for (k, v) in env {
54            self.ctx.push_env(k, v)?;
55        }
56        Ok(self)
57    }
58    pub fn inherit_env(&mut self) -> Result<&mut Self, crate::StringArrayError> {
59        for (key, value) in std::env::vars() {
60            self.ctx.push_env(&key, &value)?;
61        }
62        Ok(self)
63    }
64    pub fn arg(&mut self, arg: &str) -> Result<&mut Self, crate::StringArrayError> {
65        self.ctx.push_arg(arg)?;
66        Ok(self)
67    }
68    pub fn args(&mut self, arg: &[String]) -> Result<&mut Self, crate::StringArrayError> {
69        for a in arg {
70            self.ctx.push_arg(&a)?;
71        }
72        Ok(self)
73    }
74    pub fn inherit_args(&mut self) -> Result<&mut Self, crate::StringArrayError> {
75        for arg in std::env::args() {
76            self.ctx.push_arg(&arg)?;
77        }
78        Ok(self)
79    }
80    pub fn stdin(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
81        self.ctx.set_stdin(f);
82        self
83    }
84    pub fn stdout(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
85        self.ctx.set_stdout(f);
86        self
87    }
88    pub fn stderr(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
89        self.ctx.set_stderr(f);
90        self
91    }
92    pub fn inherit_stdin(&mut self) -> &mut Self {
93        self.stdin(Box::new(crate::sync::stdio::stdin()))
94    }
95    pub fn inherit_stdout(&mut self) -> &mut Self {
96        self.stdout(Box::new(crate::sync::stdio::stdout()))
97    }
98    pub fn inherit_stderr(&mut self) -> &mut Self {
99        self.stderr(Box::new(crate::sync::stdio::stderr()))
100    }
101    pub fn inherit_stdio(&mut self) -> &mut Self {
102        self.inherit_stdin().inherit_stdout().inherit_stderr()
103    }
104    pub fn preopened_dir(
105        &mut self,
106        dir: Dir,
107        guest_path: impl AsRef<Path>,
108    ) -> Result<&mut Self, Error> {
109        let dir = Box::new(crate::sync::dir::Dir::from_cap_std(dir));
110        self.ctx.push_preopened_dir(dir, guest_path)?;
111        Ok(self)
112    }
113    pub fn preopened_socket(
114        &mut self,
115        fd: u32,
116        socket: impl Into<Socket>,
117    ) -> Result<&mut Self, Error> {
118        let socket: Socket = socket.into();
119        let file: Box<dyn WasiFile> = socket.into();
120        self.ctx
121            .insert_file(fd, file, FileAccessMode::READ | FileAccessMode::WRITE);
122        Ok(self)
123    }
124    pub fn build(&mut self) -> WasiCtx {
125        assert!(!self.built);
126        let WasiCtxBuilder { ctx, .. } = mem::replace(self, Self::new());
127        self.built = true;
128        ctx
129    }
130}
131
132pub fn random_ctx() -> Box<dyn RngCore + Send + Sync> {
133    let mut rng = cap_rand::thread_rng(cap_rand::ambient_authority());
134    Box::new(cap_rand::rngs::StdRng::from_seed(rng.r#gen()))
135}
136
137#[cfg(feature = "wasmtime")]
138super::define_wasi!(block_on);