diff --git a/Cargo.lock b/Cargo.lock index d63fb09e39..824da0733f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2718,6 +2718,7 @@ name = "wasmtime-cli" version = "0.22.0" dependencies = [ "anyhow", + "cap-std", "env_logger 0.8.2", "file-per-thread-logger", "filecheck", @@ -2733,6 +2734,7 @@ dependencies = [ "tempfile", "test-programs", "tracing-subscriber", + "wasi-cap-std-sync", "wasi-common", "wasmparser", "wasmtime", diff --git a/Cargo.toml b/Cargo.toml index 7799977b7d..8a8e5faf87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ wasmtime-wast = { path = "crates/wast", version = "0.22.0" } wasmtime-wasi = { path = "crates/wasi", version = "0.22.0" } wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "0.22.0", optional = true } wasi-common = { path = "crates/wasi-common", version = "0.22.0" } +wasi-cap-std-sync = { path = "crates/wasi-common/cap-std-sync", version = "0.22.0" } structopt = { version = "0.3.5", features = ["color", "suggestions"] } object = { version = "0.22.0", default-features = false, features = ["write"] } anyhow = "1.0.19" @@ -44,6 +45,7 @@ log = "0.4.8" rayon = "1.2.1" humantime = "2.0.0" wasmparser = "0.71.0" +cap-std = "0.11.0" [dev-dependencies] env_logger = "0.8.1" diff --git a/crates/wasi-common/cap-std-sync/src/lib.rs b/crates/wasi-common/cap-std-sync/src/lib.rs index d1fad6bd46..f1da8ec6a4 100644 --- a/crates/wasi-common/cap-std-sync/src/lib.rs +++ b/crates/wasi-common/cap-std-sync/src/lib.rs @@ -25,6 +25,13 @@ impl WasiCtxBuilder { let s = self.0.env(var, value)?; Ok(WasiCtxBuilder(s)) } + pub fn envs(self, env: &[(String, String)]) -> Result { + let mut s = self; + for (k, v) in env { + s = s.env(k, v)?; + } + Ok(s) + } pub fn inherit_env(self) -> Result { let mut s = self.0; for (key, value) in std::env::vars() { @@ -36,6 +43,13 @@ impl WasiCtxBuilder { let s = self.0.arg(arg)?; Ok(WasiCtxBuilder(s)) } + pub fn args(self, arg: &[String]) -> Result { + let mut s = self; + for a in arg { + s = s.arg(&a)?; + } + Ok(s) + } pub fn stdin(self, f: Box) -> Self { WasiCtxBuilder(self.0.stdin(f)) } diff --git a/src/commands/run.rs b/src/commands/run.rs index e1b891d598..1caec3532d 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -2,18 +2,19 @@ use crate::{init_file_per_thread_logger, CommonOptions}; use anyhow::{bail, Context as _, Result}; +use cap_std::fs::Dir; use std::thread; use std::time::Duration; use std::{ ffi::{OsStr, OsString}, - fs::File, path::{Component, PathBuf}, process, }; use structopt::{clap::AppSettings, StructOpt}; -use wasi_common::{preopen_dir, WasiCtxBuilder}; +use wasi_cap_std_sync::WasiCtxBuilder; use wasmtime::{Engine, Func, Linker, Module, Store, Trap, Val, ValType}; -use wasmtime_wasi::Wasi; +use wasmtime_wasi::snapshots::preview_0::Wasi as WasiSnapshot0; +use wasmtime_wasi::snapshots::preview_1::Wasi as WasiSnapshot1; #[cfg(feature = "wasi-nn")] use wasmtime_wasi_nn::{WasiNn, WasiNnCtx}; @@ -139,7 +140,7 @@ impl RunCommand { let argv = self.compute_argv(); let mut linker = Linker::new(&store); - populate_with_wasi(&mut linker, &preopen_dirs, &argv, &self.vars)?; + populate_with_wasi(&mut linker, preopen_dirs, &argv, &self.vars)?; // Load the preload wasm modules. for (name, path) in self.preloads.iter() { @@ -195,20 +196,21 @@ impl RunCommand { Ok(()) } - fn compute_preopen_dirs(&self) -> Result> { + fn compute_preopen_dirs(&self) -> Result> { let mut preopen_dirs = Vec::new(); for dir in self.dirs.iter() { preopen_dirs.push(( dir.clone(), - preopen_dir(dir).with_context(|| format!("failed to open directory '{}'", dir))?, + unsafe { Dir::open_ambient_dir(dir) } + .with_context(|| format!("failed to open directory '{}'", dir))?, )); } for (guest, host) in self.map_dirs.iter() { preopen_dirs.push(( guest.clone(), - preopen_dir(host) + unsafe { Dir::open_ambient_dir(host) } .with_context(|| format!("failed to open directory '{}'", host))?, )); } @@ -340,23 +342,25 @@ impl RunCommand { /// Populates the given `Linker` with WASI APIs. fn populate_with_wasi( linker: &mut Linker, - preopen_dirs: &[(String, File)], + preopen_dirs: Vec<(String, Dir)>, argv: &[String], vars: &[(String, String)], ) -> Result<()> { - let mk_cx = || { - // Add the current snapshot to the linker. - let mut cx = WasiCtxBuilder::new(); - cx.inherit_stdio().args(argv).envs(vars); + use std::cell::RefCell; + use std::rc::Rc; - for (name, file) in preopen_dirs { - cx.preopened_dir(file.try_clone()?, name); - } + // Add the current snapshot to the linker. + let mut builder = WasiCtxBuilder::new(); + builder = builder.inherit_stdio().args(argv)?.envs(vars)?; - cx.build() - }; - let wasi = Wasi::new(linker.store(), mk_cx()?); - wasi.add_to_linker(linker)?; + for (name, dir) in preopen_dirs.into_iter() { + builder = builder.preopened_dir(dir, name)?; + } + + let cx = Rc::new(RefCell::new(builder.build()?)); + + WasiSnapshot1::new(linker.store(), cx.clone()).add_to_linker(linker)?; + WasiSnapshot0::new(linker.store(), cx).add_to_linker(linker)?; #[cfg(feature = "wasi-nn")] { @@ -364,8 +368,5 @@ fn populate_with_wasi( wasi_nn.add_to_linker(linker)?; } - let wasi = wasmtime_wasi::old::snapshot_0::Wasi::new(linker.store(), mk_cx()?); - wasi.add_to_linker(linker)?; - Ok(()) }