implement fd_write for files

This commit is contained in:
Mark McCaskey 2019-04-02 12:06:35 -07:00
parent 242f9f679d
commit 6278ced7fc
2 changed files with 60 additions and 40 deletions

View File

@ -17,10 +17,10 @@ use zbox::{init_env as zbox_init_env, File, FileType, OpenOptions, Repo, RepoOpe
pub const MAX_SYMLINKS: usize = 100; pub const MAX_SYMLINKS: usize = 100;
pub struct InodeVal { pub struct InodeVal {
stat: __wasi_filestat_t, pub stat: __wasi_filestat_t,
is_preopened: bool, pub is_preopened: bool,
name: String, pub name: String,
kind: Kind, pub kind: Kind,
} }
pub enum Kind { pub enum Kind {
@ -41,19 +41,19 @@ pub enum Kind {
} }
pub struct Fd { pub struct Fd {
rights: __wasi_rights_t, pub rights: __wasi_rights_t,
flags: __wasi_fdflags_t, pub flags: __wasi_fdflags_t,
offset: u64, pub offset: u64,
inode: Inode, pub inode: Inode,
} }
pub struct WasiFs { pub struct WasiFs {
repo: Repo, pub repo: Repo,
name_map: HashMap<String, Inode>, pub name_map: HashMap<String, Inode>,
inodes: Arena<InodeVal>, pub inodes: Arena<InodeVal>,
fd_map: HashMap<u32, Fd>, pub fd_map: HashMap<u32, Fd>,
next_fd: Cell<u32>, pub next_fd: Cell<u32>,
inode_counter: Cell<u64>, pub inode_counter: Cell<u64>,
} }
impl WasiFs { impl WasiFs {

View File

@ -8,9 +8,10 @@ pub mod windows;
use self::types::*; use self::types::*;
use crate::{ use crate::{
ptr::{Array, WasmPtr}, ptr::{Array, WasmPtr},
state::WasiState, state::{Kind, WasiState},
}; };
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use std::cell::Cell;
use std::io::{self, Write}; use std::io::{self, Write};
use wasmer_runtime_core::{debug, memory::Memory, vm::Ctx}; use wasmer_runtime_core::{debug, memory::Memory, vm::Ctx};
@ -619,46 +620,65 @@ pub fn fd_write(
debug!("wasi::fd_write: fd={}", fd); debug!("wasi::fd_write: fd={}", fd);
let memory = ctx.memory(0); let memory = ctx.memory(0);
// TODO: check __WASI_RIGHT_FD_WRITE // TODO: check __WASI_RIGHT_FD_WRITE
// return __WASI_EISDIR if dir (probably)
let iovs_arr_cell = wasi_try!(iovs.deref(memory, 0, iovs_len)); let iovs_arr_cell = wasi_try!(iovs.deref(memory, 0, iovs_len));
let nwritten_cell = wasi_try!(nwritten.deref(memory)); let nwritten_cell = wasi_try!(nwritten.deref(memory));
let mut bytes_written = 0;
match fd { fn write_bytes<T: Write>(
0 => unimplemented!(), mut write_loc: T,
memory: &Memory,
iovs_arr_cell: &[Cell<__wasi_ciovec_t>],
) -> Result<u32, __wasi_errno_t> {
let mut bytes_written = 0;
for iov in iovs_arr_cell {
let iov_inner = iov.get();
let bytes = iov_inner.buf.deref(memory, 0, iov_inner.buf_len)?;
write_loc
.write(&bytes.iter().map(|b_cell| b_cell.get()).collect::<Vec<u8>>())
.map_err(|_| __WASI_EIO)?;
// TODO: handle failure more accurately
bytes_written += iov_inner.buf_len;
}
Ok(bytes_written)
}
let bytes_written = match fd {
0 => return __WASI_EINVAL,
1 => { 1 => {
let stdout = io::stdout(); let stdout = io::stdout();
let mut handle = stdout.lock(); let mut handle = stdout.lock();
for iov in iovs_arr_cell { wasi_try!(write_bytes(handle, memory, iovs_arr_cell))
let iov_inner = iov.get();
let bytes = wasi_try!(iov_inner.buf.deref(memory, 0, iov_inner.buf_len));
wasi_try!(handle
.write(&bytes.iter().map(|b_cell| b_cell.get()).collect::<Vec<u8>>())
.map_err(|_| __WASI_EIO));
// TODO: handle failure more accurately
bytes_written += iov_inner.buf_len;
}
} }
2 => { 2 => {
let stderr = io::stderr(); let stderr = io::stderr();
let mut handle = stderr.lock(); let mut handle = stderr.lock();
// TODO: abstract this wasi_try!(write_bytes(handle, memory, iovs_arr_cell))
for iov in iovs_arr_cell { }
let iov_inner = iov.get(); _ => {
let bytes = wasi_try!(iov_inner.buf.deref(memory, 0, iov_inner.buf_len)); let state = get_wasi_state(ctx);
wasi_try!(handle let fd_entry = wasi_try!(state.fs.fd_map.get(&fd).ok_or(__WASI_EBADF));
.write(&bytes.iter().map(|b_cell| b_cell.get()).collect::<Vec<u8>>())
.map_err(|_| __WASI_EIO));
// TODO: handle failure more accurately if fd_entry.rights & __WASI_RIGHT_FD_WRITE == 0 {
bytes_written += iov_inner.buf_len; // TODO: figure out the error to return when lacking rights
return __WASI_EACCES;
}
let inode = &mut state.fs.inodes[fd_entry.inode];
match &mut inode.kind {
Kind::File { handle } => wasi_try!(write_bytes(handle, memory, iovs_arr_cell)),
Kind::Dir { .. } => {
// TODO: verify
return __WASI_EISDIR;
}
Kind::Symlink { .. } => unimplemented!(),
Kind::Buffer { buffer } => wasi_try!(write_bytes(buffer, memory, iovs_arr_cell)),
} }
} }
other => unimplemented!(), };
}
nwritten_cell.set(bytes_written); nwritten_cell.set(bytes_written);