Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasi filesystem rewrite + implementation of many syscalls #555

Merged
merged 15 commits into from
Jul 19, 2019
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ generate-emtests:
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten-tests --release

generate-wasitests:
WASM_WASI_GENERATE_WASITESTS=1 cargo build -p wasmer-wasi-tests --release -vv
WASM_WASI_GENERATE_WASITESTS=1 cargo build -p wasmer-wasi-tests --release -vv \
&& echo "formatting" \
&& cargo fmt

spectests-generate: generate-spectests
emtests-generate: generate-emtests
wasitests-generate: generate-wasitests

generate: generate-spectests generate-emtests generate-wasitests

Expand Down
9 changes: 9 additions & 0 deletions lib/runtime-core/src/memory/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,15 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
[index as usize..slice_full_len];
Some(cell_ptrs)
}

pub fn get_utf8_string<'a>(self, memory: &'a Memory, str_len: u32) -> Option<&'a str> {
if self.offset as usize + str_len as usize > memory.size().bytes().0 {
return None;
}
let ptr = unsafe { memory.view::<u8>().as_ptr().add(self.offset as usize) as *const u8 };
let slice: &[u8] = unsafe { std::slice::from_raw_parts(ptr, str_len as usize) };
std::str::from_utf8(slice).ok()
}
}

