Browse Source

Support command-line argument preopens.

pull/6374/head
Dan Gohman 2 years ago
parent
commit
bb86a3ea6b
  1. 77
      src/lib.rs
  2. 2
      src/macros.rs

77
src/lib.rs

@ -81,6 +81,12 @@ pub unsafe extern "C" fn main(
}
state.args = Some(slice::from_raw_parts(args_ptr, args_len));
// Initialize `arg_preopens`.
let preopens: &'static [Preopen] =
unsafe { std::slice::from_raw_parts(preopens.base, preopens.len) };
state.process_preopens(&preopens);
state.arg_preopens.set(Some(preopens));
Ok(())
});
@ -2289,9 +2295,13 @@ struct State {
/// to take care of initialization.
env_vars: Cell<Option<&'static [StrTuple]>>,
/// Preopened directories passed along with `main` args. Access with
/// `State::get_preopens` to take care of initialization.
arg_preopens: Cell<Option<&'static [Preopen]>>,
/// Preopened directories. Initialized lazily. Access with `State::get_preopens`
/// to take care of initialization.
preopens: Cell<Option<&'static [Preopen]>>,
env_preopens: Cell<Option<&'static [Preopen]>>,
/// Cache for the `fd_readdir` call for a final `wasi::Dirent` plus path
/// name that didn't fit into the caller's buffer.
@ -2369,7 +2379,7 @@ const fn bump_arena_size() -> usize {
start -= size_of::<DirentCache>();
// Remove miscellaneous metadata also stored in state.
start -= 24 * size_of::<usize>();
start -= 25 * size_of::<usize>();
// Everything else is the `command_data` allocation.
start
@ -2478,7 +2488,8 @@ impl State {
long_lived_arena: BumpArena::new(),
args: None,
env_vars: Cell::new(None),
preopens: Cell::new(None),
arg_preopens: Cell::new(None),
env_preopens: Cell::new(None),
dirent_cache: DirentCache {
stream: Cell::new(None),
for_fd: Cell::new(0),
@ -2678,8 +2689,9 @@ impl State {
self.env_vars.get().trapping_unwrap()
}
fn get_preopens(&self) -> &[Preopen] {
if self.preopens.get().is_none() {
fn get_preopens(&self) -> (Option<&[Preopen]>, &[Preopen]) {
// Lazily initialize `env_preopens`.
if self.env_preopens.get().is_none() {
#[link(wasm_import_module = "environment-preopens")]
extern "C" {
#[link_name = "preopens"]
@ -2698,26 +2710,47 @@ impl State {
// cast this to a &'static slice:
std::slice::from_raw_parts(list.base, list.len)
};
for preopen in preopens {
// Expectation is that the descriptor index is initialized with
// stdio (0,1,2) and no others, so that preopens are 3..
self.push_desc(Descriptor::Streams(Streams {
input: Cell::new(None),
output: Cell::new(None),
type_: StreamType::File(File {
fd: preopen.descriptor,
position: Cell::new(0),
append: false,
}),
}))
.trapping_unwrap();
}
self.preopens.set(Some(preopens));
self.process_preopens(preopens);
self.env_preopens.set(Some(preopens));
}
self.preopens.get().trapping_unwrap()
let arg_preopens = self.arg_preopens.get();
let env_preopens = self.env_preopens.get().trapping_unwrap();
(arg_preopens, env_preopens)
}
fn get_preopen(&self, fd: Fd) -> Option<&Preopen> {
self.get_preopens().get(fd.checked_sub(3)? as usize)
// Lazily initialize the preopens and obtain the two slices.
let (arg_preopens, env_preopens) = self.get_preopens();
// Subtract 3 or the stdio indices to compute the preopen index.
let index = fd.checked_sub(3)? as usize;
// Index into the conceptually concatenated preopen slices.
if let Some(arg_preopens) = arg_preopens {
if let Some(preopen) = arg_preopens.get(index) {
return Some(preopen);
}
env_preopens.get(index - arg_preopens.len())
} else {
env_preopens.get(index)
}
}
fn process_preopens(&self, preopens: &[Preopen]) {
for preopen in preopens {
// Expectation is that the descriptor index is initialized with
// stdio (0,1,2) and no others, so that preopens are 3..
self.push_desc(Descriptor::Streams(Streams {
input: Cell::new(None),
output: Cell::new(None),
type_: StreamType::File(File {
fd: preopen.descriptor,
position: Cell::new(0),
append: false,
}),
}))
.trapping_unwrap();
}
}
}

2
src/macros.rs

@ -54,6 +54,7 @@ macro_rules! unreachable {
() => {{
eprint!("unreachable executed at line ");
crate::macros::eprint_u32(line!());
eprint!("\n");
wasm32::unreachable()
}};
@ -62,6 +63,7 @@ macro_rules! unreachable {
crate::macros::eprint_u32(line!());
eprint!(": ");
eprintln!($arg);
eprint!("\n");
wasm32::unreachable()
}};
}

Loading…
Cancel
Save