Skip to content

Commit

Permalink
avoid opening files when not needed in WASI, check for write permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark McCaskey committed May 15, 2019
1 parent 245cc32 commit b275273
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 55 deletions.
13 changes: 13 additions & 0 deletions lib/wasi/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,16 @@ pub struct WasiState<'a> {
pub args: &'a [Vec<u8>],
pub envs: &'a [Vec<u8>],
}

pub fn host_file_type_to_wasi_file_type(file_type: fs::FileType) -> __wasi_filetype_t {
// TODO: handle other file types
if file_type.is_dir() {
__WASI_FILETYPE_DIRECTORY
} else if file_type.is_file() {
__WASI_FILETYPE_REGULAR_FILE
} else if file_type.is_symlink() {
__WASI_FILETYPE_SYMBOLIC_LINK
} else {
__WASI_FILETYPE_UNKNOWN
}
}
74 changes: 19 additions & 55 deletions lib/wasi/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ pub mod windows;
use self::types::*;
use crate::{
ptr::{Array, WasmPtr},
state::{Fd, InodeVal, Kind, WasiFile, WasiState, MAX_SYMLINKS},
state::{
host_file_type_to_wasi_file_type, Fd, InodeVal, Kind, WasiFile, WasiState, MAX_SYMLINKS,
},
ExitCode,
};
use rand::{thread_rng, Rng};
Expand Down Expand Up @@ -796,19 +798,9 @@ pub fn fd_readdir(
d_next: cur_cookie,
d_ino: 0, // TODO: inode
d_namlen: namlen as u32,
d_type: {
let file_type = wasi_try!(entry.file_type().map_err(|_| __WASI_EIO));
// TODO: handle other file types
if file_type.is_dir() {
__WASI_FILETYPE_DIRECTORY
} else if file_type.is_file() {
__WASI_FILETYPE_REGULAR_FILE
} else if file_type.is_symlink() {
__WASI_FILETYPE_SYMBOLIC_LINK
} else {
__WASI_FILETYPE_UNKNOWN
}
},
d_type: host_file_type_to_wasi_file_type(wasi_try!(entry
.file_type()
.map_err(|_| __WASI_EIO))),
};
let dirent_bytes = dirent_to_le_bytes(&dirent);
let upper_limit = std::cmp::min(
Expand Down Expand Up @@ -1219,64 +1211,31 @@ pub fn path_filestat_get(
}
}

let final_inode = match &state.fs.inodes[inode].kind {
let stat = match &state.fs.inodes[inode].kind {
Kind::Dir { path, entries, .. } => {
// TODO: fail earlier if size 0
// read it from internal data structures if we can
let last_segment = path_vec.last().unwrap();
cumulative_path.push(last_segment);

if entries.contains_key(last_segment) {
entries[last_segment]
state.fs.inodes[entries[last_segment]].stat
} else {
// lazily load it if we can
// otherwise read it from the host FS
if !cumulative_path.exists() {
return __WASI_ENOENT;
}
let final_path_metadata =
wasi_try!(cumulative_path.metadata().map_err(|_| __WASI_EIO));
let new_inode = if final_path_metadata.is_dir() {
debug!("Opening host directory {:#?}", &cumulative_path);
state.fs.inodes.insert(InodeVal {
stat: __wasi_filestat_t::default(),
is_preopened: false, // is this correct?
name: last_segment.clone(),
kind: Kind::Dir {
parent: Some(inode),
path: std::path::PathBuf::from(&last_segment),
entries: Default::default(),
},
})
} else {
debug!("Opening host file {:#?}", &cumulative_path);
let real_open_file = wasi_try!(std::fs::OpenOptions::new()
.read(true)
.write(true)
.open(&cumulative_path)
.map_err(|_| __WASI_ENOENT));

state.fs.inodes.insert(InodeVal {
stat: __wasi_filestat_t::default(),
is_preopened: false, // is this correct?
name: last_segment.clone(),
kind: Kind::File {
handle: WasiFile::HostFile(real_open_file),
},
})
};
// reborrow to insert entry
if let Kind::Dir { entries, .. } = &mut state.fs.inodes[inode].kind {
entries.insert(last_segment.clone(), new_inode);
__wasi_filestat_t {
st_filetype: host_file_type_to_wasi_file_type(final_path_metadata.file_type()),
..Default::default()
}
new_inode
}
}
_ => {
return __WASI_ENOTDIR;
}
};

let stat = state.fs.inodes[final_inode].stat;

buf_cell.set(stat);

__WASI_ESUCCESS
Expand Down Expand Up @@ -1540,7 +1499,12 @@ pub fn path_open(
// file is not a dir
let real_opened_file = {
let mut open_options = std::fs::OpenOptions::new();
let open_options = open_options.read(true).write(true);
let open_options = open_options.read(true);
let open_options = if dbg!(fs_rights_base & __WASI_RIGHT_FD_WRITE) != 0 {
open_options.write(true)
} else {
open_options
};
let open_options = if o_flags & __WASI_O_CREAT != 0 {
debug!(
"File {:?} may be created when opened if it does not exist",
Expand Down

0 comments on commit b275273

Please sign in to comment.