Skip to content

Commit

Permalink
Allow using virtual files for stdin/out/err
Browse files Browse the repository at this point in the history
This adds the ability to use virtual files not only for the file system
in WASI, but also for stdin, stdout and stderr.
  • Loading branch information
CryZe committed May 22, 2020
1 parent f365391 commit 6ff3a9b
Showing 1 changed file with 33 additions and 22 deletions.
55 changes: 33 additions & 22 deletions crates/wasi-common/src/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ use crate::handle::Handle;
use crate::sys::osdir::OsDir;
use crate::sys::osother::{OsOther, OsOtherExt};
use crate::sys::stdio::{Stderr, StderrExt, Stdin, StdinExt, Stdout, StdoutExt};
use crate::virtfs::{VirtualDir, VirtualDirEntry};
use crate::wasi::types;
use crate::wasi::{Errno, Result};
use crate::virtfs::{FileContents, InMemoryFile, VirtualDir, VirtualDirEntry};
use crate::wasi::{types, Errno, Result};
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap;
Expand Down Expand Up @@ -48,6 +47,7 @@ type WasiCtxBuilderResult<T> = std::result::Result<T, WasiCtxBuilderError>;
enum PendingEntry {
Thunk(fn() -> io::Result<Box<dyn Handle>>),
OsHandle(File),
Virtual(Box<dyn FileContents>),
}

impl std::fmt::Debug for PendingEntry {
Expand All @@ -59,6 +59,7 @@ impl std::fmt::Debug for PendingEntry {
f as *const fn() -> io::Result<Box<dyn Handle>>
),
Self::OsHandle(f) => write!(fmt, "PendingEntry::OsHandle({:?})", f),
Self::Virtual(_) => write!(fmt, "PendingEntry::Virtual(...)"),
}
}
}
Expand Down Expand Up @@ -247,24 +248,42 @@ impl WasiCtxBuilder {
self
}

/// Provide a File to use as stdin
/// Provide a File to use as stdin.
pub fn stdin(&mut self, file: File) -> &mut Self {
self.stdin = Some(PendingEntry::OsHandle(file));
self
}

/// Provide a File to use as stdout
/// Provide a File to use as stdout.
pub fn stdout(&mut self, file: File) -> &mut Self {
self.stdout = Some(PendingEntry::OsHandle(file));
self
}

/// Provide a File to use as stderr
/// Provide a File to use as stderr.
pub fn stderr(&mut self, file: File) -> &mut Self {
self.stderr = Some(PendingEntry::OsHandle(file));
self
}

/// Provide a virtual file to use as stdin.
pub fn stdin_virt(&mut self, file: Box<dyn FileContents>) -> &mut Self {
self.stdin = Some(PendingEntry::Virtual(file));
self
}

/// Provide a virtual file to use as stdout.
pub fn stdout_virt(&mut self, file: Box<dyn FileContents>) -> &mut Self {
self.stdout = Some(PendingEntry::Virtual(file));
self
}

/// Provide a virtual file to use as stderr.
pub fn stderr_virt(&mut self, file: Box<dyn FileContents>) -> &mut Self {
self.stderr = Some(PendingEntry::Virtual(file));
self
}

/// Add a preopened directory.
pub fn preopened_dir<P: AsRef<Path>>(&mut self, dir: File, guest_path: P) -> &mut Self {
let preopen = PendingPreopen::new(move || {
Expand Down Expand Up @@ -360,23 +379,15 @@ impl WasiCtxBuilder {
self.stderr.take().unwrap(),
] {
log::debug!("WasiCtx inserting entry {:?}", pending);
let fd = match pending {
PendingEntry::Thunk(f) => {
let handle = EntryHandle::from(f()?);
let entry = Entry::new(handle);
entries
.insert(entry)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?
}
PendingEntry::OsHandle(f) => {
let handle = OsOther::try_from(f)?;
let handle = EntryHandle::new(handle);
let entry = Entry::new(handle);
entries
.insert(entry)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?
}
let handle = match pending {
PendingEntry::Thunk(f) => EntryHandle::from(f()?),
PendingEntry::OsHandle(f) => EntryHandle::new(OsOther::try_from(f)?),
PendingEntry::Virtual(f) => EntryHandle::new(InMemoryFile::new(f)),
};
let entry = Entry::new(handle);
let fd = entries
.insert(entry)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
log::debug!("WasiCtx inserted at {:?}", fd);
}
// Then add the preopen entries.
Expand Down

0 comments on commit 6ff3a9b

Please sign in to comment.