mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-20 20:26:32 +00:00
add preopened fd and fix/improve fs syscalls (WIP)
This commit is contained in:
@ -17,7 +17,11 @@ pub use self::utils::is_wasi_module;
|
|||||||
|
|
||||||
use wasmer_runtime_core::{func, import::ImportObject, imports};
|
use wasmer_runtime_core::{func, import::ImportObject, imports};
|
||||||
|
|
||||||
pub fn generate_import_object(args: Vec<Vec<u8>>, envs: Vec<Vec<u8>>) -> ImportObject {
|
pub fn generate_import_object(
|
||||||
|
args: Vec<Vec<u8>>,
|
||||||
|
envs: Vec<Vec<u8>>,
|
||||||
|
preopened_files: Vec<String>,
|
||||||
|
) -> ImportObject {
|
||||||
let state_gen = move || {
|
let state_gen = move || {
|
||||||
fn state_destructor(data: *mut c_void) {
|
fn state_destructor(data: *mut c_void) {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -26,7 +30,7 @@ pub fn generate_import_object(args: Vec<Vec<u8>>, envs: Vec<Vec<u8>>) -> ImportO
|
|||||||
}
|
}
|
||||||
|
|
||||||
let state = Box::new(WasiState {
|
let state = Box::new(WasiState {
|
||||||
fs: WasiFs::new().unwrap(),
|
fs: WasiFs::new(&preopened_files).unwrap(),
|
||||||
args: &args[..],
|
args: &args[..],
|
||||||
envs: &envs[..],
|
envs: &envs[..],
|
||||||
});
|
});
|
||||||
|
@ -7,14 +7,89 @@ use generational_arena::{Arena, Index as Inode};
|
|||||||
use hashbrown::hash_map::{Entry, HashMap};
|
use hashbrown::hash_map::{Entry, HashMap};
|
||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
io::{self, Write},
|
fs,
|
||||||
|
io::{self, Read, Seek, Write},
|
||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
use wasmer_runtime_core::debug;
|
use wasmer_runtime_core::debug;
|
||||||
use zbox::{init_env as zbox_init_env, File, FileType, OpenOptions, Repo, RepoOpener};
|
use zbox::{init_env as zbox_init_env, FileType, OpenOptions, Repo, RepoOpener};
|
||||||
|
|
||||||
pub const MAX_SYMLINKS: usize = 100;
|
pub const MAX_SYMLINKS: usize = 100;
|
||||||
|
|
||||||
|
pub enum WasiFile {
|
||||||
|
ZboxFile(zbox::File),
|
||||||
|
HostFile(fs::File),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for WasiFile {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.write(buf),
|
||||||
|
WasiFile::HostFile(hf) => hf.write(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.flush(),
|
||||||
|
WasiFile::HostFile(hf) => hf.flush(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.write_all(buf),
|
||||||
|
WasiFile::HostFile(hf) => hf.write_all(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.write_fmt(fmt),
|
||||||
|
WasiFile::HostFile(hf) => hf.write_fmt(fmt),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for WasiFile {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.read(buf),
|
||||||
|
WasiFile::HostFile(hf) => hf.read(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.read_to_end(buf),
|
||||||
|
WasiFile::HostFile(hf) => hf.read_to_end(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.read_to_string(buf),
|
||||||
|
WasiFile::HostFile(hf) => hf.read_to_string(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.read_exact(buf),
|
||||||
|
WasiFile::HostFile(hf) => hf.read_exact(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Seek for WasiFile {
|
||||||
|
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||||
|
match self {
|
||||||
|
WasiFile::ZboxFile(zbf) => zbf.seek(pos),
|
||||||
|
WasiFile::HostFile(hf) => hf.seek(pos),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct InodeVal {
|
pub struct InodeVal {
|
||||||
pub stat: __wasi_filestat_t,
|
pub stat: __wasi_filestat_t,
|
||||||
pub is_preopened: bool,
|
pub is_preopened: bool,
|
||||||
@ -25,10 +100,10 @@ pub struct InodeVal {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
File {
|
File {
|
||||||
handle: File,
|
handle: WasiFile,
|
||||||
},
|
},
|
||||||
Dir {
|
Dir {
|
||||||
handle: File,
|
handle: WasiFile,
|
||||||
/// The entries of a directory are lazily filled.
|
/// The entries of a directory are lazily filled.
|
||||||
entries: HashMap<String, Inode>,
|
entries: HashMap<String, Inode>,
|
||||||
},
|
},
|
||||||
@ -40,7 +115,7 @@ pub enum Kind {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Fd {
|
pub struct Fd {
|
||||||
pub rights: __wasi_rights_t,
|
pub rights: __wasi_rights_t,
|
||||||
pub rights_inheriting: __wasi_rights_t,
|
pub rights_inheriting: __wasi_rights_t,
|
||||||
@ -50,7 +125,7 @@ pub struct Fd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct WasiFs {
|
pub struct WasiFs {
|
||||||
// pub repo: Repo,
|
pub repo: Repo,
|
||||||
pub name_map: HashMap<String, Inode>,
|
pub name_map: HashMap<String, Inode>,
|
||||||
pub inodes: Arena<InodeVal>,
|
pub inodes: Arena<InodeVal>,
|
||||||
pub fd_map: HashMap<u32, Fd>,
|
pub fd_map: HashMap<u32, Fd>,
|
||||||
@ -59,26 +134,58 @@ pub struct WasiFs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WasiFs {
|
impl WasiFs {
|
||||||
pub fn new() -> Result<Self, String> {
|
pub fn new(preopened_files: &[String]) -> Result<Self, String> {
|
||||||
debug!("wasi::fs::init");
|
debug!("wasi::fs::init");
|
||||||
zbox_init_env();
|
zbox_init_env();
|
||||||
debug!("wasi::fs::repo");
|
debug!("wasi::fs::repo");
|
||||||
// let repo = RepoOpener::new()
|
let repo = RepoOpener::new()
|
||||||
// .create(true)
|
.create(true)
|
||||||
// .open("mem://wasmer-test-fs", "")
|
.open("mem://wasmer-test-fs", "")
|
||||||
// .map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
debug!("wasi::fs::inodes");
|
debug!("wasi::fs::inodes");
|
||||||
let inodes = Arena::new();
|
let inodes = Arena::new();
|
||||||
let res = Ok(Self {
|
let mut wasi_fs = Self {
|
||||||
// repo: repo,
|
repo: repo,
|
||||||
name_map: HashMap::new(),
|
name_map: HashMap::new(),
|
||||||
inodes: inodes,
|
inodes: inodes,
|
||||||
fd_map: HashMap::new(),
|
fd_map: HashMap::new(),
|
||||||
next_fd: Cell::new(3),
|
next_fd: Cell::new(3),
|
||||||
inode_counter: Cell::new(1000),
|
inode_counter: Cell::new(1000),
|
||||||
});
|
};
|
||||||
|
for file in preopened_files {
|
||||||
|
debug!("Attempting to preopen {}", &file);
|
||||||
|
// TODO: think about this
|
||||||
|
let default_rights = 0x1FFFFFFF;
|
||||||
|
let cur_file: fs::File = fs::File::open(file).expect("Could not find file");
|
||||||
|
let kind = if cur_file.metadata().unwrap().is_dir() {
|
||||||
|
// it seems bad to open every file recursively; can do it lazily though
|
||||||
|
Kind::Dir {
|
||||||
|
handle: WasiFile::HostFile(cur_file),
|
||||||
|
entries: Default::default(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*Kind::File {
|
||||||
|
handle: WasiFile::HostFile(cur_file),
|
||||||
|
}*/
|
||||||
|
return Err(format!(
|
||||||
|
"WASI only supports pre-opened directories right now; found \"{}\"",
|
||||||
|
file
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let inode_val = InodeVal {
|
||||||
|
stat: __wasi_filestat_t::default(),
|
||||||
|
is_preopened: true,
|
||||||
|
// this is incorrect
|
||||||
|
name: file.clone(),
|
||||||
|
kind,
|
||||||
|
};
|
||||||
|
let inode = wasi_fs.inodes.insert(inode_val);
|
||||||
|
wasi_fs
|
||||||
|
.create_fd(default_rights, default_rights, 0, inode)
|
||||||
|
.expect("Could not open fd");
|
||||||
|
}
|
||||||
debug!("wasi::fs::end");
|
debug!("wasi::fs::end");
|
||||||
res
|
Ok(wasi_fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -195,7 +302,9 @@ impl WasiFs {
|
|||||||
pub fn fdstat(&self, fd: __wasi_fd_t) -> Result<__wasi_fdstat_t, __wasi_errno_t> {
|
pub fn fdstat(&self, fd: __wasi_fd_t) -> Result<__wasi_fdstat_t, __wasi_errno_t> {
|
||||||
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
|
|
||||||
Ok(__wasi_fdstat_t {
|
debug!("fdstat: {:?}", fd);
|
||||||
|
|
||||||
|
dbg!(Ok(__wasi_fdstat_t {
|
||||||
fs_filetype: match self.inodes[fd.inode].kind {
|
fs_filetype: match self.inodes[fd.inode].kind {
|
||||||
Kind::File { .. } => __WASI_FILETYPE_REGULAR_FILE,
|
Kind::File { .. } => __WASI_FILETYPE_REGULAR_FILE,
|
||||||
Kind::Dir { .. } => __WASI_FILETYPE_DIRECTORY,
|
Kind::Dir { .. } => __WASI_FILETYPE_DIRECTORY,
|
||||||
@ -205,12 +314,13 @@ impl WasiFs {
|
|||||||
fs_flags: fd.flags,
|
fs_flags: fd.flags,
|
||||||
fs_rights_base: fd.rights,
|
fs_rights_base: fd.rights,
|
||||||
fs_rights_inheriting: fd.rights, // TODO(lachlan): Is this right?
|
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> {
|
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 fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
|
|
||||||
|
debug!("in prestat_fd {:?}", fd);
|
||||||
let inode_val = &self.inodes[fd.inode];
|
let inode_val = &self.inodes[fd.inode];
|
||||||
|
|
||||||
if inode_val.is_preopened {
|
if inode_val.is_preopened {
|
||||||
@ -272,6 +382,19 @@ impl WasiFs {
|
|||||||
);
|
);
|
||||||
Ok(idx)
|
Ok(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*pub fn create_file_at_fd(
|
||||||
|
&mut self,
|
||||||
|
parent: __wasi_fd_t,
|
||||||
|
path: String,
|
||||||
|
fs_rights_base: __wasi_rights_t,
|
||||||
|
fs_rights_inheriting: __wasi_rights_t,
|
||||||
|
fs_flags: fs_flags,
|
||||||
|
) -> Result<__wasi_fd_t, __wasi_errno_t> {
|
||||||
|
|
||||||
|
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
|
Ok()
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WasiState<'a> {
|
pub struct WasiState<'a> {
|
||||||
|
@ -8,11 +8,11 @@ pub mod windows;
|
|||||||
use self::types::*;
|
use self::types::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
ptr::{Array, WasmPtr},
|
ptr::{Array, WasmPtr},
|
||||||
state::{Fd, Kind, WasiState, MAX_SYMLINKS},
|
state::{Fd, InodeVal, Kind, WasiFile, WasiState, MAX_SYMLINKS},
|
||||||
};
|
};
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Seek, Write};
|
||||||
use wasmer_runtime_core::{debug, memory::Memory, vm::Ctx};
|
use wasmer_runtime_core::{debug, memory::Memory, vm::Ctx};
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
@ -335,7 +335,7 @@ pub fn fd_fdstat_get(
|
|||||||
let buf = wasi_try!(buf.deref(memory));
|
let buf = wasi_try!(buf.deref(memory));
|
||||||
buf.set(stat);
|
buf.set(stat);
|
||||||
|
|
||||||
__WASI_EFAULT
|
__WASI_ESUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### `fd_fdstat_set_flags()`
|
/// ### `fd_fdstat_set_flags()`
|
||||||
@ -532,27 +532,26 @@ pub fn fd_prestat_dir_name(
|
|||||||
fd, path_len
|
fd, path_len
|
||||||
);
|
);
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
let path_chars = wasi_try!(path.deref(memory, 0, path_len));
|
||||||
|
|
||||||
if let Ok(path_chars) = path.deref(memory, 0, path_len) {
|
let state = get_wasi_state(ctx);
|
||||||
debug!(
|
let real_fd = wasi_try!(state.fs.fd_map.get(&fd).ok_or(__WASI_EBADF));
|
||||||
"=> path: {}",
|
let inode_val = &state.fs.inodes[real_fd.inode];
|
||||||
path_chars
|
|
||||||
.iter()
|
// check inode-val.is_preopened?
|
||||||
.map(|c| c.get() as char)
|
|
||||||
.collect::<String>()
|
if let Kind::Dir { .. } = inode_val.kind {
|
||||||
);
|
// TODO: verify this: null termination, etc
|
||||||
if true
|
if inode_val.name.len() <= path_len as usize {
|
||||||
/* check if dir */
|
for (i, c) in inode_val.name.bytes().enumerate() {
|
||||||
{
|
path_chars[i].set(c);
|
||||||
// get name
|
}
|
||||||
// write name
|
|
||||||
// if overflow __WASI_EOVERFLOW
|
|
||||||
__WASI_ESUCCESS
|
__WASI_ESUCCESS
|
||||||
} else {
|
} else {
|
||||||
__WASI_ENOTDIR
|
__WASI_EOVERFLOW
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
__WASI_EFAULT
|
__WASI_ENOTDIR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,7 +611,7 @@ pub fn fd_pwrite(
|
|||||||
|
|
||||||
let bytes_written = match &mut inode.kind {
|
let bytes_written = match &mut inode.kind {
|
||||||
Kind::File { handle } => {
|
Kind::File { handle } => {
|
||||||
// TODO: adjust by offset
|
handle.seek(::std::io::SeekFrom::Start(offset as u64));
|
||||||
wasi_try!(write_bytes(handle, memory, iovs_arr_cell))
|
wasi_try!(write_bytes(handle, memory, iovs_arr_cell))
|
||||||
}
|
}
|
||||||
Kind::Dir { .. } => {
|
Kind::Dir { .. } => {
|
||||||
@ -670,14 +669,18 @@ pub fn fd_read(
|
|||||||
|
|
||||||
for iov in iovs_arr_cell {
|
for iov in iovs_arr_cell {
|
||||||
let iov_inner = iov.get();
|
let iov_inner = iov.get();
|
||||||
let bytes = iov_inner.buf.deref(memory, 0, iov_inner.buf_len)?;
|
let bytes = iov_inner.buf.deref(memory, 0, dbg!(iov_inner.buf_len))?;
|
||||||
let mut raw_bytes: &mut [u8] =
|
let mut raw_bytes: &mut [u8] =
|
||||||
unsafe { &mut *(bytes as *const [_] as *mut [_] as *mut [u8]) };
|
unsafe { &mut *(bytes as *const [_] as *mut [_] as *mut [u8]) };
|
||||||
bytes_read += reader.read(raw_bytes).map_err(|_| __WASI_EIO)? as u32;
|
bytes_read += dbg!(reader.read(raw_bytes).map_err(|e| {
|
||||||
|
dbg!(e);
|
||||||
|
__WASI_EIO
|
||||||
|
})? as u32);
|
||||||
}
|
}
|
||||||
Ok(bytes_read)
|
Ok(bytes_read)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("think-fish");
|
||||||
let bytes_read = match fd {
|
let bytes_read = match fd {
|
||||||
0 => {
|
0 => {
|
||||||
let stdin = io::stdin();
|
let stdin = io::stdin();
|
||||||
@ -699,7 +702,10 @@ pub fn fd_read(
|
|||||||
let inode = &mut state.fs.inodes[fd_entry.inode];
|
let inode = &mut state.fs.inodes[fd_entry.inode];
|
||||||
|
|
||||||
let bytes_read = match &mut inode.kind {
|
let bytes_read = match &mut inode.kind {
|
||||||
Kind::File { handle } => wasi_try!(read_bytes(handle, memory, iovs_arr_cell)),
|
Kind::File { handle } => {
|
||||||
|
handle.seek(::std::io::SeekFrom::Start(offset as u64));
|
||||||
|
wasi_try!(read_bytes(handle, memory, iovs_arr_cell))
|
||||||
|
}
|
||||||
Kind::Dir { .. } => {
|
Kind::Dir { .. } => {
|
||||||
// TODO: verify
|
// TODO: verify
|
||||||
return __WASI_EISDIR;
|
return __WASI_EISDIR;
|
||||||
@ -716,7 +722,7 @@ pub fn fd_read(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
nread_cell.set(bytes_read);
|
nread_cell.set(dbg!(bytes_read));
|
||||||
|
|
||||||
__WASI_ESUCCESS
|
__WASI_ESUCCESS
|
||||||
}
|
}
|
||||||
@ -798,7 +804,7 @@ pub fn fd_seek(
|
|||||||
whence: __wasi_whence_t,
|
whence: __wasi_whence_t,
|
||||||
newoffset: WasmPtr<__wasi_filesize_t>,
|
newoffset: WasmPtr<__wasi_filesize_t>,
|
||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
debug!("wasi::fd_seek: fd={}", fd);
|
debug!("wasi::fd_seek: fd={}, offset={}", fd, offset);
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
let state = get_wasi_state(ctx);
|
let state = get_wasi_state(ctx);
|
||||||
let new_offset_cell = wasi_try!(newoffset.deref(memory));
|
let new_offset_cell = wasi_try!(newoffset.deref(memory));
|
||||||
@ -809,9 +815,11 @@ pub fn fd_seek(
|
|||||||
return __WASI_EACCES;
|
return __WASI_EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("Hmml");
|
||||||
|
|
||||||
// TODO: handle case if fd is a dir?
|
// TODO: handle case if fd is a dir?
|
||||||
match whence {
|
match whence {
|
||||||
__WASI_WHENCE_CUR => fd_entry.offset = (fd_entry.offset as i64 + offset) as u64,
|
__WASI_WHENCE_CUR => fd_entry.offset = (dbg!(fd_entry.offset) as i64 + offset) as u64,
|
||||||
__WASI_WHENCE_END => unimplemented!(),
|
__WASI_WHENCE_END => unimplemented!(),
|
||||||
__WASI_WHENCE_SET => fd_entry.offset = offset as u64,
|
__WASI_WHENCE_SET => fd_entry.offset = offset as u64,
|
||||||
_ => return __WASI_EINVAL,
|
_ => return __WASI_EINVAL,
|
||||||
@ -920,7 +928,11 @@ pub fn fd_write(
|
|||||||
let inode = &mut state.fs.inodes[fd_entry.inode];
|
let inode = &mut state.fs.inodes[fd_entry.inode];
|
||||||
|
|
||||||
let bytes_written = match &mut inode.kind {
|
let bytes_written = match &mut inode.kind {
|
||||||
Kind::File { handle } => wasi_try!(write_bytes(handle, memory, iovs_arr_cell)),
|
Kind::File { handle } => {
|
||||||
|
handle.seek(::std::io::SeekFrom::Start(offset as u64));
|
||||||
|
|
||||||
|
wasi_try!(write_bytes(handle, memory, iovs_arr_cell))
|
||||||
|
}
|
||||||
Kind::Dir { .. } => {
|
Kind::Dir { .. } => {
|
||||||
// TODO: verify
|
// TODO: verify
|
||||||
return __WASI_EISDIR;
|
return __WASI_EISDIR;
|
||||||
@ -937,7 +949,7 @@ pub fn fd_write(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
nwritten_cell.set(bytes_written);
|
nwritten_cell.set(dbg!(bytes_written));
|
||||||
|
|
||||||
__WASI_ESUCCESS
|
__WASI_ESUCCESS
|
||||||
}
|
}
|
||||||
@ -1209,12 +1221,77 @@ pub fn path_open(
|
|||||||
// entry does not exist in parent directory
|
// entry does not exist in parent directory
|
||||||
// check to see if we should create it
|
// check to see if we should create it
|
||||||
if o_flags & __WASI_O_CREAT != 0 {
|
if o_flags & __WASI_O_CREAT != 0 {
|
||||||
|
// REVIEW: the code in this branch was written while very tired
|
||||||
// insert in to directory and set values
|
// insert in to directory and set values
|
||||||
//entries.insert(path_segment[0], )
|
//entries.insert(path_segment[0], )
|
||||||
unimplemented!()
|
|
||||||
|
let real_opened_file = wasi_try!(::std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(&path_vec[0])
|
||||||
|
.map_err(|_| __WASI_EIO));
|
||||||
|
debug!("Creating host file {}", &path_vec[0]);
|
||||||
|
let new_inode = state.fs.inodes.insert(InodeVal {
|
||||||
|
stat: __wasi_filestat_t::default(),
|
||||||
|
is_preopened: false,
|
||||||
|
name: path_vec[0].clone(),
|
||||||
|
kind: Kind::File {
|
||||||
|
handle: WasiFile::HostFile(real_opened_file),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// reborrow
|
||||||
|
if let Kind::Dir { entries, .. } = &mut state.fs.inodes[working_dir.inode].kind
|
||||||
|
{
|
||||||
|
entries.insert(path_vec[0].clone(), new_inode);
|
||||||
|
}
|
||||||
|
let new_fd = wasi_try!(state.fs.create_fd(
|
||||||
|
fs_rights_base,
|
||||||
|
fs_rights_inheriting,
|
||||||
|
fs_flags,
|
||||||
|
new_inode,
|
||||||
|
));
|
||||||
|
|
||||||
|
new_fd
|
||||||
|
|
||||||
|
// TODO: technically this could just not be lazily loaded...
|
||||||
|
/*wasi_try!(state.fs.create_file_at_fd(
|
||||||
|
dirfd,
|
||||||
|
path_vec[0],
|
||||||
|
fs_rights_base,
|
||||||
|
fs_rights_inheriting,
|
||||||
|
fs_flags
|
||||||
|
));*/
|
||||||
} else {
|
} else {
|
||||||
// no entry and can't create it
|
// attempt to load it
|
||||||
return __WASI_ENOENT;
|
let real_opened_file = wasi_try!(::std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open(&path_vec[0])
|
||||||
|
.map_err(|_| __WASI_ENOENT));
|
||||||
|
|
||||||
|
debug!("Opening host file {}", &path_vec[0]);
|
||||||
|
let new_inode = state.fs.inodes.insert(InodeVal {
|
||||||
|
stat: __wasi_filestat_t::default(),
|
||||||
|
is_preopened: false,
|
||||||
|
name: path_vec[0].clone(),
|
||||||
|
kind: Kind::File {
|
||||||
|
handle: WasiFile::HostFile(real_opened_file),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// reborrow
|
||||||
|
if let Kind::Dir { entries, .. } = &mut state.fs.inodes[working_dir.inode].kind
|
||||||
|
{
|
||||||
|
entries.insert(path_vec[0].clone(), new_inode);
|
||||||
|
}
|
||||||
|
let new_fd = wasi_try!(state.fs.create_fd(
|
||||||
|
fs_rights_base,
|
||||||
|
fs_rights_inheriting,
|
||||||
|
fs_flags,
|
||||||
|
new_inode,
|
||||||
|
));
|
||||||
|
|
||||||
|
new_fd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -264,7 +264,7 @@ pub type __wasi_filedelta_t = i64;
|
|||||||
|
|
||||||
pub type __wasi_filesize_t = u64;
|
pub type __wasi_filesize_t = u64;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct __wasi_filestat_t {
|
pub struct __wasi_filestat_t {
|
||||||
pub st_dev: __wasi_device_t,
|
pub st_dev: __wasi_device_t,
|
||||||
|
@ -66,9 +66,13 @@ struct Run {
|
|||||||
#[structopt(name = "--", raw(multiple = "true"))]
|
#[structopt(name = "--", raw(multiple = "true"))]
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
|
|
||||||
/// Emscripten symbol map
|
/// Emscripten symbol ma>p
|
||||||
#[structopt(long = "em-symbol-map", parse(from_os_str))]
|
#[structopt(long = "em-symbol-map", parse(from_os_str), group = "emscripten")]
|
||||||
em_symbol_map: Option<PathBuf>,
|
em_symbol_map: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// WASI pre-opened file
|
||||||
|
#[structopt(long = "pre-open", group = "wasi")]
|
||||||
|
pre_opened_files: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
@ -248,6 +252,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
|||||||
env::vars()
|
env::vars()
|
||||||
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
options.pre_opened_files.clone(),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user