diff --git a/src/lib.rs b/src/lib.rs index ee46daf..a300a8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -541,28 +541,35 @@ mod tests { .collect::>>()? .len() ); - let mut options = OpenOptions::default(); - options.create_new(true).write(OpenOptionsWriteMode::Write); - options.open_at(&mut parent_dir, "1")?; - options.open_at(&mut parent_dir, "2")?; - options.mkdir_at(&mut parent_dir, "child")?; - options.open_at(&mut parent_dir, "child\\3")?; - let children = read_dir(&mut parent_dir)?.collect::>>()?; let dir_present = |children: &Vec, name: &OsStr| children.iter().any(|e| e.name() == name); - assert!(dir_present(&children, OsStr::new("1")), "{:?}", children); - assert!(dir_present(&children, OsStr::new("2")), "{:?}", children); - assert!( - dir_present(&children, OsStr::new("child")), - "{:?}", - children - ); - let mut child = OpenOptions::default() - .read(true) - .open_at(&mut parent_dir, "child")?; - let children = read_dir(&mut child)?.collect::>>()?; - assert_eq!(3, children.len()); - assert!(dir_present(&children, OsStr::new("3")), "{:?}", children); + { + let mut options = OpenOptions::default(); + options.create_new(true).write(OpenOptionsWriteMode::Write); + options.open_at(&mut parent_dir, "1")?; + options.open_at(&mut parent_dir, "2")?; + options.open_at(&mut options.mkdir_at(&mut parent_dir, "child")?, "3")?; + let children = read_dir(&mut parent_dir)?.collect::>>()?; + assert!(dir_present(&children, OsStr::new("1")), "{:?}", children); + assert!(dir_present(&children, OsStr::new("2")), "{:?}", children); + assert!( + dir_present(&children, OsStr::new("child")), + "{:?}", + children + ); + } + { + let mut child = OpenOptions::default() + .read(true) + .open_at(&mut parent_dir, "child")?; + // Something is permitting the fd for child to be dropped before the + // read_dir fcntl to duplicate the fd. Possibly the FD is writing + // over some other fd which is then separately dropped? + // eprintln!("More Magic"); + let children = read_dir(&mut child)?.collect::>>()?; + assert_eq!(3, children.len(), "{:?}", children); + assert!(dir_present(&children, OsStr::new("3")), "{:?}", children); + } Ok(()) } } diff --git a/src/unix.rs b/src/unix.rs index 500fdec..08a0181 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -195,7 +195,8 @@ impl<'a> ReadDirImpl<'a> { pub fn new(dir_file: &'a mut File) -> Result { // clone the FD - Nix takes ownership of the FD, but we're not // implementing TryInto here. - let new_fd = cvt_r(|| unsafe { libc::fcntl(dir_file.as_raw_fd(), libc::F_DUPFD_CLOEXEC) })?; + let new_fd = + cvt_r(|| unsafe { libc::fcntl(dir_file.as_raw_fd(), libc::F_DUPFD_CLOEXEC, 0) })?; Ok(ReadDirImpl { iter: Dir::from_fd(new_fd)?.into_iter(), _phantom: PhantomData, @@ -213,7 +214,7 @@ impl Iterator for ReadDirImpl<'_> { Some(Err(_e)) => Some(Err(std::io::Error::from_raw_os_error(errno::errno()))), Some(Ok(e)) => { let name = OsStr::from_bytes(e.file_name().to_bytes()).to_os_string(); - Some(Ok(DirEntryImpl { e, name })) + Some(Ok(DirEntryImpl { name })) } } } @@ -221,7 +222,6 @@ impl Iterator for ReadDirImpl<'_> { #[derive(Debug)] pub(crate) struct DirEntryImpl { - e: dir::Entry, name: OsString, }