diff --git a/crates/test-programs/build.rs b/crates/test-programs/build.rs index b460c46cca..e2ddc946a4 100644 --- a/crates/test-programs/build.rs +++ b/crates/test-programs/build.rs @@ -168,6 +168,7 @@ cfg_if::cfg_if! { "truncation_rights" => true, "poll_oneoff" => true, "path_link" => true, + "dangling_fd" => true, _ => false, } } else { diff --git a/crates/wasi-common/wasi-misc-tests/src/bin/dangling_fd.rs b/crates/wasi-common/wasi-misc-tests/src/bin/dangling_fd.rs new file mode 100644 index 0000000000..e9baf35d6d --- /dev/null +++ b/crates/wasi-common/wasi-misc-tests/src/bin/dangling_fd.rs @@ -0,0 +1,96 @@ +use more_asserts::assert_gt; +use std::{env, process}; +use wasi::wasi_unstable; +use wasi_misc_tests::open_scratch_directory; +use wasi_misc_tests::utils::{cleanup_dir, cleanup_file, create_dir, create_file}; +use wasi_misc_tests::wasi_wrappers::wasi_path_open; + +unsafe fn create_or_open( + dir_fd: wasi_unstable::Fd, + name: &str, + flags: wasi_unstable::OFlags, +) -> wasi_unstable::Fd { + let mut file_fd = wasi_unstable::Fd::max_value() - 1; + let mut status = wasi_path_open(dir_fd, 0, name, flags, 0, 0, 0, &mut file_fd); + assert_eq!( + status, + wasi_unstable::raw::__WASI_ESUCCESS, + "opening '{}'", + name + ); + assert_gt!( + file_fd, + libc::STDERR_FILENO as wasi_unstable::Fd, + "file descriptor range check", + ); + file_fd +} + +unsafe fn test_dangling_fd(dir_fd: wasi_unstable::Fd) { + // Create a file, open it, delete it without closing the handle, + // and then try creating it again + create_file(dir_fd, "file"); + let mut file_fd = wasi_unstable::Fd::max_value() - 1; + let mut status = wasi_path_open(dir_fd, 0, "file", 0, 0, 0, 0, &mut file_fd); + assert_eq!( + status, + wasi_unstable::raw::__WASI_ESUCCESS, + "opening a file", + ); + assert_gt!( + file_fd, + libc::STDERR_FILENO as wasi_unstable::Fd, + "file descriptor range check", + ); + cleanup_file(dir_fd, "file"); + create_file(dir_fd, "file"); + + // Now, repeat the same process but for a directory + create_dir(dir_fd, "subdir"); + let mut subdir_fd = wasi_unstable::Fd::max_value() - 1; + let mut status = wasi_path_open( + dir_fd, + 0, + "subdir", + wasi_unstable::O_DIRECTORY, + 0, + 0, + 0, + &mut subdir_fd, + ); + assert_eq!( + status, + wasi_unstable::raw::__WASI_ESUCCESS, + "opening a directory", + ); + assert_gt!( + file_fd, + libc::STDERR_FILENO as wasi_unstable::Fd, + "file descriptor range check", + ); + cleanup_dir(dir_fd, "subdir"); + create_dir(dir_fd, "subdir"); +} + +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_dangling_fd(dir_fd) } +}