diff --git a/Cargo.toml b/Cargo.toml index 6bcf791032..9ea0769ed5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ rand = "0.7" cfg-if = "0.1.9" log = "0.4" filetime = "0.2.7" +lazy_static = "1.4.0" [target.'cfg(unix)'.dependencies] nix = "0.15" @@ -34,6 +35,8 @@ nix = "0.15" [target.'cfg(windows)'.dependencies] winx = { path = "winx", version = "0.4.0" } winapi = "0.3" +cpu-time = "1.0" + [dev-dependencies] wasmtime-runtime = { git = "https://github.com/cranestation/wasmtime", rev = "875eea6" } diff --git a/build.rs b/build.rs index 48ca7d4319..4bb1f24795 100644 --- a/build.rs +++ b/build.rs @@ -196,7 +196,6 @@ mod wasm_tests { "readlink_no_buffer" => true, "dangling_symlink" => true, "symlink_loop" => true, - "clock_time_get" => true, "truncation_rights" => true, "fd_readdir" => true, "path_rename_trailing_slashes" => true, diff --git a/src/helpers.rs b/src/helpers.rs index dc770f7e71..4d99b96093 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,6 +1,7 @@ use crate::{Error, Result}; use std::convert::TryInto; use std::time::{SystemTime, UNIX_EPOCH}; + pub(crate) fn systemtime_to_timestamp(st: SystemTime) -> Result { st.duration_since(UNIX_EPOCH) .map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH diff --git a/src/host.rs b/src/host.rs index d43a127633..ebf18f0d4c 100644 --- a/src/host.rs +++ b/src/host.rs @@ -226,9 +226,14 @@ pub(crate) const RIGHTS_ALL: __wasi_rights_t = __WASI_RIGHT_FD_DATASYNC // Block and character device interaction is outside the scope of // WASI. Simply allow everything. +// Those constants are unused on Windows +#[allow(unused)] pub(crate) const RIGHTS_BLOCK_DEVICE_BASE: __wasi_rights_t = RIGHTS_ALL; +#[allow(unused)] pub(crate) const RIGHTS_BLOCK_DEVICE_INHERITING: __wasi_rights_t = RIGHTS_ALL; +#[allow(unused)] pub(crate) const RIGHTS_CHARACTER_DEVICE_BASE: __wasi_rights_t = RIGHTS_ALL; +#[allow(unused)] pub(crate) const RIGHTS_CHARACTER_DEVICE_INHERITING: __wasi_rights_t = RIGHTS_ALL; // Only allow directory operations on directories. Directories can only diff --git a/src/sys/windows/hostcalls_impl/misc.rs b/src/sys/windows/hostcalls_impl/misc.rs index f920957753..f19941a612 100644 --- a/src/sys/windows/hostcalls_impl/misc.rs +++ b/src/sys/windows/hostcalls_impl/misc.rs @@ -1,18 +1,33 @@ #![allow(non_camel_case_types)] #![allow(unused_unsafe)] #![allow(unused)] +use crate::helpers::systemtime_to_timestamp; use crate::memory::*; use crate::sys::host_impl; -use crate::{host, wasm32, Result}; +use crate::{host, wasm32, Error, Result}; +use cpu_time::{ProcessTime, ThreadTime}; +use lazy_static::lazy_static; +use std::convert::TryInto; +use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; + +lazy_static! { + static ref START_MONOTONIC: Instant = Instant::now(); +} -use wasi_common_cbindgen::wasi_common_cbindgen; pub(crate) fn clock_res_get(clock_id: host::__wasi_clockid_t) -> Result { unimplemented!("clock_res_get") } pub(crate) fn clock_time_get(clock_id: host::__wasi_clockid_t) -> Result { - unimplemented!("clock_time_get") + let duration = match clock_id { + host::__WASI_CLOCK_REALTIME => get_monotonic_time(), + host::__WASI_CLOCK_MONOTONIC => get_realtime_time()?, + host::__WASI_CLOCK_PROCESS_CPUTIME_ID => get_proc_cputime()?, + host::__WASI_CLOCK_THREAD_CPUTIME_ID => get_thread_cputime()?, + _ => return Err(Error::EINVAL), + }; + duration.as_nanos().try_into().map_err(Into::into) } pub(crate) fn poll_oneoff( @@ -21,3 +36,27 @@ pub(crate) fn poll_oneoff( ) -> Result { unimplemented!("poll_oneoff") } + +fn get_monotonic_time() -> Duration { + // We're circumventing the fact that we can't get a Duration from an Instant + // The epoch of __WASI_CLOCK_MONOTONIC is undefined, so we fix a time point once + // and count relative to this time point. + // + // The alternative would be to copy over the implementation of std::time::Instant + // to our source tree and add a conversion to std::time::Duration + START_MONOTONIC.elapsed() +} + +fn get_realtime_time() -> Result { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .map_err(|_| Error::EFAULT) +} + +fn get_proc_cputime() -> Result { + Ok(ProcessTime::try_now()?.as_duration()) +} + +fn get_thread_cputime() -> Result { + Ok(ThreadTime::try_now()?.as_duration()) +} diff --git a/winx/src/file.rs b/winx/src/file.rs index dc04dcfb96..b937c28959 100644 --- a/winx/src/file.rs +++ b/winx/src/file.rs @@ -320,42 +320,40 @@ pub unsafe fn get_file_access_mode(handle: RawHandle) -> Result { use winapi::um::accctrl; use winapi::um::aclapi::GetSecurityInfo; use winapi::um::securitybaseapi::{GetAce, IsValidAcl}; - unsafe { - let mut dacl = 0 as winnt::PACL; - let mut sec_desc = 0 as winnt::PSECURITY_DESCRIPTOR; + let mut dacl = 0 as winnt::PACL; + let mut sec_desc = 0 as winnt::PSECURITY_DESCRIPTOR; - let err = winerror::WinError::from_u32(GetSecurityInfo( - handle, - accctrl::SE_FILE_OBJECT, - winnt::DACL_SECURITY_INFORMATION, - std::ptr::null_mut(), - std::ptr::null_mut(), - &mut dacl, - std::ptr::null_mut(), - &mut sec_desc, - )); + let err = winerror::WinError::from_u32(GetSecurityInfo( + handle, + accctrl::SE_FILE_OBJECT, + winnt::DACL_SECURITY_INFORMATION, + std::ptr::null_mut(), + std::ptr::null_mut(), + &mut dacl, + std::ptr::null_mut(), + &mut sec_desc, + )); - if err != winerror::WinError::ERROR_SUCCESS { - return Err(err); - } - - if IsValidAcl(dacl) == FALSE { - return Err(winerror::WinError::last()); - } - - // let count = (*dacl).AceCount; - let mut ace = 0 as winnt::PVOID; - - if GetAce(dacl, 0, &mut ace) == FALSE { - return Err(winerror::WinError::last()); - } - - // TODO: check for PACCESS_ALLOWED_ACE in Ace before accessing - // let header = (*(ace as winnt::PACCESS_ALLOWED_ACE)).Header.AceType; - Ok(AccessMode::from_bits_truncate( - (*(ace as winnt::PACCESS_ALLOWED_ACE)).Mask, - )) + if err != winerror::WinError::ERROR_SUCCESS { + return Err(err); } + + if IsValidAcl(dacl) == FALSE { + return Err(winerror::WinError::last()); + } + + // let count = (*dacl).AceCount; + let mut ace = 0 as winnt::PVOID; + + if GetAce(dacl, 0, &mut ace) == FALSE { + return Err(winerror::WinError::last()); + } + + // TODO: check for PACCESS_ALLOWED_ACE in Ace before accessing + // let header = (*(ace as winnt::PACCESS_ALLOWED_ACE)).Header.AceType; + Ok(AccessMode::from_bits_truncate( + (*(ace as winnt::PACCESS_ALLOWED_ACE)).Mask, + )) } pub fn get_file_path(file: &File) -> Result {