Skip to content
This repository has been archived by the owner on Nov 9, 2019. It is now read-only.

Further refactor of hostcalls #38

Merged
merged 4 commits into from
Jul 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ cfg_if::cfg_if! {
"big_random_buf" => false,
"sched_yield" => false,
"file_pread_pwrite" => false,
"renumber" => false,
_ => true,
}
} else {
Expand Down
Binary file added misc_testsuite/renumber.wasm
Binary file not shown.
46 changes: 22 additions & 24 deletions src/ctx.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::fdentry::FdEntry;
use super::host;
use super::sys::{dev_null, errno_from_host};
use crate::fdentry::FdEntry;
use crate::sys::{dev_null, errno_from_host};
use crate::{host, Result};
use std::borrow::Borrow;
use std::collections::HashMap;
use std::ffi::CString;
Expand All @@ -16,7 +16,7 @@ pub struct WasiCtxBuilder {

impl WasiCtxBuilder {
/// Builder for a new `WasiCtx`.
pub fn new() -> Result<Self, host::__wasi_errno_t> {
pub fn new() -> Result<Self> {
let mut builder = Self {
fds: HashMap::new(),
preopens: HashMap::new(),
Expand All @@ -31,35 +31,32 @@ impl WasiCtxBuilder {
Ok(builder)
}

pub fn args<S: AsRef<str>>(
mut self,
args: impl Iterator<Item = S>,
) -> Result<Self, host::__wasi_errno_t> {
let args: Result<Vec<CString>, _> = args
pub fn args<S: AsRef<str>>(mut self, args: impl Iterator<Item = S>) -> Result<Self> {
let args: Result<Vec<CString>> = args
.map(|arg| CString::new(arg.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE))
.collect();
self.args = args?;
Ok(self)
}

pub fn arg(mut self, arg: &str) -> Result<Self, host::__wasi_errno_t> {
pub fn arg(mut self, arg: &str) -> Result<Self> {
self.args
.push(CString::new(arg).map_err(|_| host::__WASI_ENOTCAPABLE)?);
Ok(self)
}

pub fn inherit_stdio(mut self) -> Result<Self, host::__wasi_errno_t> {
pub fn inherit_stdio(mut self) -> Result<Self> {
self.fds.insert(0, FdEntry::duplicate_stdin()?);
self.fds.insert(1, FdEntry::duplicate_stdout()?);
self.fds.insert(2, FdEntry::duplicate_stderr()?);
Ok(self)
}

pub fn inherit_env(self) -> Result<Self, host::__wasi_errno_t> {
pub fn inherit_env(self) -> Result<Self> {
self.envs(std::env::vars())
}

pub fn env<S: AsRef<str>>(mut self, k: S, v: S) -> Result<Self, host::__wasi_errno_t> {
pub fn env<S: AsRef<str>>(mut self, k: S, v: S) -> Result<Self> {
self.env.insert(
CString::new(k.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE)?,
CString::new(v.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE)?,
Expand All @@ -70,8 +67,8 @@ impl WasiCtxBuilder {
pub fn envs<S: AsRef<str>, T: Borrow<(S, S)>>(
mut self,
envs: impl Iterator<Item = T>,
) -> Result<Self, host::__wasi_errno_t> {
let env: Result<HashMap<CString, CString>, _> = envs
) -> Result<Self> {
let env: Result<HashMap<CString, CString>> = envs
.map(|t| {
let (k, v) = t.borrow();
let k = CString::new(k.as_ref()).map_err(|_| host::__WASI_ENOTCAPABLE);
Expand All @@ -91,7 +88,7 @@ impl WasiCtxBuilder {
self
}

pub fn build(mut self) -> Result<WasiCtx, host::__wasi_errno_t> {
pub fn build(mut self) -> Result<WasiCtx> {
// startup code starts looking at fd 3 for preopens
let mut preopen_fd = 3;
for (guest_path, dir) in self.preopens {
Expand Down Expand Up @@ -147,20 +144,24 @@ impl WasiCtx {
/// - Environment variables are inherited from the host process.
///
/// To override these behaviors, use `WasiCtxBuilder`.
pub fn new<S: AsRef<str>>(args: impl Iterator<Item = S>) -> Result<Self, host::__wasi_errno_t> {
pub fn new<S: AsRef<str>>(args: impl Iterator<Item = S>) -> Result<Self> {
WasiCtxBuilder::new()
.and_then(|ctx| ctx.args(args))
.and_then(|ctx| ctx.inherit_stdio())
.and_then(|ctx| ctx.inherit_env())
.and_then(|ctx| ctx.build())
}

pub fn contains_fd_entry(&self, fd: host::__wasi_fd_t) -> bool {
self.fds.contains_key(&fd)
}

pub fn get_fd_entry(
&self,
fd: host::__wasi_fd_t,
rights_base: host::__wasi_rights_t,
rights_inheriting: host::__wasi_rights_t,
) -> Result<&FdEntry, host::__wasi_errno_t> {
) -> Result<&FdEntry> {
if let Some(fe) = self.fds.get(&fd) {
Self::validate_rights(fe, rights_base, rights_inheriting).and(Ok(fe))
} else {
Expand All @@ -173,7 +174,7 @@ impl WasiCtx {
fd: host::__wasi_fd_t,
rights_base: host::__wasi_rights_t,
rights_inheriting: host::__wasi_rights_t,
) -> Result<&mut FdEntry, host::__wasi_errno_t> {
) -> Result<&mut FdEntry> {
if let Some(fe) = self.fds.get_mut(&fd) {
Self::validate_rights(fe, rights_base, rights_inheriting).and(Ok(fe))
} else {
Expand All @@ -185,18 +186,15 @@ impl WasiCtx {
fe: &FdEntry,
rights_base: host::__wasi_rights_t,
rights_inheriting: host::__wasi_rights_t,
) -> Result<(), host::__wasi_errno_t> {
) -> Result<()> {
if !fe.rights_base & rights_base != 0 || !fe.rights_inheriting & rights_inheriting != 0 {
Err(host::__WASI_ENOTCAPABLE)
} else {
Ok(())
}
}

pub fn insert_fd_entry(
&mut self,
fe: FdEntry,
) -> Result<host::__wasi_fd_t, host::__wasi_errno_t> {
pub fn insert_fd_entry(&mut self, fe: FdEntry) -> Result<host::__wasi_fd_t> {
// never insert where stdio handles usually are
let mut fd = 3;
while self.fds.contains_key(&fd) {
Expand Down
52 changes: 44 additions & 8 deletions src/fdentry.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use super::host;
use crate::sys::{errno_from_host, fdentry_impl};
use crate::{host, Result};

use std::fs;
use std::io;
use std::mem::ManuallyDrop;
use std::path::PathBuf;
use std::{fs, io};

#[derive(Debug)]
pub enum Descriptor {
Expand All @@ -14,6 +13,43 @@ pub enum Descriptor {
Stderr,
}

impl Descriptor {
pub fn as_file(&self) -> Result<&fs::File> {
match self {
Descriptor::File(f) => Ok(f),
_ => Err(host::__WASI_EBADF),
}
}

pub fn is_file(&self) -> bool {
match self {
Descriptor::File(_) => true,
_ => false,
}
}

pub fn is_stdin(&self) -> bool {
match self {
Descriptor::Stdin => true,
_ => false,
}
}

pub fn is_stdout(&self) -> bool {
match self {
Descriptor::Stdout => true,
_ => false,
}
}

pub fn is_stderr(&self) -> bool {
match self {
Descriptor::Stderr => true,
_ => false,
}
}
}

#[derive(Debug)]
pub struct FdObject {
pub file_type: host::__wasi_filetype_t,
Expand All @@ -39,7 +75,7 @@ impl Drop for FdObject {
}

impl FdEntry {
pub fn from(file: fs::File) -> Result<Self, host::__wasi_errno_t> {
pub fn from(file: fs::File) -> Result<Self> {
fdentry_impl::determine_type_and_access_rights(&file).map(
|(file_type, rights_base, rights_inheriting)| Self {
fd_object: FdObject {
Expand All @@ -54,13 +90,13 @@ impl FdEntry {
)
}

pub fn duplicate(file: &fs::File) -> Result<Self, host::__wasi_errno_t> {
pub fn duplicate(file: &fs::File) -> Result<Self> {
file.try_clone()
.map_err(|err| err.raw_os_error().map_or(host::__WASI_EIO, errno_from_host))
.and_then(Self::from)
}

pub fn duplicate_stdin() -> Result<Self, host::__wasi_errno_t> {
pub fn duplicate_stdin() -> Result<Self> {
fdentry_impl::determine_type_and_access_rights(&io::stdin()).map(
|(file_type, rights_base, rights_inheriting)| Self {
fd_object: FdObject {
Expand All @@ -75,7 +111,7 @@ impl FdEntry {
)
}

pub fn duplicate_stdout() -> Result<Self, host::__wasi_errno_t> {
pub fn duplicate_stdout() -> Result<Self> {
fdentry_impl::determine_type_and_access_rights(&io::stdout()).map(
|(file_type, rights_base, rights_inheriting)| Self {
fd_object: FdObject {
Expand All @@ -90,7 +126,7 @@ impl FdEntry {
)
}

pub fn duplicate_stderr() -> Result<Self, host::__wasi_errno_t> {
pub fn duplicate_stderr() -> Result<Self> {
fdentry_impl::determine_type_and_access_rights(&io::stderr()).map(
|(file_type, rights_base, rights_inheriting)| Self {
fd_object: FdObject {
Expand Down
6 changes: 3 additions & 3 deletions src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! still largely reflects that.
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

use crate::Result;
use std::{io, slice, str};

pub type void = ::std::os::raw::c_void;
Expand Down Expand Up @@ -499,15 +499,15 @@ pub unsafe fn iovec_to_host_mut<'a>(iovec: &'a mut __wasi_iovec_t) -> io::IoSlic
///
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
/// `__WASI_EILSEQ` error is returned.
pub fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str, __wasi_errno_t> {
pub fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> {
str::from_utf8(s).map_err(|_| __WASI_EILSEQ)
}

/// Creates owned WASI path from byte vector.
///
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
/// `__WASI_EILSEQ` error is returned.
pub fn path_from_vec<S: Into<Vec<u8>>>(s: S) -> Result<String, __wasi_errno_t> {
pub fn path_from_vec<S: Into<Vec<u8>>>(s: S) -> Result<String> {
String::from_utf8(s.into()).map_err(|_| __WASI_EILSEQ)
}

Expand Down
Loading