diff --git a/lib/wasi-tests/build/wasitests.rs b/lib/wasi-tests/build/wasitests.rs index c305ee44e99..207f4e60f25 100644 --- a/lib/wasi-tests/build/wasitests.rs +++ b/lib/wasi-tests/build/wasitests.rs @@ -32,7 +32,6 @@ pub fn compile(file: &str, ignores: &HashSet) -> Option { }; Command::new("rustc") - .arg("+nightly") .arg(file) .arg("-o") .arg(&normalized_name) diff --git a/lib/wasi-tests/tests/wasitests/fseek.rs b/lib/wasi-tests/tests/wasitests/fseek.rs new file mode 100644 index 00000000000..3f1deb7c4ed --- /dev/null +++ b/lib/wasi-tests/tests/wasitests/fseek.rs @@ -0,0 +1,10 @@ +#[test] +fn test_fseek() { + assert_wasi_output!( + "../../wasitests/fseek.wasm", + "fseek", + vec![], + vec![], + "../../wasitests/fseek.out" + ); +} diff --git a/lib/wasi-tests/tests/wasitests/mod.rs b/lib/wasi-tests/tests/wasitests/mod.rs index 362573068f9..7331b309895 100644 --- a/lib/wasi-tests/tests/wasitests/mod.rs +++ b/lib/wasi-tests/tests/wasitests/mod.rs @@ -9,6 +9,7 @@ mod create_dir; mod envvar; mod file_metadata; mod fs_sandbox_test; +mod fseek; mod hello; mod mapdir; mod quine; diff --git a/lib/wasi-tests/wasitests/create_dir.wasm b/lib/wasi-tests/wasitests/create_dir.wasm index adfb1c2d323..107c7fd37e2 100755 Binary files a/lib/wasi-tests/wasitests/create_dir.wasm and b/lib/wasi-tests/wasitests/create_dir.wasm differ diff --git a/lib/wasi-tests/wasitests/envvar.wasm b/lib/wasi-tests/wasitests/envvar.wasm index 2fb521f3c70..41b18fe0aec 100755 Binary files a/lib/wasi-tests/wasitests/envvar.wasm and b/lib/wasi-tests/wasitests/envvar.wasm differ diff --git a/lib/wasi-tests/wasitests/file_metadata.wasm b/lib/wasi-tests/wasitests/file_metadata.wasm index a51bcdf7db6..daf95fbed16 100755 Binary files a/lib/wasi-tests/wasitests/file_metadata.wasm and b/lib/wasi-tests/wasitests/file_metadata.wasm differ diff --git a/lib/wasi-tests/wasitests/fs_sandbox_test.wasm b/lib/wasi-tests/wasitests/fs_sandbox_test.wasm index f41bc5a170a..175cea24341 100755 Binary files a/lib/wasi-tests/wasitests/fs_sandbox_test.wasm and b/lib/wasi-tests/wasitests/fs_sandbox_test.wasm differ diff --git a/lib/wasi-tests/wasitests/fseek.out b/lib/wasi-tests/wasitests/fseek.out new file mode 100644 index 00000000000..c9f09be6e17 --- /dev/null +++ b/lib/wasi-tests/wasitests/fseek.out @@ -0,0 +1,11 @@ +SCENE III. A room in Polonius' h +ouse. + + Enter LAERTES and OPH + And, sister, as the winds gi +r talk with the Lord Hamlet. + +uits, + Breathing like sanctif +is is for all: + I would not, diff --git a/lib/wasi-tests/wasitests/fseek.rs b/lib/wasi-tests/wasitests/fseek.rs new file mode 100644 index 00000000000..9b9e9f65e1c --- /dev/null +++ b/lib/wasi-tests/wasitests/fseek.rs @@ -0,0 +1,47 @@ +// Args: +// mapdir: .:wasitests/test_fs/hamlet + +use std::fs; +use std::io::{Read, Seek, SeekFrom}; +use std::path::PathBuf; + +fn main() { + #[cfg(not(target_os = "wasi"))] + let mut base = PathBuf::from("wasitests/test_fs/hamlet"); + #[cfg(target_os = "wasi")] + let mut base = PathBuf::from("."); + + base.push("act1/scene3.txt"); + + let mut file = fs::File::open(&base).expect("Could not open file"); + + let mut buffer = [0u8; 32]; + + assert_eq!(file.read(&mut buffer).unwrap(), 32); + let str_val = std::str::from_utf8(&buffer[..]).unwrap(); + println!("{}", str_val); + + assert_eq!(file.read(&mut buffer).unwrap(), 32); + let str_val = std::str::from_utf8(&buffer[..]).unwrap(); + println!("{}", str_val); + + assert_eq!(file.seek(SeekFrom::Start(123)).unwrap(), 123); + assert_eq!(file.read(&mut buffer).unwrap(), 32); + let str_val = std::str::from_utf8(&buffer[..]).unwrap(); + println!("{}", str_val); + + assert_eq!(file.seek(SeekFrom::End(-123)).unwrap(), 6617); + assert_eq!(file.read(&mut buffer).unwrap(), 32); + let str_val = std::str::from_utf8(&buffer[..]).unwrap(); + println!("{}", str_val); + + assert_eq!(file.seek(SeekFrom::Current(-250)).unwrap(), 6399); + assert_eq!(file.read(&mut buffer).unwrap(), 32); + let str_val = std::str::from_utf8(&buffer[..]).unwrap(); + println!("{}", str_val); + + assert_eq!(file.seek(SeekFrom::Current(50)).unwrap(), 6481); + assert_eq!(file.read(&mut buffer).unwrap(), 32); + let str_val = std::str::from_utf8(&buffer[..]).unwrap(); + println!("{}", str_val); +} diff --git a/lib/wasi-tests/wasitests/fseek.wasm b/lib/wasi-tests/wasitests/fseek.wasm new file mode 100755 index 00000000000..381f768e15a Binary files /dev/null and b/lib/wasi-tests/wasitests/fseek.wasm differ diff --git a/lib/wasi-tests/wasitests/hello.wasm b/lib/wasi-tests/wasitests/hello.wasm index 958d5e36da4..2703be2d1f9 100755 Binary files a/lib/wasi-tests/wasitests/hello.wasm and b/lib/wasi-tests/wasitests/hello.wasm differ diff --git a/lib/wasi-tests/wasitests/mapdir.rs b/lib/wasi-tests/wasitests/mapdir.rs index 915e0249c36..e8cb2d674b0 100644 --- a/lib/wasi-tests/wasitests/mapdir.rs +++ b/lib/wasi-tests/wasitests/mapdir.rs @@ -4,9 +4,9 @@ use std::fs; fn main() { - #[cfg(not(target = "wasi"))] + #[cfg(not(target_os = "wasi"))] let read_dir = fs::read_dir("wasitests/test_fs/hamlet").unwrap(); - #[cfg(target = "wasi")] + #[cfg(target_os = "wasi")] let read_dir = fs::read_dir(".").unwrap(); let mut out = vec![]; for entry in read_dir { diff --git a/lib/wasi-tests/wasitests/mapdir.wasm b/lib/wasi-tests/wasitests/mapdir.wasm index 32e34888c98..ff940d0e619 100755 Binary files a/lib/wasi-tests/wasitests/mapdir.wasm and b/lib/wasi-tests/wasitests/mapdir.wasm differ diff --git a/lib/wasi-tests/wasitests/quine.wasm b/lib/wasi-tests/wasitests/quine.wasm index 3b195bb0886..fa5e1427070 100755 Binary files a/lib/wasi-tests/wasitests/quine.wasm and b/lib/wasi-tests/wasitests/quine.wasm differ diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 45253262782..440103a99f8 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -903,7 +903,28 @@ pub fn fd_seek( // TODO: handle case if fd is a dir? match whence { __WASI_WHENCE_CUR => fd_entry.offset = (fd_entry.offset as i64 + offset) as u64, - __WASI_WHENCE_END => unimplemented!("__WASI__WHENCE_END in wasi::fd_seek"), + __WASI_WHENCE_END => { + use std::io::SeekFrom; + match state.fs.inodes[fd_entry.inode].kind { + Kind::File { ref mut handle } => { + let end = wasi_try!(handle.seek(SeekFrom::End(0)).ok().ok_or(__WASI_EIO)); + // TODO: handle case if fd_entry.offset uses 64 bits of a u64 + fd_entry.offset = (end as i64 + offset) as u64; + } + Kind::Symlink { .. } => { + unimplemented!("wasi::fd_seek not implemented for symlinks") + } + Kind::Dir { .. } => { + // TODO: check this + return __WASI_EINVAL; + } + Kind::Buffer { .. } => { + // seeking buffers probably makes sense + // TODO: implement this + return __WASI_EINVAL; + } + } + } __WASI_WHENCE_SET => fd_entry.offset = offset as u64, _ => return __WASI_EINVAL, } @@ -1235,6 +1256,7 @@ pub fn path_filestat_get( let last_segment = path_vec.last().unwrap(); cumulative_path.push(last_segment); + // read it from wasi FS cache first, otherwise check host system if entries.contains_key(last_segment) { state.fs.inodes[entries[last_segment]].stat } else { @@ -1244,7 +1266,25 @@ pub fn path_filestat_get( } let final_path_metadata = wasi_try!(cumulative_path.metadata().map_err(|_| __WASI_EIO)); - wasi_try!(get_stat_for_kind(&state.fs.inodes[inode].kind).ok_or(__WASI_EIO)) + let kind = if final_path_metadata.is_file() { + let file = + wasi_try!(std::fs::File::open(&cumulative_path).ok().ok_or(__WASI_EIO)); + Kind::File { + handle: WasiFile::HostFile(file), + } + } else if final_path_metadata.is_dir() { + Kind::Dir { + parent: Some(inode), + // TODO: verify that this doesn't cause issues with relative paths + path: cumulative_path.clone(), + entries: Default::default(), + } + } else { + // TODO: check this + return __WASI_EINVAL; + }; + + wasi_try!(get_stat_for_kind(&kind).ok_or(__WASI_EIO)) } } _ => {