1#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
2
3mod dir;
4mod file;
5pub mod net;
6pub mod sched;
7pub mod stdio;
8
9use crate::sched::sched_ctx;
10pub use dir::Dir;
11pub use file::File;
12pub use net::*;
13use std::future::Future;
14use std::mem;
15use std::path::Path;
16use wasi_cap_std_sync::net::Socket;
17pub use wasi_cap_std_sync::{clocks_ctx, random_ctx};
18use wasi_common::{file::FileAccessMode, Error, Table, WasiCtx, WasiFile};
19
20pub struct WasiCtxBuilder {
21 ctx: WasiCtx,
22 built: bool,
23}
24
25impl WasiCtxBuilder {
26 pub fn new() -> Self {
27 WasiCtxBuilder {
28 ctx: WasiCtx::new(random_ctx(), clocks_ctx(), sched_ctx(), Table::new()),
29 built: false,
30 }
31 }
32 pub fn env(
33 &mut self,
34 var: &str,
35 value: &str,
36 ) -> Result<&mut Self, wasi_common::StringArrayError> {
37 self.ctx.push_env(var, value)?;
38 Ok(self)
39 }
40 pub fn envs(
41 &mut self,
42 env: &[(String, String)],
43 ) -> Result<&mut Self, wasi_common::StringArrayError> {
44 for (k, v) in env {
45 self.ctx.push_env(k, v)?;
46 }
47 Ok(self)
48 }
49 pub fn inherit_env(&mut self) -> Result<&mut Self, wasi_common::StringArrayError> {
50 for (key, value) in std::env::vars() {
51 self.ctx.push_env(&key, &value)?;
52 }
53 Ok(self)
54 }
55 pub fn arg(&mut self, arg: &str) -> Result<&mut Self, wasi_common::StringArrayError> {
56 self.ctx.push_arg(arg)?;
57 Ok(self)
58 }
59 pub fn args(&mut self, arg: &[String]) -> Result<&mut Self, wasi_common::StringArrayError> {
60 for a in arg {
61 self.ctx.push_arg(&a)?;
62 }
63 Ok(self)
64 }
65 pub fn inherit_args(&mut self) -> Result<&mut Self, wasi_common::StringArrayError> {
66 for arg in std::env::args() {
67 self.ctx.push_arg(&arg)?;
68 }
69 Ok(self)
70 }
71 pub fn stdin(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
72 self.ctx.set_stdin(f);
73 self
74 }
75 pub fn stdout(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
76 self.ctx.set_stdout(f);
77 self
78 }
79 pub fn stderr(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
80 self.ctx.set_stderr(f);
81 self
82 }
83 pub fn inherit_stdin(&mut self) -> &mut Self {
84 self.stdin(Box::new(crate::stdio::stdin()))
85 }
86 pub fn inherit_stdout(&mut self) -> &mut Self {
87 self.stdout(Box::new(crate::stdio::stdout()))
88 }
89 pub fn inherit_stderr(&mut self) -> &mut Self {
90 self.stderr(Box::new(crate::stdio::stderr()))
91 }
92 pub fn inherit_stdio(&mut self) -> &mut Self {
93 self.inherit_stdin().inherit_stdout().inherit_stderr()
94 }
95 pub fn preopened_dir(
96 &mut self,
97 dir: cap_std::fs::Dir,
98 guest_path: impl AsRef<Path>,
99 ) -> Result<&mut Self, Error> {
100 let dir = Box::new(crate::dir::Dir::from_cap_std(dir));
101 self.ctx.push_preopened_dir(dir, guest_path)?;
102 Ok(self)
103 }
104 pub fn preopened_socket(
105 &mut self,
106 fd: u32,
107 socket: impl Into<Socket>,
108 ) -> Result<&mut Self, Error> {
109 let socket: Socket = socket.into();
110 let file: Box<dyn WasiFile> = socket.into();
111 self.ctx
112 .insert_file(fd, file, FileAccessMode::READ | FileAccessMode::WRITE);
113 Ok(self)
114 }
115
116 pub fn build(&mut self) -> WasiCtx {
117 assert!(!self.built);
118 let WasiCtxBuilder { ctx, .. } = mem::replace(self, Self::new());
119 self.built = true;
120 ctx
121 }
122}
123
124pub(crate) fn block_on_dummy_executor<'a, F, Fut, T>(f: F) -> Result<T, Error>
133where
134 F: FnOnce() -> Fut + Send + 'a,
135 Fut: Future<Output = Result<T, Error>>,
136 T: Send + 'static,
137{
138 tokio::task::block_in_place(move || {
139 wiggle::run_in_dummy_executor(f()).expect("wrapped operation should be synchronous")
140 })
141}