integrate with c-api

This commit is contained in:
Pat Hickey
2021-01-29 14:09:44 -08:00
parent 6a5d4b9993
commit b48e7fcc5d
4 changed files with 66 additions and 24 deletions

2
Cargo.lock generated
View File

@@ -3237,8 +3237,10 @@ name = "wasmtime-c-api"
version = "0.19.0" version = "0.19.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cap-std",
"env_logger 0.8.2", "env_logger 0.8.2",
"once_cell", "once_cell",
"wasi-cap-std-sync",
"wasi-common", "wasi-common",
"wasmtime", "wasmtime",
"wasmtime-c-api-macros", "wasmtime-c-api-macros",

View File

@@ -28,11 +28,13 @@ wat = { version = "1.0.23", optional = true }
# Optional dependencies for the `wasi` feature # Optional dependencies for the `wasi` feature
wasi-common = { path = "../wasi-common", optional = true } 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 } wasmtime-wasi = { path = "../wasi", optional = true }
cap-std = { version = "0.12", optional = true }
[features] [features]
default = ['jitdump', 'wat', 'wasi', 'cache'] default = ['jitdump', 'wat', 'wasi', 'cache']
lightbeam = ["wasmtime/lightbeam"] lightbeam = ["wasmtime/lightbeam"]
jitdump = ["wasmtime/jitdump"] jitdump = ["wasmtime/jitdump"]
cache = ["wasmtime/cache"] cache = ["wasmtime/cache"]
wasi = ['wasi-common', 'wasmtime-wasi'] wasi = ['wasi-common', 'wasi-cap-std-sync', 'wasmtime-wasi', 'cap-std']

View File

@@ -1,16 +1,22 @@
//! The WASI embedding API definitions for Wasmtime. //! The WASI embedding API definitions for Wasmtime.
use crate::{wasm_extern_t, wasm_importtype_t, wasm_store_t, wasm_trap_t}; use crate::{wasm_extern_t, wasm_importtype_t, wasm_store_t, wasm_trap_t};
use anyhow::Result; use anyhow::Result;
use cap_std::fs::Dir;
use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::CStr; use std::ffi::CStr;
use std::fs::File; use std::fs::File;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::slice; use std::slice;
use std::str; 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::{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> { unsafe fn cstr_to_path<'a>(path: *const c_char) -> Option<&'a Path> {
CStr::from_ptr(path).to_str().map(Path::new).ok() CStr::from_ptr(path).to_str().map(Path::new).ok()
@@ -39,7 +45,7 @@ pub struct wasi_config_t {
stdin: Option<File>, stdin: Option<File>,
stdout: Option<File>, stdout: Option<File>,
stderr: Option<File>, stderr: Option<File>,
preopens: Vec<(File, PathBuf)>, preopens: Vec<(Dir, PathBuf)>,
inherit_args: bool, inherit_args: bool,
inherit_env: bool, inherit_env: bool,
inherit_stdin: bool, inherit_stdin: bool,
@@ -180,7 +186,7 @@ pub unsafe extern "C" fn wasi_config_preopen_dir(
}; };
let dir = match cstr_to_path(path) { 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, Ok(d) => d,
Err(_) => return false, Err(_) => return false,
}, },
@@ -197,39 +203,57 @@ enum WasiInstance {
Snapshot0(WasiSnapshot0), Snapshot0(WasiSnapshot0),
} }
fn create_wasi_ctx(config: wasi_config_t) -> Result<WasiCtx> { fn create_wasi_ctx(config: wasi_config_t) -> Result<Rc<RefCell<WasiCtx>>> {
use std::convert::TryFrom;
use wasi_common::OsFile;
let mut builder = WasiCtxBuilder::new(); let mut builder = WasiCtxBuilder::new();
if config.inherit_args { if config.inherit_args {
builder.inherit_args(); builder = builder.inherit_args()?;
} else if !config.args.is_empty() { } else if !config.args.is_empty() {
builder.args(config.args); let args = config
.args
.into_iter()
.map(|bytes| Ok(String::from_utf8(bytes)?))
.collect::<Result<Vec<String>>>()?;
builder = builder.args(&args)?;
} }
if config.inherit_env { if config.inherit_env {
builder.inherit_env(); builder = builder.inherit_env()?;
} else if !config.env.is_empty() { } 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::<Result<Vec<(String, String)>>>()?;
builder = builder.envs(&env)?;
} }
if config.inherit_stdin { if config.inherit_stdin {
builder.inherit_stdin(); builder = builder.inherit_stdin();
} else if let Some(file) = config.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 { if config.inherit_stdout {
builder.inherit_stdout(); builder = builder.inherit_stdout();
} else if let Some(file) = config.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 { if config.inherit_stderr {
builder.inherit_stderr(); builder = builder.inherit_stderr();
} else if let Some(file) = config.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 { for (dir, path) in config.preopens {
builder.preopened_dir(preopen.0, preopen.1); builder = builder.preopened_dir(dir, path)?;
} }
Ok(builder.build()?) Ok(Rc::new(RefCell::new(builder.build()?)))
} }
#[repr(C)] #[repr(C)]

View File

@@ -50,6 +50,13 @@ impl WasiCtxBuilder {
} }
Ok(s) Ok(s)
} }
pub fn inherit_args(self) -> Result<Self, wasi_common::StringArrayError> {
let mut s = self.0;
for arg in std::env::args() {
s = s.arg(&arg)?;
}
Ok(WasiCtxBuilder(s))
}
pub fn stdin(self, f: Box<dyn WasiFile>) -> Self { pub fn stdin(self, f: Box<dyn WasiFile>) -> Self {
WasiCtxBuilder(self.0.stdin(f)) WasiCtxBuilder(self.0.stdin(f))
} }
@@ -59,10 +66,17 @@ impl WasiCtxBuilder {
pub fn stderr(self, f: Box<dyn WasiFile>) -> Self { pub fn stderr(self, f: Box<dyn WasiFile>) -> Self {
WasiCtxBuilder(self.0.stderr(f)) WasiCtxBuilder(self.0.stderr(f))
} }
pub fn inherit_stdio(self) -> Self { pub fn inherit_stdin(self) -> Self {
self.stdin(Box::new(crate::stdio::stdin())) 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( pub fn preopened_dir(
self, self,