mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 22:25:40 +00:00
Implement wasi::fd_pread
This commit is contained in:
parent
61d72a179b
commit
e6f188286b
@ -56,6 +56,23 @@ fn write_bytes<T: Write>(
|
||||
Ok(bytes_written)
|
||||
}
|
||||
|
||||
fn read_bytes<T: Read>(
|
||||
mut reader: T,
|
||||
memory: &Memory,
|
||||
iovs_arr_cell: &[Cell<__wasi_iovec_t>],
|
||||
) -> Result<u32, __wasi_errno_t> {
|
||||
let mut bytes_read = 0;
|
||||
|
||||
for iov in iovs_arr_cell {
|
||||
let iov_inner = iov.get();
|
||||
let bytes = iov_inner.buf.deref(memory, 0, iov_inner.buf_len)?;
|
||||
let mut raw_bytes: &mut [u8] =
|
||||
unsafe { &mut *(bytes as *const [_] as *mut [_] as *mut [u8]) };
|
||||
bytes_read += reader.read(raw_bytes).map_err(|_| __WASI_EIO)? as u32;
|
||||
}
|
||||
Ok(bytes_read)
|
||||
}
|
||||
|
||||
/// checks that `rights_check_set` is a subset of `rights_set`
|
||||
fn has_rights(rights_set: __wasi_rights_t, rights_check_set: __wasi_rights_t) -> bool {
|
||||
rights_set | rights_check_set == rights_set
|
||||
@ -607,6 +624,21 @@ pub fn fd_filestat_set_times(
|
||||
__WASI_ESUCCESS
|
||||
}
|
||||
|
||||
/// ### `fd_pread()`
|
||||
/// Read from the file at the given offset without updating the file cursor.
|
||||
/// This acts like a stateless version of Seek + Read
|
||||
/// Inputs:
|
||||
/// - `__wasi_fd_t fd`
|
||||
/// The file descriptor to read the data with
|
||||
/// - `const __wasi_iovec_t* iovs'
|
||||
/// Vectors where the data will be stored
|
||||
/// - `size_t iovs_len`
|
||||
/// The number of vectors to store the data into
|
||||
/// - `__wasi_filesize_t offset`
|
||||
/// The file cursor to use: the starting position from which data will be read
|
||||
/// Output:
|
||||
/// - `size_t nread`
|
||||
/// The number of bytes read
|
||||
pub fn fd_pread(
|
||||
ctx: &mut Ctx,
|
||||
fd: __wasi_fd_t,
|
||||
@ -620,9 +652,56 @@ pub fn fd_pread(
|
||||
|
||||
let iov_cells = wasi_try!(iovs.deref(memory, 0, iovs_len));
|
||||
let nread_cell = wasi_try!(nread.deref(memory));
|
||||
let state = get_wasi_state(ctx);
|
||||
|
||||
unimplemented!("wasi::fd_pread");
|
||||
let bytes_read = match fd {
|
||||
__WASI_STDIN_FILENO => wasi_try!(read_bytes(&mut state.fs.stdin, memory, iov_cells)),
|
||||
__WASI_STDOUT_FILENO => return __WASI_EINVAL,
|
||||
__WASI_STDERR_FILENO => return __WASI_EINVAL,
|
||||
_ => {
|
||||
let fd_entry = wasi_try!(state.fs.fd_map.get_mut(&fd).ok_or(__WASI_EBADF));
|
||||
let inode = fd_entry.inode;
|
||||
|
||||
if !(has_rights(fd_entry.rights, __WASI_RIGHT_FD_READ)
|
||||
&& has_rights(fd_entry.rights, __WASI_RIGHT_FD_SEEK))
|
||||
{
|
||||
return __WASI_EACCES;
|
||||
}
|
||||
match &mut state.fs.inodes[inode].kind {
|
||||
Kind::File { handle, .. } => {
|
||||
if let Some(h) = handle {
|
||||
let current_pos =
|
||||
wasi_try!(h.seek(std::io::SeekFrom::Current(0)).ok(), __WASI_EIO);
|
||||
wasi_try!(
|
||||
h.seek(std::io::SeekFrom::Start(offset as u64)).ok(),
|
||||
__WASI_EIO
|
||||
);
|
||||
let bytes_read = wasi_try!(read_bytes(h, memory, iov_cells));
|
||||
// reborrow so we can seek it back (the &mut gets moved into `read_bytes`
|
||||
// and we can't use it after)
|
||||
// If you're in the future and there's a nicer way to do this, please
|
||||
// clean up this code
|
||||
if let Some(h) = handle {
|
||||
wasi_try!(
|
||||
h.seek(std::io::SeekFrom::Start(current_pos)).ok(),
|
||||
__WASI_EIO
|
||||
);
|
||||
}
|
||||
bytes_read
|
||||
} else {
|
||||
return __WASI_EINVAL;
|
||||
}
|
||||
}
|
||||
Kind::Dir { .. } | Kind::Root { .. } => return __WASI_EISDIR,
|
||||
Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_pread"),
|
||||
Kind::Buffer { buffer } => {
|
||||
wasi_try!(read_bytes(&buffer[(offset as usize)..], memory, iov_cells))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
nread_cell.set(bytes_read);
|
||||
__WASI_ESUCCESS
|
||||
}
|
||||
|
||||
@ -733,8 +812,9 @@ pub fn fd_pwrite(
|
||||
_ => {
|
||||
let fd_entry = wasi_try!(state.fs.fd_map.get_mut(&fd).ok_or(__WASI_EBADF));
|
||||
|
||||
if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_WRITE) {
|
||||
// TODO: figure out the error to return when lacking rights
|
||||
if !(has_rights(fd_entry.rights, __WASI_RIGHT_FD_WRITE)
|
||||
&& has_rights(fd_entry.rights, __WASI_RIGHT_FD_SEEK))
|
||||
{
|
||||
return __WASI_EACCES;
|
||||
}
|
||||
|
||||
@ -794,23 +874,6 @@ pub fn fd_read(
|
||||
|
||||
let iovs_arr_cell = wasi_try!(iovs.deref(memory, 0, iovs_len));
|
||||
let nread_cell = wasi_try!(nread.deref(memory));
|
||||
|
||||
fn read_bytes<T: Read>(
|
||||
mut reader: T,
|
||||
memory: &Memory,
|
||||
iovs_arr_cell: &[Cell<__wasi_iovec_t>],
|
||||
) -> Result<u32, __wasi_errno_t> {
|
||||
let mut bytes_read = 0;
|
||||
|
||||
for iov in iovs_arr_cell {
|
||||
let iov_inner = iov.get();
|
||||
let bytes = iov_inner.buf.deref(memory, 0, iov_inner.buf_len)?;
|
||||
let mut raw_bytes: &mut [u8] =
|
||||
unsafe { &mut *(bytes as *const [_] as *mut [_] as *mut [u8]) };
|
||||
bytes_read += reader.read(raw_bytes).map_err(|_| __WASI_EIO)? as u32;
|
||||
}
|
||||
Ok(bytes_read)
|
||||
}
|
||||
let state = get_wasi_state(ctx);
|
||||
|
||||
let bytes_read = match fd {
|
||||
@ -830,7 +893,7 @@ pub fn fd_read(
|
||||
let bytes_read = match &mut inode.kind {
|
||||
Kind::File { handle, .. } => {
|
||||
if let Some(handle) = handle {
|
||||
handle.seek(::std::io::SeekFrom::Start(offset as u64));
|
||||
handle.seek(std::io::SeekFrom::Start(offset as u64));
|
||||
wasi_try!(read_bytes(handle, memory, iovs_arr_cell))
|
||||
} else {
|
||||
return __WASI_EINVAL;
|
||||
|
Loading…
Reference in New Issue
Block a user