diff --git a/.appveyor.yml b/.appveyor.yml index 56df0ef21..00ccff954 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -6,6 +6,7 @@ branches: only: - staging - trying + - master environment: matrix: @@ -17,6 +18,7 @@ environment: cache: - 'C:\Users\appveyor\.cargo' - target + - wapm-cli-target install: # # Install LLVM @@ -47,7 +49,21 @@ install: # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) build_script: - - cargo build --release --verbose + - cargo build --release --verbose + # Now we build wapm + - git submodule init + - git submodule update + # Cache wapm cli target in dir above to prevent breaking git submodule on windows + - if not exist wapm-cli-target mkdir wapm-cli-target + - move wapm-cli-target wapm-cli + - cd wapm-cli + - rename wapm-cli-target target + - cd .. + - cargo build --release --manifest-path wapm-cli/Cargo.toml --features telemetry + - cd wapm-cli + - rename target wapm-cli-target + - cd .. + - move wapm-cli\wapm-cli-target wapm-cli-target test_script: - cargo test --manifest-path lib/spectests/Cargo.toml --features clif @@ -66,7 +82,7 @@ deploy: description: 'WasmerInstaller' artifact: /.*\.exe/ auth_token: - secure: CaKtncy7S1PWxzDUQ0p2264pe3HwxzDn5VIyRizDaa72/SVfskNcoMjwwRh0ut22 + secure: BbreGNDJy20922za7OhJG5TERzfX+dJSBQwttNTJkLvszbqMov6hhAtRb3P45hpf provider: GitHub on: branch: master diff --git a/.circleci/config.yml b/.circleci/config.yml index 7467652db..73a6a77c7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -220,7 +220,7 @@ jobs: name: "Pull dependencies" command: | git submodule init - git submodule update --remote + git submodule update - restore_cache: keys: - v8-cargo-cache-darwin-nightly-{{ arch }}-{{ checksum "Cargo.lock" }} @@ -314,13 +314,15 @@ jobs: tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz rustup toolchain install nightly rustup target add wasm32-wasi --toolchain nightly + - run: | + rustup default nightly + make test-wasi-singlepass + make test-wasi-clif - run: rustup default nightly-2019-04-11 - run: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make test make test-singlepass - make test-wasi-singlepass - make test-wasi-clif make test-emscripten-clif make test-emscripten-singlepass - save_cache: diff --git a/CHANGELOG.md b/CHANGELOG.md index 23c4ffcc8..1b4051de1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Blocks of changes will separated by version increments. ## 0.4.2 - 2019-05-16 +- [#457](https://github.com/wasmerio/wasmer/pull/457) Implement file metadata for WASI, fix bugs in WASI clock code for Unix platforms - [#416](https://github.com/wasmerio/wasmer/pull/416) Remote code loading framework - [#449](https://github.com/wasmerio/wasmer/pull/449) Fix bugs: opening host files in filestat and opening with write permissions unconditionally in path_open - [#442](https://github.com/wasmerio/wasmer/pull/442) Misc. WASI FS fixes and implement readdir diff --git a/lib/wasi/src/state.rs b/lib/wasi/src/state.rs index d8d366e6b..0ca18c85c 100644 --- a/lib/wasi/src/state.rs +++ b/lib/wasi/src/state.rs @@ -487,3 +487,64 @@ pub fn host_file_type_to_wasi_file_type(file_type: fs::FileType) -> __wasi_filet __WASI_FILETYPE_UNKNOWN } } + +pub fn get_stat_for_kind(kind: &Kind) -> Option<__wasi_filestat_t> { + match kind { + Kind::File { handle } => match handle { + WasiFile::HostFile(hf) => { + let md = hf.metadata().ok()?; + + Some(__wasi_filestat_t { + st_filetype: host_file_type_to_wasi_file_type(md.file_type()), + st_size: md.len(), + st_atim: md + .accessed() + .ok()? + .duration_since(SystemTime::UNIX_EPOCH) + .ok()? + .as_nanos() as u64, + st_mtim: md + .modified() + .ok()? + .duration_since(SystemTime::UNIX_EPOCH) + .ok()? + .as_nanos() as u64, + st_ctim: md + .created() + .ok() + .and_then(|ct| ct.duration_since(SystemTime::UNIX_EPOCH).ok()) + .map(|ct| ct.as_nanos() as u64) + .unwrap_or(0), + ..__wasi_filestat_t::default() + }) + } + }, + Kind::Dir { path, .. } => { + let md = path.metadata().ok()?; + Some(__wasi_filestat_t { + st_filetype: host_file_type_to_wasi_file_type(md.file_type()), + st_size: md.len(), + st_atim: md + .accessed() + .ok()? + .duration_since(SystemTime::UNIX_EPOCH) + .ok()? + .as_nanos() as u64, + st_mtim: md + .modified() + .ok()? + .duration_since(SystemTime::UNIX_EPOCH) + .ok()? + .as_nanos() as u64, + st_ctim: md + .created() + .ok() + .and_then(|ct| ct.duration_since(SystemTime::UNIX_EPOCH).ok()) + .map(|ct| ct.as_nanos() as u64) + .unwrap_or(0), + ..__wasi_filestat_t::default() + }) + } + _ => None, + } +} diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 4e5e72e67..7574c87b5 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -9,7 +9,8 @@ use self::types::*; use crate::{ ptr::{Array, WasmPtr}, state::{ - host_file_type_to_wasi_file_type, Fd, InodeVal, Kind, WasiFile, WasiState, MAX_SYMLINKS, + get_stat_for_kind, host_file_type_to_wasi_file_type, Fd, InodeVal, Kind, WasiFile, + WasiState, MAX_SYMLINKS, }, ExitCode, }; @@ -187,7 +188,10 @@ pub fn clock_time_get( precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t>, ) -> __wasi_errno_t { - debug!("wasi::clock_time_get"); + debug!( + "wasi::clock_time_get clock_id: {}, precision: {}", + clock_id, precision + ); let memory = ctx.memory(0); let out_addr = wasi_try!(time.deref(memory)); @@ -1082,7 +1086,7 @@ pub fn path_create_directory( entries: Default::default(), }; let new_inode = state.fs.inodes.insert(InodeVal { - stat: __wasi_filestat_t::default(), + stat: wasi_try!(get_stat_for_kind(&kind).ok_or(__WASI_EIO)), is_preopened: false, name: path_vec[0].clone(), kind, @@ -1226,10 +1230,7 @@ pub fn path_filestat_get( } let final_path_metadata = wasi_try!(cumulative_path.metadata().map_err(|_| __WASI_EIO)); - __wasi_filestat_t { - st_filetype: host_file_type_to_wasi_file_type(final_path_metadata.file_type()), - ..Default::default() - } + wasi_try!(get_stat_for_kind(&state.fs.inodes[inode].kind).ok_or(__WASI_EIO)) } } _ => { @@ -1535,7 +1536,7 @@ pub fn path_open( // record lazily loaded or newly created fd let new_inode = state.fs.inodes.insert(InodeVal { - stat: __wasi_filestat_t::default(), + stat: wasi_try!(get_stat_for_kind(&kind).ok_or(__WASI_EIO)), is_preopened: false, name: file_name.clone(), kind, diff --git a/lib/wasi/src/syscalls/types.rs b/lib/wasi/src/syscalls/types.rs index d484db08b..7971fb503 100644 --- a/lib/wasi/src/syscalls/types.rs +++ b/lib/wasi/src/syscalls/types.rs @@ -24,9 +24,9 @@ pub struct __wasi_ciovec_t { unsafe impl ValueType for __wasi_ciovec_t {} pub type __wasi_clockid_t = u32; -pub const __WASI_CLOCK_MONOTONIC: u32 = 0; -pub const __WASI_CLOCK_PROCESS_CPUTIME_ID: u32 = 1; -pub const __WASI_CLOCK_REALTIME: u32 = 2; +pub const __WASI_CLOCK_REALTIME: u32 = 0; +pub const __WASI_CLOCK_MONOTONIC: u32 = 1; +pub const __WASI_CLOCK_PROCESS_CPUTIME_ID: u32 = 2; pub const __WASI_CLOCK_THREAD_CPUTIME_ID: u32 = 3; pub type __wasi_device_t = u64; diff --git a/lib/wasi/src/syscalls/unix/mod.rs b/lib/wasi/src/syscalls/unix/mod.rs index 4c9cfada3..43a79319f 100644 --- a/lib/wasi/src/syscalls/unix/mod.rs +++ b/lib/wasi/src/syscalls/unix/mod.rs @@ -23,7 +23,8 @@ pub fn platform_clock_res_get( (clock_getres(unix_clock_id, &mut timespec_out), timespec_out) }; - resolution.set(timespec_out.tv_nsec as __wasi_timestamp_t); + let t_out = (timespec_out.tv_sec * 1_000_000_000).wrapping_add(timespec_out.tv_nsec); + resolution.set(t_out as __wasi_timestamp_t); // TODO: map output of clock_getres to __wasi_errno_t __WASI_ESUCCESS @@ -50,9 +51,8 @@ pub fn platform_clock_time_get( ) }; - // TODO: adjust output by precision... - - time.set(timespec_out.tv_nsec as __wasi_timestamp_t); + let t_out = (timespec_out.tv_sec * 1_000_000_000).wrapping_add(timespec_out.tv_nsec); + time.set(t_out as __wasi_timestamp_t); // TODO: map output of clock_gettime to __wasi_errno_t __WASI_ESUCCESS diff --git a/lib/wasi/tests/wasitests/_common.rs b/lib/wasi/tests/wasitests/_common.rs index 687324e13..1fbd783f4 100644 --- a/lib/wasi/tests/wasitests/_common.rs +++ b/lib/wasi/tests/wasitests/_common.rs @@ -46,7 +46,7 @@ macro_rules! assert_wasi_output { .map_err(|e| format!("{:?}", e)) .expect("start function in wasi module"); - let _result = start.call(); + start.call().expect("execute the wasm"); let output = capturer.end().unwrap().0; let expected_output = include_str!($expected); diff --git a/lib/wasi/tests/wasitests/file_metadata.rs b/lib/wasi/tests/wasitests/file_metadata.rs index 70bb6de9b..a22dc5127 100644 --- a/lib/wasi/tests/wasitests/file_metadata.rs +++ b/lib/wasi/tests/wasitests/file_metadata.rs @@ -1,5 +1,4 @@ #[test] -#[ignore] fn test_file_metadata() { assert_wasi_output!( "../../wasitests/file_metadata.wasm", diff --git a/lib/wasi/wasitests/create_dir b/lib/wasi/wasitests/create_dir index f83063c51..df15914c9 100755 Binary files a/lib/wasi/wasitests/create_dir and b/lib/wasi/wasitests/create_dir differ diff --git a/lib/wasi/wasitests/create_dir.wasm b/lib/wasi/wasitests/create_dir.wasm index c92d95516..f7f86a587 100755 Binary files a/lib/wasi/wasitests/create_dir.wasm and b/lib/wasi/wasitests/create_dir.wasm differ diff --git a/lib/wasi/wasitests/file_metadata b/lib/wasi/wasitests/file_metadata index cd3728704..804d38dd4 100755 Binary files a/lib/wasi/wasitests/file_metadata and b/lib/wasi/wasitests/file_metadata differ diff --git a/lib/wasi/wasitests/file_metadata.out b/lib/wasi/wasitests/file_metadata.out index d49e60f1d..7250bc00f 100644 --- a/lib/wasi/wasitests/file_metadata.out +++ b/lib/wasi/wasitests/file_metadata.out @@ -1,2 +1,3 @@ is dir: false -file info: FileType(FileType { mode: 33188 }) 419 Ok(SystemTime { tv_sec: 1558132188, tv_nsec: 545288295 }) Ok(SystemTime { tv_sec: 1558132188, tv_nsec: 545243056 }) Ok(SystemTime { tv_sec: 1558132191, tv_nsec: 359031112 }) +filetype: false true false +file info: 456 diff --git a/lib/wasi/wasitests/file_metadata.rs b/lib/wasi/wasitests/file_metadata.rs index 7419a4f82..630382a01 100644 --- a/lib/wasi/wasitests/file_metadata.rs +++ b/lib/wasi/wasitests/file_metadata.rs @@ -6,12 +6,12 @@ fn main() { fs::File::open("wasitests/file_metadata.rs").expect("could not find src file"); let md = this_file.metadata().unwrap(); println!("is dir: {}", md.is_dir()); + let filetype = md.file_type(); println!( - "file info: {:?} {} {:?} {:?} {:?}", - md.file_type(), - md.len(), - md.modified(), - md.created(), - md.accessed() + "filetype: {} {} {}", + filetype.is_dir(), + filetype.is_file(), + filetype.is_symlink() ); + println!("file info: {}", md.len()); } diff --git a/lib/wasi/wasitests/file_metadata.wasm b/lib/wasi/wasitests/file_metadata.wasm index 2e2f702f9..3b8b4aae1 100755 Binary files a/lib/wasi/wasitests/file_metadata.wasm and b/lib/wasi/wasitests/file_metadata.wasm differ diff --git a/lib/wasi/wasitests/hello b/lib/wasi/wasitests/hello index 546d8907f..702ef3a47 100755 Binary files a/lib/wasi/wasitests/hello and b/lib/wasi/wasitests/hello differ diff --git a/lib/wasi/wasitests/hello.wasm b/lib/wasi/wasitests/hello.wasm index 0001ccf6e..fa48455cd 100755 Binary files a/lib/wasi/wasitests/hello.wasm and b/lib/wasi/wasitests/hello.wasm differ diff --git a/lib/wasi/wasitests/ignores.txt b/lib/wasi/wasitests/ignores.txt index aa48474bf..061ac5e1e 100644 --- a/lib/wasi/wasitests/ignores.txt +++ b/lib/wasi/wasitests/ignores.txt @@ -1,2 +1 @@ -file_metadata create_dir diff --git a/lib/wasi/wasitests/quine b/lib/wasi/wasitests/quine index 409c63048..6593dbb69 100755 Binary files a/lib/wasi/wasitests/quine and b/lib/wasi/wasitests/quine differ diff --git a/lib/wasi/wasitests/quine.wasm b/lib/wasi/wasitests/quine.wasm index 937671762..d11d03add 100755 Binary files a/lib/wasi/wasitests/quine.wasm and b/lib/wasi/wasitests/quine.wasm differ