2019-08-01 20:46:35 -06:00
|
|
|
#![deny(
|
|
|
|
dead_code,
|
2019-08-15 20:18:29 -06:00
|
|
|
nonstandard_style,
|
2019-08-01 20:46:35 -06:00
|
|
|
unused_imports,
|
2019-08-15 20:18:29 -06:00
|
|
|
unused_mut,
|
2019-08-01 20:46:35 -06:00
|
|
|
unused_variables,
|
|
|
|
unused_unsafe,
|
|
|
|
unreachable_patterns
|
|
|
|
)]
|
2019-09-03 17:06:31 -07:00
|
|
|
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
|
|
|
|
#![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")]
|
|
|
|
|
2019-09-26 17:15:43 -07:00
|
|
|
//! Wasmer's WASI implementation
|
|
|
|
//!
|
|
|
|
//! Use `generate_import_object` to create an `ImportObject`. This `ImportObject`
|
|
|
|
//! can be combined with a module to create an `Instance` which can execute WASI
|
|
|
|
//! Wasm functions.
|
|
|
|
//!
|
|
|
|
//! See `state` for the experimental WASI FS API. Also see the
|
|
|
|
//! [WASI plugin example](https://github.com/wasmerio/wasmer/blob/master/examples/plugin.rs)
|
|
|
|
//! for an example of how to extend WASI using the WASI FS API.
|
|
|
|
|
2019-05-21 10:41:40 -07:00
|
|
|
#[cfg(target = "windows")]
|
2019-05-21 10:35:51 -07:00
|
|
|
extern crate winapi;
|
2019-04-01 15:15:20 -07:00
|
|
|
|
2019-04-01 16:34:18 -07:00
|
|
|
#[macro_use]
|
|
|
|
mod macros;
|
2019-03-28 17:00:10 -07:00
|
|
|
mod ptr;
|
2019-07-31 09:58:39 +09:00
|
|
|
pub mod state;
|
2019-03-28 11:54:22 -07:00
|
|
|
mod syscalls;
|
2019-03-28 12:19:23 -07:00
|
|
|
mod utils;
|
|
|
|
|
2019-04-01 15:52:35 -07:00
|
|
|
use self::state::{WasiFs, WasiState};
|
2019-07-31 09:58:39 +09:00
|
|
|
pub use self::syscalls::types;
|
2019-03-28 12:18:05 -07:00
|
|
|
use self::syscalls::*;
|
|
|
|
|
|
|
|
use std::ffi::c_void;
|
2019-05-16 17:35:13 -07:00
|
|
|
use std::path::PathBuf;
|
2019-03-28 11:23:08 -07:00
|
|
|
|
2019-11-12 12:54:28 -08:00
|
|
|
pub use self::utils::{get_wasi_version, is_wasi_module, WasiVersion};
|
2019-03-28 12:19:23 -07:00
|
|
|
|
2019-04-02 10:58:22 -07:00
|
|
|
use wasmer_runtime_core::{func, import::ImportObject, imports};
|
2019-03-28 11:44:31 -07:00
|
|
|
|
2019-04-22 11:42:52 -07:00
|
|
|
/// This is returned in the Box<dyn Any> RuntimeError::Error variant.
|
|
|
|
/// Use `downcast` or `downcast_ref` to retrieve the `ExitCode`.
|
|
|
|
pub struct ExitCode {
|
|
|
|
pub code: syscalls::types::__wasi_exitcode_t,
|
|
|
|
}
|
|
|
|
|
2019-09-30 16:32:18 -07:00
|
|
|
/// Creates a Wasi [`ImportObject`] with [`WasiState`].
|
2019-04-10 18:23:25 -07:00
|
|
|
pub fn generate_import_object(
|
|
|
|
args: Vec<Vec<u8>>,
|
|
|
|
envs: Vec<Vec<u8>>,
|
2019-09-30 15:26:04 -07:00
|
|
|
preopened_files: Vec<PathBuf>,
|
2019-05-20 16:46:08 -07:00
|
|
|
mapped_dirs: Vec<(String, PathBuf)>,
|
2019-04-10 18:23:25 -07:00
|
|
|
) -> ImportObject {
|
2019-03-28 12:18:05 -07:00
|
|
|
let state_gen = move || {
|
2019-08-28 13:19:06 -07:00
|
|
|
// TODO: look into removing all these unnecessary clones
|
2019-04-03 17:13:50 -07:00
|
|
|
fn state_destructor(data: *mut c_void) {
|
2019-03-28 12:18:05 -07:00
|
|
|
unsafe {
|
|
|
|
drop(Box::from_raw(data as *mut WasiState));
|
|
|
|
}
|
|
|
|
}
|
2019-08-28 13:19:06 -07:00
|
|
|
let preopened_files = preopened_files.clone();
|
|
|
|
let mapped_dirs = mapped_dirs.clone();
|
2019-09-30 15:26:04 -07:00
|
|
|
//let wasi_builder = create_wasi_instance();
|
2019-03-28 12:18:05 -07:00
|
|
|
|
|
|
|
let state = Box::new(WasiState {
|
2019-08-28 13:19:06 -07:00
|
|
|
fs: WasiFs::new(&preopened_files, &mapped_dirs).expect("Could not create WASI FS"),
|
2019-08-27 15:18:12 -07:00
|
|
|
args: args.clone(),
|
|
|
|
envs: envs.clone(),
|
2019-03-28 12:18:05 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
(
|
2019-08-28 10:50:59 -07:00
|
|
|
Box::into_raw(state) as *mut c_void,
|
2019-04-03 17:13:50 -07:00
|
|
|
state_destructor as fn(*mut c_void),
|
2019-03-28 12:18:05 -07:00
|
|
|
)
|
|
|
|
};
|
2019-03-28 11:44:31 -07:00
|
|
|
imports! {
|
|
|
|
// This generates the wasi state.
|
2019-03-28 12:18:05 -07:00
|
|
|
state_gen,
|
2019-11-12 12:54:28 -08:00
|
|
|
"wasi_snapshot_preview1" => {
|
2019-03-28 15:17:52 -07:00
|
|
|
"args_get" => func!(args_get),
|
|
|
|
"args_sizes_get" => func!(args_sizes_get),
|
|
|
|
"clock_res_get" => func!(clock_res_get),
|
|
|
|
"clock_time_get" => func!(clock_time_get),
|
|
|
|
"environ_get" => func!(environ_get),
|
|
|
|
"environ_sizes_get" => func!(environ_sizes_get),
|
|
|
|
"fd_advise" => func!(fd_advise),
|
|
|
|
"fd_allocate" => func!(fd_allocate),
|
|
|
|
"fd_close" => func!(fd_close),
|
|
|
|
"fd_datasync" => func!(fd_datasync),
|
|
|
|
"fd_fdstat_get" => func!(fd_fdstat_get),
|
|
|
|
"fd_fdstat_set_flags" => func!(fd_fdstat_set_flags),
|
|
|
|
"fd_fdstat_set_rights" => func!(fd_fdstat_set_rights),
|
|
|
|
"fd_filestat_get" => func!(fd_filestat_get),
|
|
|
|
"fd_filestat_set_size" => func!(fd_filestat_set_size),
|
|
|
|
"fd_filestat_set_times" => func!(fd_filestat_set_times),
|
|
|
|
"fd_pread" => func!(fd_pread),
|
|
|
|
"fd_prestat_get" => func!(fd_prestat_get),
|
|
|
|
"fd_prestat_dir_name" => func!(fd_prestat_dir_name),
|
|
|
|
"fd_pwrite" => func!(fd_pwrite),
|
|
|
|
"fd_read" => func!(fd_read),
|
|
|
|
"fd_readdir" => func!(fd_readdir),
|
|
|
|
"fd_renumber" => func!(fd_renumber),
|
|
|
|
"fd_seek" => func!(fd_seek),
|
|
|
|
"fd_sync" => func!(fd_sync),
|
|
|
|
"fd_tell" => func!(fd_tell),
|
|
|
|
"fd_write" => func!(fd_write),
|
|
|
|
"path_create_directory" => func!(path_create_directory),
|
|
|
|
"path_filestat_get" => func!(path_filestat_get),
|
|
|
|
"path_filestat_set_times" => func!(path_filestat_set_times),
|
|
|
|
"path_link" => func!(path_link),
|
|
|
|
"path_open" => func!(path_open),
|
|
|
|
"path_readlink" => func!(path_readlink),
|
|
|
|
"path_remove_directory" => func!(path_remove_directory),
|
|
|
|
"path_rename" => func!(path_rename),
|
|
|
|
"path_symlink" => func!(path_symlink),
|
|
|
|
"path_unlink_file" => func!(path_unlink_file),
|
|
|
|
"poll_oneoff" => func!(poll_oneoff),
|
|
|
|
"proc_exit" => func!(proc_exit),
|
|
|
|
"proc_raise" => func!(proc_raise),
|
|
|
|
"random_get" => func!(random_get),
|
|
|
|
"sched_yield" => func!(sched_yield),
|
|
|
|
"sock_recv" => func!(sock_recv),
|
|
|
|
"sock_send" => func!(sock_send),
|
|
|
|
"sock_shutdown" => func!(sock_shutdown),
|
2019-03-28 11:44:31 -07:00
|
|
|
},
|
|
|
|
}
|
2019-03-28 11:54:22 -07:00
|
|
|
}
|
2019-11-12 12:54:28 -08:00
|
|
|
|
|
|
|
#[cfg(feature = "snapshot0")]
|
|
|
|
/// Creates a Wasi [`ImportObject`] with [`WasiState`].
|
|
|
|
pub fn generate_import_object_snapshot0(
|
|
|
|
args: Vec<Vec<u8>>,
|
|
|
|
envs: Vec<Vec<u8>>,
|
|
|
|
preopened_files: Vec<PathBuf>,
|
|
|
|
mapped_dirs: Vec<(String, PathBuf)>,
|
|
|
|
) -> ImportObject {
|
|
|
|
let state_gen = move || {
|
|
|
|
// TODO: look into removing all these unnecessary clones
|
|
|
|
fn state_destructor(data: *mut c_void) {
|
|
|
|
unsafe {
|
|
|
|
drop(Box::from_raw(data as *mut WasiState));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let preopened_files = preopened_files.clone();
|
|
|
|
let mapped_dirs = mapped_dirs.clone();
|
|
|
|
//let wasi_builder = create_wasi_instance();
|
|
|
|
|
|
|
|
let state = Box::new(WasiState {
|
|
|
|
fs: WasiFs::new(&preopened_files, &mapped_dirs).expect("Could not create WASI FS"),
|
|
|
|
args: args.clone(),
|
|
|
|
envs: envs.clone(),
|
|
|
|
});
|
|
|
|
|
|
|
|
(
|
|
|
|
Box::into_raw(state) as *mut c_void,
|
|
|
|
state_destructor as fn(*mut c_void),
|
|
|
|
)
|
|
|
|
};
|
|
|
|
imports! {
|
|
|
|
// This generates the wasi state.
|
|
|
|
state_gen,
|
|
|
|
"wasi_unstable" => {
|
|
|
|
"args_get" => func!(args_get),
|
|
|
|
"args_sizes_get" => func!(args_sizes_get),
|
|
|
|
"clock_res_get" => func!(clock_res_get),
|
|
|
|
"clock_time_get" => func!(clock_time_get),
|
|
|
|
"environ_get" => func!(environ_get),
|
|
|
|
"environ_sizes_get" => func!(environ_sizes_get),
|
|
|
|
"fd_advise" => func!(fd_advise),
|
|
|
|
"fd_allocate" => func!(fd_allocate),
|
|
|
|
"fd_close" => func!(fd_close),
|
|
|
|
"fd_datasync" => func!(fd_datasync),
|
|
|
|
"fd_fdstat_get" => func!(fd_fdstat_get),
|
|
|
|
"fd_fdstat_set_flags" => func!(fd_fdstat_set_flags),
|
|
|
|
"fd_fdstat_set_rights" => func!(fd_fdstat_set_rights),
|
|
|
|
"fd_filestat_get" => func!(legacy::snapshot0::fd_filestat_get),
|
|
|
|
"fd_filestat_set_size" => func!(fd_filestat_set_size),
|
|
|
|
"fd_filestat_set_times" => func!(fd_filestat_set_times),
|
|
|
|
"fd_pread" => func!(fd_pread),
|
|
|
|
"fd_prestat_get" => func!(fd_prestat_get),
|
|
|
|
"fd_prestat_dir_name" => func!(fd_prestat_dir_name),
|
|
|
|
"fd_pwrite" => func!(fd_pwrite),
|
|
|
|
"fd_read" => func!(fd_read),
|
|
|
|
"fd_readdir" => func!(fd_readdir),
|
|
|
|
"fd_renumber" => func!(fd_renumber),
|
|
|
|
"fd_seek" => func!(legacy::snapshot0::fd_seek),
|
|
|
|
"fd_sync" => func!(fd_sync),
|
|
|
|
"fd_tell" => func!(fd_tell),
|
|
|
|
"fd_write" => func!(fd_write),
|
|
|
|
"path_create_directory" => func!(path_create_directory),
|
|
|
|
"path_filestat_get" => func!(legacy::snapshot0::path_filestat_get),
|
|
|
|
"path_filestat_set_times" => func!(path_filestat_set_times),
|
|
|
|
"path_link" => func!(path_link),
|
|
|
|
"path_open" => func!(path_open),
|
|
|
|
"path_readlink" => func!(path_readlink),
|
|
|
|
"path_remove_directory" => func!(path_remove_directory),
|
|
|
|
"path_rename" => func!(path_rename),
|
|
|
|
"path_symlink" => func!(path_symlink),
|
|
|
|
"path_unlink_file" => func!(path_unlink_file),
|
|
|
|
"poll_oneoff" => func!(legacy::snapshot0::poll_oneoff),
|
|
|
|
"proc_exit" => func!(proc_exit),
|
|
|
|
"proc_raise" => func!(proc_raise),
|
|
|
|
"random_get" => func!(random_get),
|
|
|
|
"sched_yield" => func!(sched_yield),
|
|
|
|
"sock_recv" => func!(sock_recv),
|
|
|
|
"sock_send" => func!(sock_send),
|
|
|
|
"sock_shutdown" => func!(sock_shutdown),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|