port in args and env. slightly different style

building up a bunch of deferred errors in the CtxBuilder sucks. so does
reporting errors right away. Idk what to do here?
This commit is contained in:
Pat Hickey
2020-12-11 15:33:15 -08:00
parent aef8be560f
commit d586574b1f
5 changed files with 86 additions and 8 deletions

View File

@@ -25,7 +25,7 @@ pub fn instantiate(
// Additionally register any preopened directories if we have them. // Additionally register any preopened directories if we have them.
let mut builder = wasi_c2::WasiCtx::builder(); let mut builder = wasi_c2::WasiCtx::builder();
builder.arg(bin_name).arg(".").inherit_stdio(); builder.arg(bin_name)?.arg(".")?.inherit_stdio();
/* /*
if let Some(workspace) = workspace { if let Some(workspace) = workspace {

View File

@@ -1,5 +1,6 @@
use crate::dir::{DirCaps, DirEntry, WasiDir}; use crate::dir::{DirCaps, DirEntry, WasiDir};
use crate::file::{FileCaps, FileEntry, WasiFile}; use crate::file::{FileCaps, FileEntry, WasiFile};
use crate::string_array::{StringArray, StringArrayError};
use crate::table::Table; use crate::table::Table;
use crate::Error; use crate::Error;
use std::cell::{RefCell, RefMut}; use std::cell::{RefCell, RefMut};
@@ -7,6 +8,8 @@ use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
pub struct WasiCtx { pub struct WasiCtx {
pub(crate) args: StringArray,
pub(crate) env: StringArray,
table: Rc<RefCell<Table>>, table: Rc<RefCell<Table>>,
} }
@@ -17,6 +20,8 @@ impl WasiCtx {
pub fn new() -> Self { pub fn new() -> Self {
WasiCtx { WasiCtx {
args: StringArray::new(),
env: StringArray::new(),
table: Rc::new(RefCell::new(Table::new())), table: Rc::new(RefCell::new(Table::new())),
} }
} }
@@ -64,9 +69,9 @@ impl WasiCtxBuilder {
pub fn build(self) -> Result<WasiCtx, Error> { pub fn build(self) -> Result<WasiCtx, Error> {
Ok(self.0) Ok(self.0)
} }
pub fn arg(&mut self, _arg: &str) -> &mut Self { pub fn arg(&mut self, arg: &str) -> Result<&mut Self, StringArrayError> {
// Intentionally left blank. We do not handle arguments yet. self.0.args.push(arg.to_owned())?;
self Ok(self)
} }
pub fn inherit_stdio(&mut self) -> &mut Self { pub fn inherit_stdio(&mut self) -> &mut Self {
self.0.insert_file( self.0.insert_file(

View File

@@ -6,9 +6,11 @@ mod error;
mod file; mod file;
pub mod snapshots; pub mod snapshots;
pub mod stdio; pub mod stdio;
mod string_array;
pub mod table; pub mod table;
pub use ctx::WasiCtx; pub use ctx::WasiCtx;
pub use dir::{DirCaps, WasiDir}; pub use dir::{DirCaps, WasiDir};
pub use error::Error; pub use error::Error;
pub use file::{FileCaps, WasiFile}; pub use file::{FileCaps, WasiFile};
pub use string_array::StringArrayError;

View File

@@ -106,11 +106,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
argv: &GuestPtr<'b, GuestPtr<'b, u8>>, argv: &GuestPtr<'b, GuestPtr<'b, u8>>,
argv_buf: &GuestPtr<'b, u8>, argv_buf: &GuestPtr<'b, u8>,
) -> Result<(), Error> { ) -> Result<(), Error> {
unimplemented!() self.args.write_to_guest(argv_buf, argv)
} }
fn args_sizes_get(&self) -> Result<(types::Size, types::Size), Error> { fn args_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
unimplemented!() Ok((self.args.number_elements(), self.args.cumulative_size()))
} }
fn environ_get<'b>( fn environ_get<'b>(
@@ -118,11 +118,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
environ: &GuestPtr<'b, GuestPtr<'b, u8>>, environ: &GuestPtr<'b, GuestPtr<'b, u8>>,
environ_buf: &GuestPtr<'b, u8>, environ_buf: &GuestPtr<'b, u8>,
) -> Result<(), Error> { ) -> Result<(), Error> {
unimplemented!() self.env.write_to_guest(environ_buf, environ)
} }
fn environ_sizes_get(&self) -> Result<(types::Size, types::Size), Error> { fn environ_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
unimplemented!() Ok((self.env.number_elements(), self.env.cumulative_size()))
} }
fn clock_res_get(&self, id: types::Clockid) -> Result<types::Timestamp, Error> { fn clock_res_get(&self, id: types::Clockid) -> Result<types::Timestamp, Error> {

View File

@@ -0,0 +1,71 @@
use crate::Error;
use wiggle::GuestPtr;
pub struct StringArray {
elems: Vec<String>,
}
#[derive(Debug, thiserror::Error)]
pub enum StringArrayError {
#[error("Number of elements exceeds 2^32")]
NumberElements,
#[error("Element size exceeds 2^32")]
ElementSize,
#[error("Cumulative size exceeds 2^32")]
CumulativeSize,
}
impl StringArray {
pub fn new() -> Self {
StringArray { elems: Vec::new() }
}
pub fn push(&mut self, elem: String) -> Result<(), StringArrayError> {
if self.elems.len() + 1 > std::u32::MAX as usize {
return Err(StringArrayError::NumberElements);
}
if elem.as_bytes().len() + 1 > std::u32::MAX as usize {
return Err(StringArrayError::ElementSize);
}
if self.cumulative_size() as usize + elem.as_bytes().len() + 1 > std::u32::MAX as usize {
return Err(StringArrayError::CumulativeSize);
}
self.elems.push(elem);
Ok(())
}
pub fn number_elements(&self) -> u32 {
self.elems.len() as u32
}
pub fn cumulative_size(&self) -> u32 {
self.elems
.iter()
.map(|e| e.as_bytes().len() + 1)
.sum::<usize>() as u32
}
pub fn write_to_guest<'a>(
&self,
buffer: &GuestPtr<'a, u8>,
element_heads: &GuestPtr<'a, GuestPtr<'a, u8>>,
) -> Result<(), Error> {
let element_heads = element_heads.as_array(self.number_elements());
let buffer = buffer.as_array(self.cumulative_size());
let mut cursor = 0;
for (elem, head) in self.elems.iter().zip(element_heads.iter()) {
let bytes = elem.as_bytes();
let len = bytes.len() as u32;
{
let elem_buffer = buffer
.get_range(cursor..(cursor + len))
.ok_or(Error::Inval)?; // Elements don't fit in buffer provided
elem_buffer.copy_from_slice(bytes)?;
}
buffer.get(cursor + len).ok_or(Error::Inval)?.write(0)?; // 0 terminate
head?.write(buffer.get(cursor).expect("already validated"))?;
cursor += len + 1;
}
Ok(())
}
}