diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index 5183dc511..c6908988c 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -15,7 +15,7 @@ use std::ffi::c_void; pub use self::utils::is_wasi_module; -use wasmer_runtime_core::{debug, func, import::ImportObject, imports}; +use wasmer_runtime_core::{func, import::ImportObject, imports}; pub fn generate_import_object(args: Vec>, envs: Vec>) -> ImportObject { let state_gen = move || { diff --git a/lib/wasi/src/state.rs b/lib/wasi/src/state.rs index 49d8335b3..2f7cb8ef5 100644 --- a/lib/wasi/src/state.rs +++ b/lib/wasi/src/state.rs @@ -194,6 +194,21 @@ impl WasiFs { fs_rights_inheriting: fd.rights, // TODO(lachlan): Is this right? }) } + + pub fn prestat_fd(&self, fd: __wasi_fd_t) -> Result<__wasi_prestat_t, __wasi_errno_t> { + let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?; + + let inode_val = &self.inodes[fd.inode]; + + if inode_val.is_preopened { + Ok(PrestatEnum::PreOpenDir { + pr_name_len: inode_val.name.len() as u32, + } + .get_untagged()) + } else { + Err(__WASI_EBADF) + } + } } pub struct WasiState<'a> { diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 1a6a1d45e..4e86d4d12 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -380,6 +380,14 @@ pub fn fd_pread( } } +/// ### `fd_prestat_get()` +/// Get metadata about a preopened file descriptor +/// Input: +/// - `__wasi_fd_t fd` +/// The preopened file descriptor to query +/// Output: +/// - `__wasi_prestat *buf` +/// Where the metadata will be written pub fn fd_prestat_get( ctx: &mut Ctx, fd: __wasi_fd_t, @@ -388,13 +396,12 @@ pub fn fd_prestat_get( debug!("wasi::fd_prestat_get: fd={}", fd); let memory = ctx.memory(0); - if let Ok(prestat_ptr) = buf.deref(memory) { - // open fd - // write info to prestat_ptr - __WASI_ESUCCESS - } else { - __WASI_EFAULT - } + let prestat_ptr = wasi_try!(buf.deref(memory)); + + let state = get_wasi_state(ctx); + prestat_ptr.set(wasi_try!(state.fs.prestat_fd(fd))); + + __WASI_ESUCCESS } pub fn fd_prestat_dir_name( diff --git a/lib/wasi/src/syscalls/types.rs b/lib/wasi/src/syscalls/types.rs index 17098aacf..157720675 100644 --- a/lib/wasi/src/syscalls/types.rs +++ b/lib/wasi/src/syscalls/types.rs @@ -191,6 +191,37 @@ pub struct __wasi_prestat_t { u: __wasi_prestat_u, } +#[derive(Copy, Clone)] +pub enum PrestatEnum { + PreOpenDir { pr_name_len: u32 }, +} + +impl __wasi_prestat_t { + pub fn get_tagged(&self) -> PrestatEnum { + match self.pr_type { + __WASI_PREOPENTYPE_DIR => PrestatEnum::PreOpenDir { + pr_name_len: unsafe { self.u.dir.pr_name_len }, + }, + _ => panic!("Invalid enum variant in __wasi_prestat_t: {}", self.pr_type), + } + } +} + +impl PrestatEnum { + pub fn get_untagged(&self) -> __wasi_prestat_t { + match self { + PrestatEnum::PreOpenDir { pr_name_len } => __wasi_prestat_t { + pr_type: __WASI_PREOPENTYPE_DIR, + u: __wasi_prestat_u { + dir: __wasi_prestat_u_dir_t { + pr_name_len: *pr_name_len, + }, + }, + }, + } + } +} + unsafe impl ValueType for __wasi_prestat_t {} #[derive(Debug, Copy, Clone, PartialEq, Eq)]