mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 00:00:49 +00:00
expose vfs in emscripten and impl read
syscall, feature flag
This commit is contained in:
parent
b9c3a49f3c
commit
cc3f04efd7
@ -39,7 +39,7 @@ glob = "0.2.11"
|
||||
|
||||
[features]
|
||||
default = ["fast-tests"]
|
||||
|
||||
vfs = ["wasmer-runtime-abi", "wasmer-runtime-core/vfs", "wasmer-emscripten/vfs", "wasmer-clif-backend/vfs"]
|
||||
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
# This feature will allow cargo test to run much faster
|
||||
fast-tests = []
|
||||
|
@ -10,6 +10,8 @@ build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" }
|
||||
wasmer-runtime-abi = { path = "../runtime-abi", optional = true }
|
||||
lazy_static = "1.2.0"
|
||||
libc = "0.2.49"
|
||||
byteorder = "1"
|
||||
@ -19,7 +21,6 @@ time = "0.1.41"
|
||||
rand = "0.6"
|
||||
|
||||
[dev-dependencies]
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" }
|
||||
wabt = "0.7.2"
|
||||
|
||||
[target.'cfg(not(windows))'.dev-dependencies]
|
||||
@ -30,4 +31,5 @@ glob = "0.2.11"
|
||||
|
||||
[features]
|
||||
clif = []
|
||||
llvm = []
|
||||
llvm = []
|
||||
vfs = ["wasmer-runtime-core/vfs", "wasmer-clif-backend/vfs", "wasmer-runtime-abi"]
|
||||
|
12
lib/emscripten/emtests/test_vfs.c
vendored
Normal file
12
lib/emscripten/emtests/test_vfs.c
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
char data[256] = {0};
|
||||
ssize_t fd = open("data.txt", 0);
|
||||
ssize_t result = read((int)fd, &data, 255);
|
||||
printf("content: %s", data);
|
||||
printf("fd: %zd\n", fd);
|
||||
return 0;
|
||||
}
|
6
lib/emscripten/emtests/test_vfs.md
vendored
Normal file
6
lib/emscripten/emtests/test_vfs.md
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
The wasm file `test_vfs.wasm` is generated by compiling the `test_vfs.c` and writing a tar.zst blob with a single file
|
||||
named `data.txt`.
|
||||
|
||||
The program expects to find a file named `data.txt` and reads the contents and the file descriptor.
|
||||
|
||||
The runtime should mount the virtual filesystem and expose the file.
|
1
lib/emscripten/emtests/test_vfs.out
vendored
Normal file
1
lib/emscripten/emtests/test_vfs.out
vendored
Normal file
@ -0,0 +1 @@
|
||||
content: wasmer is awesomer
|
BIN
lib/emscripten/emtests/test_vfs.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/test_vfs.wasm
vendored
Normal file
Binary file not shown.
@ -54,6 +54,11 @@ pub use self::utils::{
|
||||
get_emscripten_table_size, is_emscripten_module,
|
||||
};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
#[cfg(feature = "vfs")]
|
||||
use wasmer_runtime_abi::vfs::vfs::VfsBacking;
|
||||
|
||||
// TODO: Magic number - how is this calculated?
|
||||
const TOTAL_STACK: u32 = 5_242_880;
|
||||
// TODO: Magic number - how is this calculated?
|
||||
@ -135,6 +140,9 @@ pub struct EmscriptenData<'a> {
|
||||
pub dyn_call_viji: Option<Func<'a, (i32, i32, i32, i32, i32)>>,
|
||||
pub dyn_call_vijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
||||
pub dyn_call_vijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
||||
|
||||
#[cfg(feature = "vfs")]
|
||||
pub vfs: Option<VfsBacking>,
|
||||
}
|
||||
|
||||
impl<'a> EmscriptenData<'a> {
|
||||
@ -231,17 +239,33 @@ impl<'a> EmscriptenData<'a> {
|
||||
dyn_call_viji,
|
||||
dyn_call_vijiii,
|
||||
dyn_call_vijj,
|
||||
#[cfg(feature = "vfs")]
|
||||
vfs: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_emscripten_instance(
|
||||
_module: &Module,
|
||||
module: &Module,
|
||||
instance: &mut Instance,
|
||||
path: &str,
|
||||
args: Vec<&str>,
|
||||
) -> CallResult<()> {
|
||||
let mut data = EmscriptenData::new(instance);
|
||||
|
||||
// Construct a new virtual filesystem and inject it into the emscripten data
|
||||
// This is behind a feature flag for now, but will be default in the future
|
||||
#[cfg(feature = "vfs")]
|
||||
{
|
||||
data.vfs = match module.info().custom_sections.get("wasmer_fs") {
|
||||
Some(bytes) => match VfsBacking::from_tar_zstd_bytes(&bytes[..]) {
|
||||
Ok(vfs_backing) => Some(vfs_backing),
|
||||
Err(_) => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
}
|
||||
|
||||
let data_ptr = &mut data as *mut _ as *mut c_void;
|
||||
instance.context_mut().data = data_ptr;
|
||||
|
||||
|
@ -29,7 +29,7 @@ use libc::{
|
||||
// iovec,
|
||||
lseek,
|
||||
// open,
|
||||
read,
|
||||
// read,
|
||||
// readv,
|
||||
rmdir,
|
||||
// writev,
|
||||
@ -40,7 +40,6 @@ use libc::{
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
use super::env;
|
||||
use std::cell::Cell;
|
||||
use std::slice;
|
||||
// use std::sys::fd::FileDesc;
|
||||
|
||||
@ -67,6 +66,7 @@ pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) {
|
||||
}
|
||||
|
||||
/// read
|
||||
#[cfg(not(feature = "vfs"))]
|
||||
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
// -> ssize_t
|
||||
debug!("emscripten::___syscall3 (read) {}", which);
|
||||
@ -75,7 +75,27 @@ pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
let count: i32 = varargs.get(ctx);
|
||||
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
|
||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void;
|
||||
let ret = unsafe { read(fd, buf_addr, count as _) };
|
||||
let ret = unsafe { libc::read(fd, buf_addr, count as _) };
|
||||
debug!("=> ret: {}", ret);
|
||||
ret as _
|
||||
}
|
||||
|
||||
/// read
|
||||
#[cfg(feature = "vfs")]
|
||||
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
// -> ssize_t
|
||||
debug!("emscripten::___syscall3 (read - vfs) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
let count: i32 = varargs.get(ctx);
|
||||
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
|
||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut u8;
|
||||
let mut buf_slice = unsafe { slice::from_raw_parts_mut(buf_addr, count as _) };
|
||||
let emscripten_data = get_emscripten_data(ctx);
|
||||
let ret = match &mut emscripten_data.vfs {
|
||||
Some(vfs) => vfs.read_file(fd as _, &mut buf_slice).unwrap(),
|
||||
None => 0,
|
||||
};
|
||||
debug!("=> ret: {}", ret);
|
||||
ret as _
|
||||
}
|
||||
@ -91,6 +111,23 @@ pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
unsafe { write(fd, buf_addr, count as _) as i32 }
|
||||
}
|
||||
|
||||
/// open
|
||||
#[cfg(feature = "vfs")]
|
||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall5 (open vfs) {}", which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
||||
let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
|
||||
let emscripten_data = get_emscripten_data(ctx);
|
||||
let fd = if let Some(vfs) = &mut emscripten_data.vfs {
|
||||
vfs.open_file(path_str).unwrap_or(-1)
|
||||
} else {
|
||||
-1
|
||||
};
|
||||
debug!("=> fd: {}", fd);
|
||||
return fd as _;
|
||||
}
|
||||
|
||||
/// close
|
||||
pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall6 (close) {}", which);
|
||||
@ -307,7 +344,7 @@ pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
as *mut c_void;
|
||||
let iov_len = (*guest_iov_addr).iov_len as _;
|
||||
// debug!("=> iov_addr: {:?}, {:?}", iov_base, iov_len);
|
||||
let curr = read(fd, iov_base, iov_len);
|
||||
let curr = libc::read(fd, iov_base, iov_len);
|
||||
if curr < 0 {
|
||||
return -1;
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ use libc::SO_NOSIGPIPE;
|
||||
const SO_NOSIGPIPE: c_int = 0;
|
||||
|
||||
/// open
|
||||
#[cfg(not(feature = "vfs"))]
|
||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall5 (open) {}", which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::env::get_emscripten_data;
|
||||
use crate::utils::copy_cstr_into_wasm;
|
||||
use crate::utils::read_string_from_wasm;
|
||||
use crate::varargs::VarArgs;
|
||||
@ -15,6 +16,7 @@ use wasmer_runtime_core::vm::Ctx;
|
||||
type pid_t = c_int;
|
||||
|
||||
/// open
|
||||
#[cfg(not(feature = "vfs"))]
|
||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall5 (open) {}", which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
|
@ -176,6 +176,8 @@ mod test_unary_literal;
|
||||
mod test_utf;
|
||||
mod test_varargs;
|
||||
mod test_varargs_multi;
|
||||
#[cfg(feature = "vfs")]
|
||||
mod test_vfs;
|
||||
mod test_vprintf;
|
||||
mod test_vsnprintf;
|
||||
mod test_wprintf;
|
||||
|
9
lib/emscripten/tests/emtests/test_vfs.rs
Normal file
9
lib/emscripten/tests/emtests/test_vfs.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#[test]
|
||||
fn test_vfs() {
|
||||
assert_emscripten_output!(
|
||||
"../../emtests/test_vfs.wasm",
|
||||
"test_vfs",
|
||||
vec![],
|
||||
"../../emtests/test_vfs.out"
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user