unsafe impl<T: Copy, Ty> WasmExternType for WasmPtr<T, Ty> {
Expand Down
21 changes: 20 additions & 1 deletion lib/wasi-tests/build/wasitests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub fn compile(file: &str, ignores: &HashSet<String>) -> Option<String> {
};

let src_code = fs::read_to_string(file).expect("read src file");
let args = extract_args_from_source_file(&src_code).unwrap_or_default();
let args: Args = extract_args_from_source_file(&src_code).unwrap_or_default();

let mapdir_args = {
let mut out_str = String::new();
Expand All @@ -116,12 +116,25 @@ pub fn compile(file: &str, ignores: &HashSet<String>) -> Option<String> {
out_str
};

let po_args = {
let mut out_str = String::new();
out_str.push_str("vec![");

for entry in args.po_dirs {
out_str.push_str(&format!("\"{}\".to_string(),", entry));
}

out_str.push_str("]");
out_str
};

let contents = format!(
"#[test]{ignore}
fn test_{rs_module_name}() {{
assert_wasi_output!(
\"../../{module_path}\",
\"{rs_module_name}\",
{po_args},
{mapdir_args},
{envvar_args},
\"../../{test_output_path}\"
Expand All @@ -132,6 +145,7 @@ fn test_{rs_module_name}() {{
module_path = wasm_out_name,
rs_module_name = rs_module_name,
test_output_path = format!("{}.out", normalized_name),
po_args = po_args,
mapdir_args = mapdir_args,
envvar_args = envvar_args
);
Expand Down Expand Up @@ -192,6 +206,8 @@ fn read_ignore_list() -> HashSet<String> {
struct Args {
pub mapdir: Vec<(String, String)>,
pub envvars: Vec<(String, String)>,
/// pre-opened directories
pub po_dirs: Vec<String>,
}

/// Pulls args to the program out of a comment at the top of the file starting with "// Args:"
Expand Down Expand Up @@ -237,6 +253,9 @@ fn extract_args_from_source_file(source_code: &str) -> Option<Args> {
eprintln!("Parse error in env {} not parsed correctly", &tokenized[1]);
}
}
"dir" => {
args.po_dirs.push(tokenized[1].to_string());
}
e => {
eprintln!("WARN: comment arg: {} is not supported", e);
}
Expand Down
5 changes: 2 additions & 3 deletions lib/wasi-tests/tests/wasitests/_common.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
macro_rules! assert_wasi_output {
($file:expr, $name:expr, $mapdir_args:expr, $envvar_args:expr, $expected:expr) => {{
($file:expr, $name:expr, $po_dir_args: expr, $mapdir_args:expr, $envvar_args:expr, $expected:expr) => {{
use wasmer_dev_utils::stdio::StdioCapturer;
use wasmer_runtime_core::{backend::Compiler, Func};
use wasmer_wasi::generate_import_object;
Expand Down Expand Up @@ -33,8 +33,7 @@ macro_rules! assert_wasi_output {
let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &get_compiler())
.expect("WASM can't be compiled");

let import_object =
generate_import_object(vec![], vec![], vec![".".to_string()], $mapdir_args);
let import_object = generate_import_object(vec![], vec![], $po_dir_args, $mapdir_args);

let instance = module
.instantiate(&import_object)
Expand Down
2 changes: 1 addition & 1 deletion lib/wasi-tests/tests/wasitests/create_dir.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#[test]
#[ignore]
fn test_create_dir() {
assert_wasi_output!(
"../../wasitests/create_dir.wasm",
"create_dir",
vec![".".to_string(),],
vec![],
vec![],
"../../wasitests/create_dir.out"
Expand Down
1 change: 1 addition & 0 deletions lib/wasi-tests/tests/wasitests/envvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ fn test_envvar() {
"../../wasitests/envvar.wasm",
"envvar",
vec![],
vec![],
vec!["DOG=1".to_string(), "CAT=2".to_string(),],
"../../wasitests/envvar.out"
);
Expand Down
1 change: 1 addition & 0 deletions lib/wasi-tests/tests/wasitests/file_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ fn test_file_metadata() {
assert_wasi_output!(
"../../wasitests/file_metadata.wasm",
"file_metadata",
vec![".".to_string(),],
vec![],
vec![],
"../../wasitests/file_metadata.out"
Expand Down
1 change: 1 addition & 0 deletions lib/wasi-tests/tests/wasitests/fs_sandbox_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ fn test_fs_sandbox_test() {
"fs_sandbox_test",
vec![],
vec![],
vec![],
"../../wasitests/fs_sandbox_test.out"
);
}
1 change: 1 addition & 0 deletions lib/wasi-tests/tests/wasitests/fseek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ fn test_fseek() {
assert_wasi_output!(
"../../wasitests/fseek.wasm",
"fseek",
vec![],
vec![(
".".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet")
Expand Down
1 change: 1 addition & 0 deletions lib/wasi-tests/tests/wasitests/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ fn test_hello() {
"hello",
vec![],
vec![],
vec![],
"../../wasitests/hello.out"
);
}
1 change: 1 addition & 0 deletions lib/wasi-tests/tests/wasitests/mapdir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ fn test_mapdir() {
assert_wasi_output!(
"../../wasitests/mapdir.wasm",
"mapdir",
vec![],
vec![(
".".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet")
Expand Down
3 changes: 3 additions & 0 deletions lib/wasi-tests/tests/wasitests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ mod fseek;
mod hello;
mod mapdir;
mod quine;
mod readlink;
mod wasi_sees_virtual_root;
mod writing;
1 change: 1 addition & 0 deletions lib/wasi-tests/tests/wasitests/quine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ fn test_quine() {
assert_wasi_output!(
"../../wasitests/quine.wasm",
"quine",
vec![".".to_string(),],
vec![],
vec![],
"../../wasitests/quine.out"
Expand Down
14 changes: 14 additions & 0 deletions lib/wasi-tests/tests/wasitests/readlink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[test]
fn test_readlink() {
assert_wasi_output!(
"../../wasitests/readlink.wasm",
"readlink",
vec![],
vec![(
".".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet")
),],
vec![],
"../../wasitests/readlink.out"
);
}
24 changes: 24 additions & 0 deletions lib/wasi-tests/tests/wasitests/wasi_sees_virtual_root.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#[test]
fn test_wasi_sees_virtual_root() {
assert_wasi_output!(
"../../wasitests/wasi_sees_virtual_root.wasm",
"wasi_sees_virtual_root",
vec![],
vec![
(
"act1".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet/act1")
),
(
"act2".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet/act2")
),
(
"act1-again".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet/act1")
),
],
vec![],
"../../wasitests/wasi_sees_virtual_root.out"
);
}
24 changes: 24 additions & 0 deletions lib/wasi-tests/tests/wasitests/writing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#[test]
fn test_writing() {
assert_wasi_output!(
"../../wasitests/writing.wasm",
"writing",
vec![],
vec![
(
"act1".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet/act1")
),
(
"act2".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet/act2")
),
(
"act1-again".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet/act1")
),
],
vec![],
"../../wasitests/writing.out"
);
}
3 changes: 3 additions & 0 deletions lib/wasi-tests/wasitests/create_dir.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Args:
// dir: .

use std::fs;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::*;
Expand Down
Binary file modified lib/wasi-tests/wasitests/create_dir.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion lib/wasi-tests/wasitests/file_metadata.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
is dir: false
filetype: false true false
file info: 456
file info: 476
3 changes: 3 additions & 0 deletions lib/wasi-tests/wasitests/file_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Args:
// dir: .

use std::fs;
use std::io::Read;

Expand Down
2 changes: 1 addition & 1 deletion lib/wasi-tests/wasitests/ignores.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
create_dir

1 change: 1 addition & 0 deletions lib/wasi-tests/wasitests/mapdir.out
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
"./act3"
"./act4"
"./act5"
"./bookmarks"
3 changes: 3 additions & 0 deletions lib/wasi-tests/wasitests/quine.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Args:
// dir: .

use std::fs;
use std::io::Read;

Expand Down
3 changes: 3 additions & 0 deletions lib/wasi-tests/wasitests/quine.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Args:
// dir: .

use std::fs;
use std::io::Read;

Expand Down
4 changes: 4 additions & 0 deletions lib/wasi-tests/wasitests/readlink.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
../act1/scene2.txt
SCENE II. A room of state in the castle.

Enter KING CLAUDIUS, QUEEN GERTRUDE, HAMLET, POLONIUS, LAERTES, VOLTIMAND, CORNELI
27 changes: 27 additions & 0 deletions lib/wasi-tests/wasitests/readlink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Args:
// mapdir: .:wasitests/test_fs/hamlet
use std::io::Read;

fn main() {
#[cfg(not(target_os = "wasi"))]
let cur_dir = std::env::current_dir().unwrap();
#[cfg(not(target_os = "wasi"))]
std::env::set_current_dir("wasitests/test_fs/hamlet").unwrap();

let sym_link_path = "bookmarks/2019-07-16";

let link_path = std::fs::read_link(sym_link_path).unwrap();
println!("{}", link_path.to_string_lossy());

let mut some_contents = std::fs::File::open(sym_link_path).unwrap();

let mut buffer = [0; 128];

assert_eq!(some_contents.read(&mut buffer).unwrap(), 128);
let str_val = std::str::from_utf8(&buffer[..]).unwrap();
println!("{}", str_val);

// return to the current directory
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(not(target_os = "wasi"))]
std::env::set_current_dir(cur_dir).unwrap();
}
Binary file added lib/wasi-tests/wasitests/readlink.wasm
Binary file not shown.
13 changes: 13 additions & 0 deletions lib/wasi-tests/wasitests/wasi_sees_virtual_root.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"/act1"
"/act1-again"
"/act2"
"/act1"
"/act1-again"
"/act2"
"/act1"
"/act1-again"
"/act2"
"/act1"
"/act1-again"
"/act2"
ROOT IS SAFE
59 changes: 59 additions & 0 deletions lib/wasi-tests/wasitests/wasi_sees_virtual_root.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Args:
// mapdir: act1:wasitests/test_fs/hamlet/act1
// mapdir: act2:wasitests/test_fs/hamlet/act2
// mapdir: act1-again:wasitests/test_fs/hamlet/act1

use std::fs;

fn main() {
// just cheat in this test because there is no comparison for native
#[cfg(not(target_os = "wasi"))]
let results = {
let start = vec!["\"/act1\"", "\"/act1-again\"", "\"/act2\""];

let mut out = vec![];
for _ in 0..4 {
for path_str in &start {
out.push(path_str.to_string());
}
}

out.push("ROOT IS SAFE".to_string());
out
};

#[cfg(target_os = "wasi")]
let results = {
let mut out = vec![];

let read_dir = fs::read_dir("/").unwrap();
for entry in read_dir {
out.push(format!("{:?}", entry.unwrap().path()))
}
let read_dir = fs::read_dir("act1/..").unwrap();
for entry in read_dir {
out.push(format!("{:?}", entry.unwrap().path()))
}
let read_dir = fs::read_dir("act1/../../..").unwrap();
for entry in read_dir {
out.push(format!("{:?}", entry.unwrap().path()))
}
let read_dir = fs::read_dir("act1/../../act2/../act1/../../../").unwrap();
for entry in read_dir {
out.push(format!("{:?}", entry.unwrap().path()))
}
let f = fs::OpenOptions::new().write(true).open("/abc");

if f.is_ok() {
out.push("ROOT IS NOT SAFE".to_string());
} else {
out.push("ROOT IS SAFE".to_string());
}

out
};

for result in results {
println!("{}", result);
}
}
Binary file not shown.
Loading