From cad15a7076d493a0651fb0b7889bd5e5a72a8f17 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 12 Oct 2023 10:19:59 -0700 Subject: [PATCH] Fixes for `Dir` on macOS, FreeBSD, and WASI. --- src/backend/libc/fs/dir.rs | 9 +++++++++ tests/fs/dir.rs | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/src/backend/libc/fs/dir.rs b/src/backend/libc/fs/dir.rs index 77cad0123..c5cb2c485 100644 --- a/src/backend/libc/fs/dir.rs +++ b/src/backend/libc/fs/dir.rs @@ -46,6 +46,7 @@ impl Dir { } #[inline] + #[allow(unused_mut)] fn _read_from(fd: BorrowedFd<'_>) -> io::Result { let mut any_errors = false; @@ -57,6 +58,7 @@ impl Dir { let flags = fcntl_getfl(fd)?; let fd_for_dir = match openat(fd, cstr!("."), flags | OFlags::CLOEXEC, Mode::empty()) { Ok(fd) => fd, + #[cfg(not(target_os = "wasi"))] Err(io::Errno::NOENT) => { // If "." doesn't exist, it means the directory was removed. // We treat that as iterating through a directory with no @@ -341,6 +343,13 @@ fn dir_iterator_handles_io_errors() { core::mem::forget(owned_fd); } + // FreeBSD and macOS seem to read some directory entries before we call + // `.next()`. + #[cfg(any(apple, freebsdlike))] + { + dir.rewind(); + } + assert!(matches!(dir.next(), Some(Err(_)))); assert!(matches!(dir.next(), None)); } diff --git a/tests/fs/dir.rs b/tests/fs/dir.rs index 06d243ae7..d71b8b628 100644 --- a/tests/fs/dir.rs +++ b/tests/fs/dir.rs @@ -62,6 +62,10 @@ fn test_dir() { assert!(saw_cargo_toml); } +// Test that `Dir` silently stops iterating if the directory has been removed. +// +// Except on FreeBSD and macOS, where apparently `readdir` just keeps reading. +#[cfg_attr(any(apple, freebsdlike), ignore)] #[test] fn dir_iterator_handles_dir_removal() { // create a dir, keep the FD, then delete the dir @@ -83,6 +87,7 @@ fn dir_iterator_handles_dir_removal() { // Like `dir_iterator_handles_dir_removal`, but close the directory after // `Dir::read_from`. +#[cfg_attr(any(apple, freebsdlike), ignore)] #[test] fn dir_iterator_handles_dir_removal_after_open() { // create a dir, keep the FD, then delete the dir