diff --git a/crates/test-programs/README.md b/crates/test-programs/README.md index 662216f426..31f3c1bfad 100644 --- a/crates/test-programs/README.md +++ b/crates/test-programs/README.md @@ -1,2 +1,7 @@ This is the `test-programs` crate, which builds and runs whole programs compiled to wasm32-wasi. + +To actually run these tests, the test-programs feature must be enabled, e.g.: +``` +cargo test --features test-programs/test_programs --package test-programs +``` diff --git a/crates/test-programs/wasi-tests/src/bin/path_open_missing.rs b/crates/test-programs/wasi-tests/src/bin/path_open_missing.rs new file mode 100644 index 0000000000..410b602c45 --- /dev/null +++ b/crates/test-programs/wasi-tests/src/bin/path_open_missing.rs @@ -0,0 +1,43 @@ +use std::{env, process}; +use wasi_tests::{open_scratch_directory}; + +unsafe fn test_path_open_missing(dir_fd: wasi::Fd) { + assert_eq!( + wasi::path_open( + dir_fd, + 0, + "file", + 0, // not passing O_CREAT here + 0, + 0, + 0, + ) + .expect_err("trying to open a file that doesn't exist") + .raw_error(), + wasi::ERRNO_NOENT, + "errno should be ERRNO_NOENT" + ); +} + +fn main() { + let mut args = env::args(); + let prog = args.next().unwrap(); + let arg = if let Some(arg) = args.next() { + arg + } else { + eprintln!("usage: {} ", prog); + process::exit(1); + }; + + // Open scratch directory + let dir_fd = match open_scratch_directory(&arg) { + Ok(dir_fd) => dir_fd, + Err(err) => { + eprintln!("{}", err); + process::exit(1) + } + }; + + // Run the tests. + unsafe { test_path_open_missing(dir_fd) } +} diff --git a/crates/wasi-common/src/virtfs.rs b/crates/wasi-common/src/virtfs.rs index 0023825208..8eba9808e6 100644 --- a/crates/wasi-common/src/virtfs.rs +++ b/crates/wasi-common/src/virtfs.rs @@ -661,23 +661,30 @@ impl Handle for VirtualDir { e.get().try_clone().map_err(Into::into) } Entry::Vacant(v) => { - if self.writable { - // Enforce a hard limit at `u32::MAX - 2` files. - // This is to have a constant limit (rather than target-dependent limit we - // would have with `usize`. The limit is the full `u32` range minus two so we - // can reserve "self" and "parent" cookie values. - if entry_count >= (std::u32::MAX - RESERVED_ENTRY_COUNT) as usize { - return Err(Error::Nospc); + if oflags.contains(&Oflags::CREAT) { + if self.writable { + // Enforce a hard limit at `u32::MAX - 2` files. + // This is to have a constant limit (rather than target-dependent limit we + // would have with `usize`. The limit is the full `u32` range minus two so we + // can reserve "self" and "parent" cookie values. + if entry_count >= (std::u32::MAX - RESERVED_ENTRY_COUNT) as usize { + return Err(Error::Nospc); + } + + tracing::trace!( + "VirtualDir::openat creating an InMemoryFile named {}", + path + ); + + let file = Box::new(InMemoryFile::memory_backed()); + file.fd_flags.set(fd_flags); + file.set_parent(Some(self.try_clone().expect("can clone self"))); + v.insert(file).try_clone().map_err(Into::into) + } else { + Err(Error::Acces) } - - tracing::trace!("VirtualDir::openat creating an InMemoryFile named {}", path); - - let file = Box::new(InMemoryFile::memory_backed()); - file.fd_flags.set(fd_flags); - file.set_parent(Some(self.try_clone().expect("can clone self"))); - v.insert(file).try_clone().map_err(Into::into) } else { - Err(Error::Acces) + Err(Error::Noent) } } }