Fix fd_readdir on BSD-style nixes (#81)

* Fix fd_readdir on BSD-style nixes

The fix was tested on Darwin-XNU and FreeBSD. The change introduces
thread-safe cache of (RawFd, *mut libc::DIR) pairs so that
libc::fdopendir syscall is called only once when invoking fd_readdir
for the first time, and then the pointer to the directory stream,
*mut libc::DIR, is reused until the matching raw file descriptor
is closed.

This fix allows then correct use (and matching to the implementation
on Linux kernels) of libc::seekdir and libc::rewinddir to seek through
and rewind the existing directory stream, *mut libc::DIR, which
otherwise seems to be reset/invalidated every time libc::fdopendir
is called (unlike on Linux, where this behaviour is not observed).

* Store dir stream as part of the FdEntry's Descriptor

* Move bsd specifics into separate module

* Add todo comments and fix formatting

* Refactor int conversions

* Emphasise in debug logs that we're looking at fd_readdir entry

* Change visibility of FdEntry and related to public-private

* Rewrite creating DirStream for the first time
This commit is contained in:
Jakub Konka
2019-09-14 21:01:39 +02:00
committed by GitHub
parent 500e32a3b2
commit c98b3d10ec
15 changed files with 484 additions and 219 deletions

View File

@@ -2,12 +2,42 @@ use crate::fdentry::Descriptor;
use crate::{host, Error, Result};
use std::fs::File;
use std::io;
use std::ops::{Deref, DerefMut};
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, RawHandle};
#[derive(Debug)]
pub(crate) struct OsFile(File);
impl From<File> for OsFile {
fn from(file: File) -> Self {
Self(file)
}
}
impl AsRawHandle for OsFile {
fn as_raw_handle(&self) -> RawHandle {
self.0.as_raw_handle()
}
}
impl Deref for OsFile {
type Target = File;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for OsFile {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl AsRawHandle for Descriptor {
fn as_raw_handle(&self) -> RawHandle {
match self {
Descriptor::File(f) => f.as_raw_handle(),
Descriptor::OsFile(file) => file.as_raw_handle(),
Descriptor::Stdin => io::stdin().as_raw_handle(),
Descriptor::Stdout => io::stdout().as_raw_handle(),
Descriptor::Stderr => io::stderr().as_raw_handle(),