Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update WASI fs abstraction to open files on each rw #448

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 62 additions & 10 deletions lib/wasi/src/state.rs
Expand Up @@ -18,65 +18,117 @@ pub const MAX_SYMLINKS: usize = 100;

#[derive(Debug)]
pub enum WasiFile {
HostFile(fs::File),
HostFile { path: PathBuf, offset: u64 },
}

impl WasiFile {
pub fn new_host_file(path: PathBuf) -> WasiFile {
WasiFile::HostFile { path, offset: 0 }
}
}

impl Write for WasiFile {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self {
WasiFile::HostFile(hf) => hf.write(buf),
WasiFile::HostFile { path, offset } => {
let mut file = fs::OpenOptions::new().write(true).open(path)?;
file.seek(io::SeekFrom::Start(*offset))?;
file.write(buf)
}
}
}

fn flush(&mut self) -> io::Result<()> {
match self {
WasiFile::HostFile(hf) => hf.flush(),
WasiFile::HostFile { path, offset } => {
let mut file = fs::OpenOptions::new().write(true).open(path)?;
file.seek(io::SeekFrom::Start(*offset))?;
file.flush()
}
}
}

fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
match self {
WasiFile::HostFile(hf) => hf.write_all(buf),
WasiFile::HostFile { path, offset } => {
let mut file = fs::OpenOptions::new().write(true).open(path)?;
file.seek(io::SeekFrom::Start(*offset))?;
file.write_all(buf)
}
}
}

fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
match self {
WasiFile::HostFile(hf) => hf.write_fmt(fmt),
WasiFile::HostFile { path, offset } => {
let mut file = fs::OpenOptions::new().write(true).open(path)?;
file.seek(io::SeekFrom::Start(*offset))?;
file.write_fmt(fmt)
}
}
}
}

impl Read for WasiFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
WasiFile::HostFile(hf) => hf.read(buf),
WasiFile::HostFile { path, offset } => {
let mut file = fs::OpenOptions::new().read(true).open(path)?;
file.seek(io::SeekFrom::Start(*offset))?;
file.read(buf)
}
}
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
match self {
WasiFile::HostFile(hf) => hf.read_to_end(buf),
WasiFile::HostFile { path, offset } => {
let mut file = fs::OpenOptions::new().read(true).open(path)?;
file.seek(io::SeekFrom::Start(*offset))?;
file.read_to_end(buf)
}
}
}

fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
match self {
WasiFile::HostFile(hf) => hf.read_to_string(buf),
WasiFile::HostFile { path, offset } => {
let mut file = fs::OpenOptions::new().read(true).open(path)?;
file.seek(io::SeekFrom::Start(*offset))?;
file.read_to_string(buf)
}
}
}

fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
match self {
WasiFile::HostFile(hf) => hf.read_exact(buf),
WasiFile::HostFile { path, offset } => {
let mut file = fs::OpenOptions::new().read(true).open(path)?;
file.seek(io::SeekFrom::Start(*offset))?;
file.read_exact(buf)
}
}
}
}

impl Seek for WasiFile {
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
match self {
WasiFile::HostFile(hf) => hf.seek(pos),
WasiFile::HostFile { path, offset } => {
match pos {
io::SeekFrom::Start(v) => {
*offset = v;
}
io::SeekFrom::Current(v) => {
*offset = ((*offset as i64) + v) as u64;
}
io::SeekFrom::End(v) => {
// TODO: investigate this for an off by 1 error
*offset = (path.metadata()?.len() as i64 - v) as u64;
}
};
Ok(*offset)
}
}
}
}
Expand Down
25 changes: 8 additions & 17 deletions lib/wasi/src/syscalls/mod.rs
Expand Up @@ -1248,18 +1248,12 @@ pub fn path_filestat_get(
})
} 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),
handle: WasiFile::new_host_file(cumulative_path),
},
})
};
Expand Down Expand Up @@ -1538,32 +1532,29 @@ pub fn path_open(
}
} else {
// 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 o_flags & __WASI_O_CREAT != 0 {
debug!(
"File {:?} may be created when opened if it does not exist",
&file_path
);
open_options.create(true)
open_options.write(true).create(true)
} else {
open_options
};
let open_options = if o_flags & __WASI_O_TRUNC != 0 {
debug!("File {:?} will be truncated when opened", &file_path);
open_options.truncate(true)
open_options.write(true).truncate(true)
} else {
open_options
};
debug!("Opening host file {:?}", &file_path);
let real_open_file =
wasi_try!(open_options.open(&file_path).map_err(|_| __WASI_EIO));

real_open_file
};
wasi_try!(open_options.open(&file_path).map_err(|_| __WASI_EIO));
}
Kind::File {
handle: WasiFile::HostFile(real_opened_file),
handle: WasiFile::new_host_file(file_path),
}
};

Expand Down