mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-14 14:45:40 +00:00
Merge branch 'feature/wasi' of github.com:wasmerio/wasmer into feature/wasi
This commit is contained in:
commit
84dc20af94
@ -1,6 +1,8 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
mod ptr;
|
mod ptr;
|
||||||
mod state;
|
mod state;
|
||||||
mod syscalls;
|
mod syscalls;
|
||||||
|
13
lib/wasi/src/macros.rs
Normal file
13
lib/wasi/src/macros.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
macro_rules! wasi_try {
|
||||||
|
($expr:expr) => {{
|
||||||
|
let res: Result<_, crate::syscalls::types::__wasi_errno_t> = $expr;
|
||||||
|
match res {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(err) => return err,
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
($expr:expr; $e:expr) => {{
|
||||||
|
let opt: Option<_> = $expr;
|
||||||
|
wasi_try!(opt.ok_or($e))
|
||||||
|
}};
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::syscalls::types::{__wasi_errno_t, __WASI_EFAULT};
|
||||||
use std::{cell::Cell, fmt, marker::PhantomData, mem};
|
use std::{cell::Cell, fmt, marker::PhantomData, mem};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
memory::Memory,
|
memory::Memory,
|
||||||
@ -30,27 +31,32 @@ impl<T: Copy, Ty> WasmPtr<T, Ty> {
|
|||||||
|
|
||||||
impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell<T>> {
|
pub fn deref<'a>(self, memory: &'a Memory) -> Result<&'a Cell<T>, __wasi_errno_t> {
|
||||||
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
|
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
|
||||||
return None;
|
return Err(__WASI_EFAULT);
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
let cell_ptr = memory
|
let cell_ptr = memory
|
||||||
.view::<T>()
|
.view::<T>()
|
||||||
.get_unchecked((self.offset() as usize) / mem::size_of::<T>())
|
.get_unchecked((self.offset() as usize) / mem::size_of::<T>())
|
||||||
as *const _;
|
as *const _;
|
||||||
Some(&*cell_ptr)
|
Ok(&*cell_ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn deref<'a>(self, memory: &'a Memory, index: u32, length: u32) -> Option<&'a [Cell<T>]> {
|
pub fn deref<'a>(
|
||||||
|
self,
|
||||||
|
memory: &'a Memory,
|
||||||
|
index: u32,
|
||||||
|
length: u32,
|
||||||
|
) -> Result<&'a [Cell<T>], __wasi_errno_t> {
|
||||||
if (self.offset as usize) + (mem::size_of::<T>() * ((index + length) as usize))
|
if (self.offset as usize) + (mem::size_of::<T>() * ((index + length) as usize))
|
||||||
>= memory.size().bytes().0
|
>= memory.size().bytes().0
|
||||||
{
|
{
|
||||||
return None;
|
return Err(__WASI_EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -59,7 +65,7 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
|||||||
..((self.offset() as usize) / mem::size_of::<T>())
|
..((self.offset() as usize) / mem::size_of::<T>())
|
||||||
+ ((index + length) as usize),
|
+ ((index + length) as usize),
|
||||||
) as *const _;
|
) as *const _;
|
||||||
Some(&*cell_ptrs)
|
Ok(&*cell_ptrs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,31 +166,19 @@ impl WasiFs {
|
|||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
||||||
warn!("Should use preopned_fd: {}", preopened_fd);
|
warn!("Should use preopned_fd: {}", preopened_fd);
|
||||||
let inode = if let Some(inode) = self.get_inode(path) {
|
let inode = self.get_inode(path).ok_or(__WASI_EINVAL)?;
|
||||||
inode
|
|
||||||
} else {
|
|
||||||
return Err(__WASI_EINVAL);
|
|
||||||
};
|
|
||||||
|
|
||||||
self.filestat_inode(inode, flags)
|
self.filestat_inode(inode, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filestat_fd(&self, fd: __wasi_fd_t) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
pub fn filestat_fd(&self, fd: __wasi_fd_t) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
||||||
let fd = if let Some(fd) = self.fd_map.get(&fd) {
|
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
fd
|
|
||||||
} else {
|
|
||||||
return Err(__WASI_EBADF);
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(self.inodes[fd.inode].stat)
|
Ok(self.inodes[fd.inode].stat)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = if let Some(fd) = self.fd_map.get(&fd) {
|
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
fd
|
|
||||||
} else {
|
|
||||||
return Err(__WASI_EBADF);
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(__wasi_fdstat_t {
|
Ok(__wasi_fdstat_t {
|
||||||
fs_filetype: match self.inodes[fd.inode].kind {
|
fs_filetype: match self.inodes[fd.inode].kind {
|
||||||
|
@ -31,23 +31,13 @@ fn write_buffer_array(
|
|||||||
ptr_buffer: WasmPtr<WasmPtr<u8, Array>, Array>,
|
ptr_buffer: WasmPtr<WasmPtr<u8, Array>, Array>,
|
||||||
buffer: WasmPtr<u8, Array>,
|
buffer: WasmPtr<u8, Array>,
|
||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let ptrs = if let Some(cells) = ptr_buffer.deref(memory, 0, from.len() as u32) {
|
let ptrs = wasi_try!(ptr_buffer.deref(memory, 0, from.len() as u32));
|
||||||
cells
|
|
||||||
} else {
|
|
||||||
return __WASI_EOVERFLOW;
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut current_buffer_offset = 0;
|
let mut current_buffer_offset = 0;
|
||||||
for ((i, sub_buffer), ptr) in from.iter().enumerate().zip(ptrs.iter()) {
|
for ((i, sub_buffer), ptr) in from.iter().enumerate().zip(ptrs.iter()) {
|
||||||
ptr.set(WasmPtr::new(buffer.offset() + current_buffer_offset));
|
ptr.set(WasmPtr::new(buffer.offset() + current_buffer_offset));
|
||||||
|
|
||||||
let cells = if let Some(cells) =
|
let cells = wasi_try!(buffer.deref(memory, current_buffer_offset, sub_buffer.len() as u32));
|
||||||
buffer.deref(memory, current_buffer_offset, sub_buffer.len() as u32)
|
|
||||||
{
|
|
||||||
cells
|
|
||||||
} else {
|
|
||||||
return __WASI_EOVERFLOW;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (cell, &byte) in cells.iter().zip(sub_buffer.iter()) {
|
for (cell, &byte) in cells.iter().zip(sub_buffer.iter()) {
|
||||||
cell.set(byte);
|
cell.set(byte);
|
||||||
@ -92,16 +82,15 @@ pub fn args_sizes_get(
|
|||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let (Some(argc), Some(argv_buf_size)) = (argc.deref(memory), argv_buf_size.deref(memory)) {
|
let argc = wasi_try!(argc.deref(memory));
|
||||||
let state = get_wasi_state(ctx);
|
let argv_buf_size = wasi_try!(argv_buf_size.deref(memory));
|
||||||
|
|
||||||
argc.set(state.args.len() as u32);
|
let state = get_wasi_state(ctx);
|
||||||
argv_buf_size.set(state.args.iter().map(|v| v.len() as u32).sum());
|
|
||||||
|
|
||||||
__WASI_ESUCCESS
|
argc.set(state.args.len() as u32);
|
||||||
} else {
|
argv_buf_size.set(state.args.iter().map(|v| v.len() as u32).sum());
|
||||||
__WASI_EOVERFLOW
|
|
||||||
}
|
__WASI_ESUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### `clock_res_get()`
|
/// ### `clock_res_get()`
|
||||||
@ -119,11 +108,8 @@ pub fn clock_res_get(
|
|||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let Some(out_addr) = resolution.deref(memory) {
|
let out_addr = wasi_try!(resolution.deref(memory));
|
||||||
platform_clock_res_get(clock_id, out_addr)
|
platform_clock_res_get(clock_id, out_addr)
|
||||||
} else {
|
|
||||||
__WASI_EFAULT
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### `clock_time_get()`
|
/// ### `clock_time_get()`
|
||||||
@ -144,11 +130,8 @@ pub fn clock_time_get(
|
|||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let Some(out_addr) = time.deref(memory) {
|
let out_addr = wasi_try!(time.deref(memory));
|
||||||
platform_clock_time_get(clock_id, precision, out_addr)
|
platform_clock_time_get(clock_id, precision, out_addr)
|
||||||
} else {
|
|
||||||
__WASI_EFAULT
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### `environ_get()`
|
/// ### `environ_get()`
|
||||||
@ -184,18 +167,15 @@ pub fn environ_sizes_get(
|
|||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let (Some(environ_count), Some(environ_buf_size)) =
|
let environ_count = wasi_try!(environ_count.deref(memory));
|
||||||
(environ_count.deref(memory), environ_buf_size.deref(memory))
|
let environ_buf_size = wasi_try!(environ_buf_size.deref(memory));
|
||||||
{
|
|
||||||
let state = get_wasi_state(ctx);
|
|
||||||
|
|
||||||
environ_count.set(state.envs.len() as u32);
|
let state = get_wasi_state(ctx);
|
||||||
environ_buf_size.set(state.envs.iter().map(|v| v.len() as u32).sum());
|
|
||||||
|
|
||||||
__WASI_ESUCCESS
|
environ_count.set(state.envs.len() as u32);
|
||||||
} else {
|
environ_buf_size.set(state.envs.iter().map(|v| v.len() as u32).sum());
|
||||||
__WASI_EOVERFLOW
|
|
||||||
}
|
__WASI_EOVERFLOW
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### `fd_advise()`
|
/// ### `fd_advise()`
|
||||||
@ -282,17 +262,12 @@ pub fn fd_fdstat_get(
|
|||||||
let mut state = get_wasi_state(ctx);
|
let mut state = get_wasi_state(ctx);
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
let stat = match state.fs.fdstat(fd) {
|
let stat = wasi_try!(state.fs.fdstat(fd));
|
||||||
Ok(stat) => stat,
|
|
||||||
Err(errno) => return errno,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(buf) = buf.deref(memory) {
|
let buf = wasi_try!(buf.deref(memory));
|
||||||
buf.set(stat);
|
buf.set(stat);
|
||||||
__WASI_ESUCCESS
|
|
||||||
} else {
|
__WASI_EFAULT
|
||||||
__WASI_EFAULT
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### `fd_fdstat_set_flags()`
|
/// ### `fd_fdstat_set_flags()`
|
||||||
@ -344,17 +319,12 @@ pub fn fd_filestat_get(
|
|||||||
let mut state = get_wasi_state(ctx);
|
let mut state = get_wasi_state(ctx);
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
let stat = match state.fs.filestat_fd(fd) {
|
let stat = wasi_try!(state.fs.filestat_fd(fd));
|
||||||
Ok(stat) => stat,
|
|
||||||
Err(errno) => return errno,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(buf) = buf.deref(memory) {
|
let buf = wasi_try!(buf.deref(memory));
|
||||||
buf.set(stat);
|
buf.set(stat);
|
||||||
__WASI_ESUCCESS
|
|
||||||
} else {
|
__WASI_ESUCCESS
|
||||||
__WASI_EFAULT
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fd_filestat_set_size(
|
pub fn fd_filestat_set_size(
|
||||||
@ -384,7 +354,7 @@ pub fn fd_pread(
|
|||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let ((Some(iov_cells), Some(nread_cell))) =
|
if let ((Ok(iov_cells), Ok(nread_cell))) =
|
||||||
(iovs.deref(memory, 0, iovs_len), nread.deref(memory))
|
(iovs.deref(memory, 0, iovs_len), nread.deref(memory))
|
||||||
{
|
{
|
||||||
platform_fd_pread(fd, iov_cells, iovs_len, offset, nread_cell)
|
platform_fd_pread(fd, iov_cells, iovs_len, offset, nread_cell)
|
||||||
@ -400,7 +370,7 @@ pub fn fd_prestat_get(
|
|||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let Some(prestat_ptr) = buf.deref(memory) {
|
if let Ok(prestat_ptr) = buf.deref(memory) {
|
||||||
// open fd
|
// open fd
|
||||||
// write info to prestat_ptr
|
// write info to prestat_ptr
|
||||||
__WASI_ESUCCESS
|
__WASI_ESUCCESS
|
||||||
@ -417,7 +387,7 @@ pub fn fd_prestat_dir_name(
|
|||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let Some(path_chars) = path.deref(memory, 0, path_len) {
|
if let Ok(path_chars) = path.deref(memory, 0, path_len) {
|
||||||
if true
|
if true
|
||||||
/* check if dir */
|
/* check if dir */
|
||||||
{
|
{
|
||||||
@ -467,7 +437,7 @@ pub fn fd_read(
|
|||||||
|
|
||||||
// check __WASI_RIGHT_FD_READ
|
// check __WASI_RIGHT_FD_READ
|
||||||
|
|
||||||
if let (Some(iovs_arr_cell), Some(nwritten_cell)) =
|
if let (Ok(iovs_arr_cell), Ok(nwritten_cell)) =
|
||||||
(iovs.deref(memory, 0, iovs_len), nread.deref(memory))
|
(iovs.deref(memory, 0, iovs_len), nread.deref(memory))
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
@ -501,7 +471,7 @@ pub fn fd_readdir(
|
|||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let (Some(buf_arr_cell), Some(bufused_cell)) =
|
if let (Ok(buf_arr_cell), Ok(bufused_cell)) =
|
||||||
(buf.deref(memory, 0, buf_len), bufused.deref(memory))
|
(buf.deref(memory, 0, buf_len), bufused.deref(memory))
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
@ -543,7 +513,7 @@ pub fn fd_seek(
|
|||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
// TODO: check __WASI_RIGHT_FD_SEEK
|
// TODO: check __WASI_RIGHT_FD_SEEK
|
||||||
// TODO: handle directory input
|
// TODO: handle directory input
|
||||||
if let Some(new_offset_cell) = newoffset.deref(memory) {
|
if let Ok(new_offset_cell) = newoffset.deref(memory) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
} else {
|
} else {
|
||||||
__WASI_EFAULT
|
__WASI_EFAULT
|
||||||
@ -605,7 +575,7 @@ pub fn fd_write(
|
|||||||
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)
|
// return __WASI_EISDIR if dir (probably)
|
||||||
if let (Some(iovs_arr_cell), Some(nwritten_cell)) =
|
if let (Ok(iovs_arr_cell), Ok(nwritten_cell)) =
|
||||||
(iovs.deref(memory, 0, iovs_len), nwritten.deref(memory))
|
(iovs.deref(memory, 0, iovs_len), nwritten.deref(memory))
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
@ -659,6 +629,9 @@ pub fn path_filestat_get(
|
|||||||
path_len: u32,
|
path_len: u32,
|
||||||
buf: WasmPtr<__wasi_filestat_t>,
|
buf: WasmPtr<__wasi_filestat_t>,
|
||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
|
let mut state = get_wasi_state(ctx);
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
// check __WASI_RIGHT_PATH_FILESTAT_GET
|
// check __WASI_RIGHT_PATH_FILESTAT_GET
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
@ -768,7 +741,7 @@ pub fn path_open(
|
|||||||
|
|
||||||
// check for __WASI_RIGHT_PATH_OPEN somewhere, probably via dirfd
|
// check for __WASI_RIGHT_PATH_OPEN somewhere, probably via dirfd
|
||||||
|
|
||||||
if let (Some(fd_cell), Some(path_cell)) = (fd.deref(memory), path.deref(memory, 0, path_len)) {
|
if let (Ok(fd_cell), Ok(path_cell)) = (fd.deref(memory), path.deref(memory, 0, path_len)) {
|
||||||
// o_flags:
|
// o_flags:
|
||||||
// - __WASI_O_FLAG_CREAT (create if it does not exist)
|
// - __WASI_O_FLAG_CREAT (create if it does not exist)
|
||||||
// - __WASI_O_DIRECTORY (fail if not dir)
|
// - __WASI_O_DIRECTORY (fail if not dir)
|
||||||
@ -860,7 +833,7 @@ pub fn random_get(ctx: &mut Ctx, buf: WasmPtr<u8, Array>, buf_len: u32) -> __was
|
|||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let memory = ctx.memory(0);
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
if let Some(buf) = buf.deref(memory, 0, buf_len) {
|
if let Ok(buf) = buf.deref(memory, 0, buf_len) {
|
||||||
for i in 0..(buf_len as usize) {
|
for i in 0..(buf_len as usize) {
|
||||||
let random_byte = rng.gen::<u8>();
|
let random_byte = rng.gen::<u8>();
|
||||||
buf[i].set(random_byte);
|
buf[i].set(random_byte);
|
||||||
|
Loading…
Reference in New Issue
Block a user