From b48e7fcc5d756a58d77e8047eebeb9458f084a86 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Fri, 29 Jan 2021 14:09:44 -0800 Subject: [PATCH] integrate with c-api --- Cargo.lock | 2 + crates/c-api/Cargo.toml | 4 +- crates/c-api/src/wasi.rs | 64 +++++++++++++++------- crates/wasi-common/cap-std-sync/src/lib.rs | 20 ++++++- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1dc096c77a..2a58151dd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3237,8 +3237,10 @@ name = "wasmtime-c-api" version = "0.19.0" dependencies = [ "anyhow", + "cap-std", "env_logger 0.8.2", "once_cell", + "wasi-cap-std-sync", "wasi-common", "wasmtime", "wasmtime-c-api-macros", diff --git a/crates/c-api/Cargo.toml b/crates/c-api/Cargo.toml index 14324ca0ef..6dd56f4464 100644 --- a/crates/c-api/Cargo.toml +++ b/crates/c-api/Cargo.toml @@ -28,11 +28,13 @@ wat = { version = "1.0.23", optional = true } # Optional dependencies for the `wasi` feature wasi-common = { path = "../wasi-common", optional = true } +wasi-cap-std-sync = { path = "../wasi-common/cap-std-sync", optional = true } wasmtime-wasi = { path = "../wasi", optional = true } +cap-std = { version = "0.12", optional = true } [features] default = ['jitdump', 'wat', 'wasi', 'cache'] lightbeam = ["wasmtime/lightbeam"] jitdump = ["wasmtime/jitdump"] cache = ["wasmtime/cache"] -wasi = ['wasi-common', 'wasmtime-wasi'] +wasi = ['wasi-common', 'wasi-cap-std-sync', 'wasmtime-wasi', 'cap-std'] diff --git a/crates/c-api/src/wasi.rs b/crates/c-api/src/wasi.rs index 763ecf4ba1..8fa15f0c20 100644 --- a/crates/c-api/src/wasi.rs +++ b/crates/c-api/src/wasi.rs @@ -1,16 +1,22 @@ //! The WASI embedding API definitions for Wasmtime. use crate::{wasm_extern_t, wasm_importtype_t, wasm_store_t, wasm_trap_t}; use anyhow::Result; +use cap_std::fs::Dir; +use std::cell::RefCell; use std::collections::HashMap; use std::ffi::CStr; use std::fs::File; use std::os::raw::{c_char, c_int}; use std::path::{Path, PathBuf}; +use std::rc::Rc; use std::slice; use std::str; -use wasi_common::{preopen_dir, WasiCtx, WasiCtxBuilder}; +use wasi_cap_std_sync::WasiCtxBuilder; +use wasi_common::WasiCtx; use wasmtime::{Extern, Linker, Trap}; -use wasmtime_wasi::{old::snapshot_0::Wasi as WasiSnapshot0, Wasi as WasiPreview1}; +use wasmtime_wasi::{ + snapshots::preview_0::Wasi as WasiSnapshot0, snapshots::preview_1::Wasi as WasiPreview1, +}; unsafe fn cstr_to_path<'a>(path: *const c_char) -> Option<&'a Path> { CStr::from_ptr(path).to_str().map(Path::new).ok() @@ -39,7 +45,7 @@ pub struct wasi_config_t { stdin: Option, stdout: Option, stderr: Option, - preopens: Vec<(File, PathBuf)>, + preopens: Vec<(Dir, PathBuf)>, inherit_args: bool, inherit_env: bool, inherit_stdin: bool, @@ -180,7 +186,7 @@ pub unsafe extern "C" fn wasi_config_preopen_dir( }; let dir = match cstr_to_path(path) { - Some(p) => match preopen_dir(p) { + Some(p) => match cap_std::fs::Dir::open_ambient_dir(p) { Ok(d) => d, Err(_) => return false, }, @@ -197,39 +203,57 @@ enum WasiInstance { Snapshot0(WasiSnapshot0), } -fn create_wasi_ctx(config: wasi_config_t) -> Result { - use std::convert::TryFrom; - use wasi_common::OsFile; +fn create_wasi_ctx(config: wasi_config_t) -> Result>> { let mut builder = WasiCtxBuilder::new(); if config.inherit_args { - builder.inherit_args(); + builder = builder.inherit_args()?; } else if !config.args.is_empty() { - builder.args(config.args); + let args = config + .args + .into_iter() + .map(|bytes| Ok(String::from_utf8(bytes)?)) + .collect::>>()?; + builder = builder.args(&args)?; } if config.inherit_env { - builder.inherit_env(); + builder = builder.inherit_env()?; } else if !config.env.is_empty() { - builder.envs(config.env); + let env = config + .env + .into_iter() + .map(|(kbytes, vbytes)| { + let k = String::from_utf8(kbytes)?; + let v = String::from_utf8(vbytes)?; + Ok((k, v)) + }) + .collect::>>()?; + builder = builder.envs(&env)?; } if config.inherit_stdin { - builder.inherit_stdin(); + builder = builder.inherit_stdin(); } else if let Some(file) = config.stdin { - builder.stdin(OsFile::try_from(file)?); + let file = unsafe { cap_std::fs::File::from_std(file) }; + let file = wasi_cap_std_sync::file::File::from_cap_std(file); + builder = builder.stdin(Box::new(file)); } if config.inherit_stdout { - builder.inherit_stdout(); + builder = builder.inherit_stdout(); } else if let Some(file) = config.stdout { - builder.stdout(OsFile::try_from(file)?); + let file = unsafe { cap_std::fs::File::from_std(file) }; + let file = wasi_cap_std_sync::file::File::from_cap_std(file); + builder = builder.stdout(Box::new(file)); } if config.inherit_stderr { - builder.inherit_stderr(); + builder = builder.inherit_stderr(); } else if let Some(file) = config.stderr { - builder.stderr(OsFile::try_from(file)?); + let file = unsafe { cap_std::fs::File::from_std(file) }; + let file = wasi_cap_std_sync::file::File::from_cap_std(file); + builder = builder.stderr(Box::new(file)); } - for preopen in config.preopens { - builder.preopened_dir(preopen.0, preopen.1); + for (dir, path) in config.preopens { + builder = builder.preopened_dir(dir, path)?; } - Ok(builder.build()?) + Ok(Rc::new(RefCell::new(builder.build()?))) } #[repr(C)] diff --git a/crates/wasi-common/cap-std-sync/src/lib.rs b/crates/wasi-common/cap-std-sync/src/lib.rs index f1da8ec6a4..2bb2aecc2e 100644 --- a/crates/wasi-common/cap-std-sync/src/lib.rs +++ b/crates/wasi-common/cap-std-sync/src/lib.rs @@ -50,6 +50,13 @@ impl WasiCtxBuilder { } Ok(s) } + pub fn inherit_args(self) -> Result { + let mut s = self.0; + for arg in std::env::args() { + s = s.arg(&arg)?; + } + Ok(WasiCtxBuilder(s)) + } pub fn stdin(self, f: Box) -> Self { WasiCtxBuilder(self.0.stdin(f)) } @@ -59,10 +66,17 @@ impl WasiCtxBuilder { pub fn stderr(self, f: Box) -> Self { WasiCtxBuilder(self.0.stderr(f)) } - pub fn inherit_stdio(self) -> Self { + pub fn inherit_stdin(self) -> Self { self.stdin(Box::new(crate::stdio::stdin())) - .stdout(Box::new(crate::stdio::stdout())) - .stderr(Box::new(crate::stdio::stderr())) + } + pub fn inherit_stdout(self) -> Self { + self.stdout(Box::new(crate::stdio::stdout())) + } + pub fn inherit_stderr(self) -> Self { + self.stderr(Box::new(crate::stdio::stderr())) + } + pub fn inherit_stdio(self) -> Self { + self.inherit_stdin().inherit_stdout().inherit_stderr() } pub fn preopened_dir( self,