mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-12 22:05:33 +00:00
implement map-dir for WASI; fix bug in path_open
This commit is contained in:
parent
4ddffb8285
commit
f9beef276d
@ -14,6 +14,7 @@ use self::state::{WasiFs, WasiState};
|
||||
use self::syscalls::*;
|
||||
|
||||
use std::ffi::c_void;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub use self::utils::is_wasi_module;
|
||||
|
||||
@ -29,6 +30,7 @@ pub fn generate_import_object(
|
||||
args: Vec<Vec<u8>>,
|
||||
envs: Vec<Vec<u8>>,
|
||||
preopened_files: Vec<String>,
|
||||
mapped_dirs: Vec<(PathBuf, String)>,
|
||||
) -> ImportObject {
|
||||
let state_gen = move || {
|
||||
fn state_destructor(data: *mut c_void) {
|
||||
@ -38,7 +40,7 @@ pub fn generate_import_object(
|
||||
}
|
||||
|
||||
let state = Box::new(WasiState {
|
||||
fs: WasiFs::new(&preopened_files).unwrap(),
|
||||
fs: WasiFs::new(&preopened_files, &mapped_dirs).unwrap(),
|
||||
args: &args[..],
|
||||
envs: &envs[..],
|
||||
});
|
||||
|
@ -175,21 +175,20 @@ pub struct WasiFs {
|
||||
}
|
||||
|
||||
impl WasiFs {
|
||||
pub fn new(preopened_dirs: &[String]) -> Result<Self, String> {
|
||||
/*let repo = RepoOpener::new()
|
||||
.create(true)
|
||||
.open("mem://wasmer-test-fs", "")
|
||||
.map_err(|e| e.to_string())?;*/
|
||||
pub fn new(
|
||||
preopened_dirs: &[String],
|
||||
mapped_dirs: &[(PathBuf, String)],
|
||||
) -> Result<Self, String> {
|
||||
debug!("wasi::fs::inodes");
|
||||
let inodes = Arena::new();
|
||||
let mut wasi_fs = Self {
|
||||
//repo: repo,
|
||||
name_map: HashMap::new(),
|
||||
inodes: inodes,
|
||||
fd_map: HashMap::new(),
|
||||
next_fd: Cell::new(3),
|
||||
inode_counter: Cell::new(1000),
|
||||
};
|
||||
debug!("wasi::fs::preopen_dirs");
|
||||
for dir in preopened_dirs {
|
||||
debug!("Attempting to preopen {}", &dir);
|
||||
// TODO: think about this
|
||||
@ -218,6 +217,36 @@ impl WasiFs {
|
||||
.create_fd(default_rights, default_rights, 0, inode)
|
||||
.expect("Could not open fd");
|
||||
}
|
||||
debug!("wasi::fs::mapped_dirs");
|
||||
for (src_dir, dest_dir) in mapped_dirs {
|
||||
debug!("Attempting to open {:?} at {}", src_dir, dest_dir);
|
||||
// TODO: think about this
|
||||
let default_rights = 0x1FFFFFFF; // all rights
|
||||
let cur_dir_metadata = src_dir
|
||||
.metadata()
|
||||
.expect("mapped dir not at previously verified location");
|
||||
let kind = if cur_dir_metadata.is_dir() {
|
||||
Kind::Dir {
|
||||
parent: None,
|
||||
path: src_dir.clone(),
|
||||
entries: Default::default(),
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"WASI only supports pre-opened directories right now; found \"{:?}\"",
|
||||
&src_dir,
|
||||
));
|
||||
};
|
||||
// TODO: handle nested pats in `file`
|
||||
let inode_val =
|
||||
InodeVal::from_file_metadata(&cur_dir_metadata, dest_dir.clone(), true, kind);
|
||||
|
||||
let inode = wasi_fs.inodes.insert(inode_val);
|
||||
wasi_fs.inodes[inode].stat.st_ino = wasi_fs.inode_counter.get();
|
||||
wasi_fs
|
||||
.create_fd(default_rights, default_rights, 0, inode)
|
||||
.expect("Could not open fd");
|
||||
}
|
||||
debug!("wasi::fs::end");
|
||||
Ok(wasi_fs)
|
||||
}
|
||||
@ -424,24 +453,18 @@ impl WasiFs {
|
||||
loop {
|
||||
path_segments.push(self.inodes[cur_inode].name.clone());
|
||||
|
||||
if let Kind::Dir { parent, .. } = &self.inodes[cur_inode].kind {
|
||||
if let Some(p_inode) = parent {
|
||||
cur_inode = *p_inode;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
if let Kind::Dir { path, .. } = &self.inodes[cur_inode].kind {
|
||||
return Some(path.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
path_segments.reverse();
|
||||
/*path_segments.reverse();
|
||||
Some(
|
||||
path_segments
|
||||
.iter()
|
||||
.skip(1)
|
||||
.fold(path_segments.first()?.clone(), |a, b| a + "/" + b),
|
||||
)
|
||||
)*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1465,6 +1465,7 @@ pub fn path_open(
|
||||
let file_path = cumulative_path;
|
||||
|
||||
let out_fd = if let Kind::Dir { entries, .. } = &mut state.fs.inodes[cur_dir_inode].kind {
|
||||
debug!("Hm");
|
||||
if let Some(child) = entries.get(file_name).cloned() {
|
||||
let child_inode_val = &state.fs.inodes[child];
|
||||
// early return based on flags
|
||||
@ -1485,10 +1486,11 @@ pub fn path_open(
|
||||
.fs
|
||||
.create_fd(fs_rights_base, fs_rights_inheriting, fs_flags, child))
|
||||
} else {
|
||||
let file_metadata = wasi_try!(file_path.metadata().map_err(|_| __WASI_ENOENT));
|
||||
debug!("Attempting to load file from host system");
|
||||
let file_metadata = file_path.metadata();
|
||||
// if entry does not exist in parent directory, try to lazily
|
||||
// load it; possibly creating or truncating it if flags set
|
||||
let kind = if file_metadata.is_dir() {
|
||||
let kind = if file_metadata.is_ok() && file_metadata.unwrap().is_dir() {
|
||||
// special dir logic
|
||||
Kind::Dir {
|
||||
parent: Some(cur_dir_inode),
|
||||
|
@ -97,7 +97,11 @@ struct Run {
|
||||
#[structopt(long = "dir", multiple = true, group = "wasi")]
|
||||
pre_opened_directories: Vec<String>,
|
||||
|
||||
// Custom code loader
|
||||
/// Map a host directory to a different location for the wasm module
|
||||
#[structopt(long = "map-dir", multiple = true)]
|
||||
mapped_dirs: Vec<String>,
|
||||
|
||||
/// Custom code loader
|
||||
#[structopt(
|
||||
long = "loader",
|
||||
raw(possible_values = "LoaderName::variants()", case_insensitive = "true")
|
||||
@ -227,6 +231,28 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let disable_cache = options.disable_cache;
|
||||
|
||||
let mapped_dirs = {
|
||||
let mut md = vec![];
|
||||
for entry in options.mapped_dirs.iter() {
|
||||
if let &[source, dest] = &entry.split(':').collect::<Vec<&str>>()[..] {
|
||||
let pb = PathBuf::from(&source);
|
||||
if let Ok(pb_metadata) = pb.metadata() {
|
||||
if !pb_metadata.is_dir() {
|
||||
return Err(format!("\"{}\" exists, but it is not a directory", &source));
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Directory \"{}\" does not exist", &source));
|
||||
}
|
||||
md.push((pb, dest.to_string()));
|
||||
continue;
|
||||
}
|
||||
return Err(format!(
|
||||
"Directory mappings must consist of two paths separate by a colon. Found {}",
|
||||
&entry
|
||||
));
|
||||
}
|
||||
md
|
||||
};
|
||||
let wasm_path = &options.path;
|
||||
|
||||
let mut wasm_binary: Vec<u8> = read_file_contents(wasm_path).map_err(|err| {
|
||||
@ -445,6 +471,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
||||
.collect(),
|
||||
options.pre_opened_directories.clone(),
|
||||
mapped_dirs,
|
||||
);
|
||||
|
||||
let instance = module
|
||||
|
Loading…
Reference in New Issue
Block a user