diff --git a/Cargo.lock b/Cargo.lock index ece6862f7b..140dcbc230 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3426,6 +3426,7 @@ dependencies = [ "env_logger 0.9.0", "once_cell", "wasi-cap-std-sync", + "wasi-common", "wasmtime", "wasmtime-c-api-macros", "wasmtime-wasi", diff --git a/crates/c-api/Cargo.toml b/crates/c-api/Cargo.toml index 56c3d6d2b3..e50cf2a1be 100644 --- a/crates/c-api/Cargo.toml +++ b/crates/c-api/Cargo.toml @@ -30,11 +30,12 @@ wat = { workspace = true, optional = true } wasi-cap-std-sync = { workspace = true, optional = true } wasmtime-wasi = { workspace = true, optional = true } cap-std = { workspace = true, optional = true } +wasi-common = { workspace = true, optional = true } [features] default = ['jitdump', 'wat', 'wasi', 'cache', 'parallel-compilation', 'memory-init-cow'] jitdump = ["wasmtime/jitdump"] cache = ["wasmtime/cache"] parallel-compilation = ['wasmtime/parallel-compilation'] -wasi = ['wasi-cap-std-sync', 'wasmtime-wasi', 'cap-std'] +wasi = ['wasi-cap-std-sync', 'wasmtime-wasi', 'cap-std', 'wasi-common'] memory-init-cow = ["wasmtime/memory-init-cow"] diff --git a/crates/c-api/include/wasi.h b/crates/c-api/include/wasi.h index 994c66b226..f3d1dfd452 100644 --- a/crates/c-api/include/wasi.h +++ b/crates/c-api/include/wasi.h @@ -94,6 +94,16 @@ WASI_API_EXTERN void wasi_config_inherit_env(wasi_config_t* config); */ WASI_API_EXTERN bool wasi_config_set_stdin_file(wasi_config_t* config, const char* path); +/** + * \brief Configures standard input to be taken from the specified #wasm_byte_vec_t. + * + * By default WASI programs have no stdin, but this configures the specified + * bytes to be used as stdin for this configuration. + * + * This function takes ownership of the `binary` argument. + */ +WASI_API_EXTERN void wasi_config_set_stdin_bytes(wasi_config_t* config, wasm_byte_vec_t* binary); + /** * \brief Configures this process's own stdin stream to be used as stdin for * this WASI configuration. diff --git a/crates/c-api/src/wasi.rs b/crates/c-api/src/wasi.rs index 1d197473b3..3eb6f3bd49 100644 --- a/crates/c-api/src/wasi.rs +++ b/crates/c-api/src/wasi.rs @@ -1,5 +1,6 @@ //! The WASI embedding API definitions for Wasmtime. +use crate::wasm_byte_vec_t; use anyhow::Result; use cap_std::ambient_authority; use std::ffi::CStr; @@ -7,6 +8,7 @@ use std::fs::File; use std::os::raw::{c_char, c_int}; use std::path::{Path, PathBuf}; use std::slice; +use wasi_common::pipe::ReadPipe; use wasmtime_wasi::{ sync::{Dir, WasiCtxBuilder}, WasiCtx, @@ -29,15 +31,31 @@ unsafe fn create_file(path: *const c_char) -> Option { pub struct wasi_config_t { args: Vec>, env: Vec<(Vec, Vec)>, - stdin: Option, - stdout: Option, - stderr: Option, + stdin: WasiConfigReadPipe, + stdout: WasiConfigWritePipe, + stderr: WasiConfigWritePipe, preopens: Vec<(Dir, PathBuf)>, inherit_args: bool, inherit_env: bool, - inherit_stdin: bool, - inherit_stdout: bool, - inherit_stderr: bool, +} + +#[repr(C)] +#[derive(Default)] +pub enum WasiConfigReadPipe { + #[default] + None, + Inherit, + File(File), + Bytes(Vec), +} + +#[repr(C)] +#[derive(Default)] +pub enum WasiConfigWritePipe { + #[default] + None, + Inherit, + File(File), } wasmtime_c_api_macros::declare_own!(wasi_config_t); @@ -69,27 +87,37 @@ impl wasi_config_t { .collect::>>()?; builder = builder.envs(&env)?; } - if self.inherit_stdin { - builder = builder.inherit_stdin(); - } else if let Some(file) = self.stdin { - let file = 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 self.inherit_stdout { - builder = builder.inherit_stdout(); - } else if let Some(file) = self.stdout { - let file = 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 self.inherit_stderr { - builder = builder.inherit_stderr(); - } else if let Some(file) = self.stderr { - let file = 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)); - } + builder = match self.stdin { + WasiConfigReadPipe::None => builder, + WasiConfigReadPipe::Inherit => builder.inherit_stdin(), + WasiConfigReadPipe::File(file) => { + let file = cap_std::fs::File::from_std(file); + let file = wasi_cap_std_sync::file::File::from_cap_std(file); + builder.stdin(Box::new(file)) + } + WasiConfigReadPipe::Bytes(binary) => { + let binary = ReadPipe::from(binary); + builder.stdin(Box::new(binary)) + } + }; + builder = match self.stdout { + WasiConfigWritePipe::None => builder, + WasiConfigWritePipe::Inherit => builder.inherit_stdout(), + WasiConfigWritePipe::File(file) => { + let file = cap_std::fs::File::from_std(file); + let file = wasi_cap_std_sync::file::File::from_cap_std(file); + builder.stdout(Box::new(file)) + } + }; + builder = match self.stderr { + WasiConfigWritePipe::None => builder, + WasiConfigWritePipe::Inherit => builder.inherit_stderr(), + WasiConfigWritePipe::File(file) => { + let file = cap_std::fs::File::from_std(file); + let file = wasi_cap_std_sync::file::File::from_cap_std(file); + builder.stderr(Box::new(file)) + } + }; for (dir, path) in self.preopens { builder = builder.preopened_dir(dir, path)?; } @@ -159,16 +187,24 @@ pub unsafe extern "C" fn wasi_config_set_stdin_file( None => return false, }; - config.stdin = Some(file); - config.inherit_stdin = false; + config.stdin = WasiConfigReadPipe::File(file); true } +#[no_mangle] +pub unsafe extern "C" fn wasi_config_set_stdin_bytes( + config: &mut wasi_config_t, + binary: &mut wasm_byte_vec_t, +) { + let binary = binary.take(); + + config.stdin = WasiConfigReadPipe::Bytes(binary); +} + #[no_mangle] pub extern "C" fn wasi_config_inherit_stdin(config: &mut wasi_config_t) { - config.stdin = None; - config.inherit_stdin = true; + config.stdin = WasiConfigReadPipe::Inherit; } #[no_mangle] @@ -181,16 +217,14 @@ pub unsafe extern "C" fn wasi_config_set_stdout_file( None => return false, }; - config.stdout = Some(file); - config.inherit_stdout = false; + config.stdout = WasiConfigWritePipe::File(file); true } #[no_mangle] pub extern "C" fn wasi_config_inherit_stdout(config: &mut wasi_config_t) { - config.stdout = None; - config.inherit_stdout = true; + config.stdout = WasiConfigWritePipe::Inherit; } #[no_mangle] @@ -203,16 +237,14 @@ pub unsafe extern "C" fn wasi_config_set_stderr_file( None => return false, }; - (*config).stderr = Some(file); - (*config).inherit_stderr = false; + config.stderr = WasiConfigWritePipe::File(file); true } #[no_mangle] pub extern "C" fn wasi_config_inherit_stderr(config: &mut wasi_config_t) { - config.stderr = None; - config.inherit_stderr = true; + config.stderr = WasiConfigWritePipe::Inherit; } #[no_mangle]