diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 48a8c3067..a7bbecb4e 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -248,6 +248,7 @@ pub fn fd_filestat_set_times( ) -> __wasi_errno_t { unimplemented!() } + pub fn fd_pread( ctx: &mut Ctx, fd: __wasi_fd_t, @@ -256,8 +257,17 @@ pub fn fd_pread( offset: __wasi_filesize_t, nread: WasmPtr, ) -> __wasi_errno_t { - unimplemented!() + let memory = ctx.memory(0); + + if let ((Some(iov_cells), Some(nread_cell))) = + (iovs.deref(memory, 0, iovs_len), nread.deref(memory)) + { + platform_fd_pread(fd, iov_cells, iovs_len, offset, nread_cell) + } else { + __WASI_EFAULT + } } + pub fn fd_prestat_get( ctx: &mut Ctx, fd: __wasi_fd_t, diff --git a/lib/wasi/src/syscalls/types.rs b/lib/wasi/src/syscalls/types.rs index 7995e86be..7f4cba575 100644 --- a/lib/wasi/src/syscalls/types.rs +++ b/lib/wasi/src/syscalls/types.rs @@ -1,6 +1,7 @@ #![allow(non_camel_case_types)] use crate::ptr::{Array, WasmPtr}; +use std::mem; use wasmer_runtime_core::types::{ValueError, ValueType}; pub type __wasi_advice_t = u8; @@ -212,6 +213,25 @@ pub struct __wasi_iovec_t { pub buf_len: u32, } +impl ValueType for __wasi_iovec_t { + fn into_le(self, buffer: &mut [u8]) { + self.buf + .into_le(&mut buffer[..mem::size_of::>()]); + self.buf_len + .into_le(&mut buffer[mem::size_of::>()..]); + } + + fn from_le(buffer: &[u8]) -> Result { + if buffer.len() >= mem::size_of::<__wasi_iovec_t>() { + let buf = ValueType::from_le(&buffer[..mem::size_of::>()])?; + let buf_len = ValueType::from_le(&buffer[mem::size_of::>()..])?; + Ok(Self { buf, buf_len }) + } else { + Err(ValueError::BufferTooSmall) + } + } +} + pub type __wasi_linkcount_t = u32; pub type __wasi_lookupflags_t = u32; diff --git a/lib/wasi/src/syscalls/unix/linux.rs b/lib/wasi/src/syscalls/unix/linux.rs index 8b1378917..cf62cc380 100644 --- a/lib/wasi/src/syscalls/unix/linux.rs +++ b/lib/wasi/src/syscalls/unix/linux.rs @@ -1 +1,27 @@ +use crate::syscalls::types::*; +use std::cell::Cell; +use libc::preadv; + +pub fn platform_fd_pread( + fd: __wasi_fd_t, + iovs: &[Cell<__wasi_iovec_t>], + iovs_len: u32, + offset: __wasi_filesize_t, + nread: &Cell, +) -> __wasi_errno_t { + let (result, iovec) = unsafe { + let mut iovec = vec![mem::uninitialized(); iovs_len as usize]; + (preadv(fd, &mut iovec, iovs_len, offset), iovec) + }; + nread.set(result); + for (arr_cell, i) in iov_arr.iter().enumerate() { + let wasi_iovec = __wasi_iovec_t { + buf: iovec[i] as _, + buf_len: iovec[i].iov_len as u32, + }; + arr_cell.set(wasi_iovec); + } + + __WASI_ESUCCESS +} diff --git a/lib/wasi/src/syscalls/unix/macos.rs b/lib/wasi/src/syscalls/unix/macos.rs index 8b1378917..748a58fb3 100644 --- a/lib/wasi/src/syscalls/unix/macos.rs +++ b/lib/wasi/src/syscalls/unix/macos.rs @@ -1 +1,12 @@ +use crate::syscalls::types::*; +use std::cell::Cell; +pub fn platform_fd_pread( + fd: __wasi_fd_t, + iovs: &[Cell<__wasi_iovec_t>], + iovs_len: u32, + offset: __wasi_filesize_t, + nread: &Cell, +) -> __wasi_errno_t { + unimplemented!() +} diff --git a/lib/wasi/src/syscalls/windows.rs b/lib/wasi/src/syscalls/windows.rs index 6273695d3..5ea255f0a 100644 --- a/lib/wasi/src/syscalls/windows.rs +++ b/lib/wasi/src/syscalls/windows.rs @@ -15,3 +15,13 @@ pub fn platform_clock_time_get( ) -> __wasi_errno_t { unimplemented!() } + +pub fn platform_fd_pread( + fd: __wasi_fd_t, + iovs: &[Cell<__wasi_iovec_t>], + iovs_len: u32, + offset: __wasi_filesize_t, + nread: &Cell, +) -> __wasi_errno_t { + unimplemented!() +}