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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ All PRs to the Wasmer repository must add to this file.
Blocks of changes will separated by version increments.

## **[Unreleased]**
- [#555](https://github.com/wasmerio/wasmer/pull/555) WASI filesystem rewrite. Major improvements
- adds virtual root showing all preopened directories
- improved sandboxing and code-reuse
- symlinks work in a lot more situations
- many various improvements to most syscalls touching the filesystem

## 0.5.6
- [#565](https://github.com/wasmerio/wasmer/pull/565) Update wapm and bump version to 0.5.6
Expand Down
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 dir_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}\",
{dir_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),
dir_args = dir_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"
5 changes: 0 additions & 5 deletions lib/wasi-tests/wasitests/mapdir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
use std::fs;

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();

Expand All @@ -19,7 +17,4 @@ fn main() {
for p in out {
println!("{}", p);
}
// return to the current directory
#[cfg(not(target_os = "wasi"))]
std::env::set_current_dir(cur_dir).unwrap();
}
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
21 changes: 21 additions & 0 deletions lib/wasi-tests/wasitests/readlink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Args:
// mapdir: .:wasitests/test_fs/hamlet
use std::io::Read;

fn main() {
#[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);
}
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
Loading