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:
@@ -1,48 +1,57 @@
|
||||
use crate::sys::fdentry_impl;
|
||||
use crate::sys::fdentry_impl::{determine_type_and_access_rights, OsFile};
|
||||
use crate::{host, Error, Result};
|
||||
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, io};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Descriptor {
|
||||
File(fs::File),
|
||||
pub(crate) enum Descriptor {
|
||||
OsFile(OsFile),
|
||||
Stdin,
|
||||
Stdout,
|
||||
Stderr,
|
||||
}
|
||||
|
||||
impl Descriptor {
|
||||
pub fn as_file(&self) -> Result<&fs::File> {
|
||||
pub(crate) fn as_file(&self) -> Result<&OsFile> {
|
||||
match self {
|
||||
Descriptor::File(f) => Ok(f),
|
||||
Descriptor::OsFile(file) => Ok(file),
|
||||
_ => Err(Error::EBADF),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
pub(crate) fn as_file_mut(&mut self) -> Result<&mut OsFile> {
|
||||
match self {
|
||||
Descriptor::File(_) => true,
|
||||
Descriptor::OsFile(file) => Ok(file),
|
||||
_ => Err(Error::EBADF),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_file(&self) -> bool {
|
||||
match self {
|
||||
Descriptor::OsFile(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_stdin(&self) -> bool {
|
||||
#[allow(unused)]
|
||||
pub(crate) fn is_stdin(&self) -> bool {
|
||||
match self {
|
||||
Descriptor::Stdin => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_stdout(&self) -> bool {
|
||||
#[allow(unused)]
|
||||
pub(crate) fn is_stdout(&self) -> bool {
|
||||
match self {
|
||||
Descriptor::Stdout => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_stderr(&self) -> bool {
|
||||
#[allow(unused)]
|
||||
pub(crate) fn is_stderr(&self) -> bool {
|
||||
match self {
|
||||
Descriptor::Stderr => true,
|
||||
_ => false,
|
||||
@@ -51,19 +60,19 @@ impl Descriptor {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FdObject {
|
||||
pub file_type: host::__wasi_filetype_t,
|
||||
pub descriptor: ManuallyDrop<Descriptor>,
|
||||
pub needs_close: bool,
|
||||
pub(crate) struct FdObject {
|
||||
pub(crate) file_type: host::__wasi_filetype_t,
|
||||
pub(crate) descriptor: ManuallyDrop<Descriptor>,
|
||||
pub(crate) needs_close: bool,
|
||||
// TODO: directories
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FdEntry {
|
||||
pub fd_object: FdObject,
|
||||
pub rights_base: host::__wasi_rights_t,
|
||||
pub rights_inheriting: host::__wasi_rights_t,
|
||||
pub preopen_path: Option<PathBuf>,
|
||||
pub(crate) struct FdEntry {
|
||||
pub(crate) fd_object: FdObject,
|
||||
pub(crate) rights_base: host::__wasi_rights_t,
|
||||
pub(crate) rights_inheriting: host::__wasi_rights_t,
|
||||
pub(crate) preopen_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Drop for FdObject {
|
||||
@@ -75,12 +84,12 @@ impl Drop for FdObject {
|
||||
}
|
||||
|
||||
impl FdEntry {
|
||||
pub fn from(file: fs::File) -> Result<Self> {
|
||||
fdentry_impl::determine_type_and_access_rights(&file).map(
|
||||
pub(crate) fn from(file: fs::File) -> Result<Self> {
|
||||
determine_type_and_access_rights(&file).map(
|
||||
|(file_type, rights_base, rights_inheriting)| Self {
|
||||
fd_object: FdObject {
|
||||
file_type,
|
||||
descriptor: ManuallyDrop::new(Descriptor::File(file)),
|
||||
descriptor: ManuallyDrop::new(Descriptor::OsFile(OsFile::from(file))),
|
||||
needs_close: true,
|
||||
},
|
||||
rights_base,
|
||||
@@ -90,12 +99,12 @@ impl FdEntry {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn duplicate(file: &fs::File) -> Result<Self> {
|
||||
pub(crate) fn duplicate(file: &fs::File) -> Result<Self> {
|
||||
Self::from(file.try_clone()?)
|
||||
}
|
||||
|
||||
pub fn duplicate_stdin() -> Result<Self> {
|
||||
fdentry_impl::determine_type_and_access_rights(&io::stdin()).map(
|
||||
pub(crate) fn duplicate_stdin() -> Result<Self> {
|
||||
determine_type_and_access_rights(&io::stdin()).map(
|
||||
|(file_type, rights_base, rights_inheriting)| Self {
|
||||
fd_object: FdObject {
|
||||
file_type,
|
||||
@@ -109,8 +118,8 @@ impl FdEntry {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn duplicate_stdout() -> Result<Self> {
|
||||
fdentry_impl::determine_type_and_access_rights(&io::stdout()).map(
|
||||
pub(crate) fn duplicate_stdout() -> Result<Self> {
|
||||
determine_type_and_access_rights(&io::stdout()).map(
|
||||
|(file_type, rights_base, rights_inheriting)| Self {
|
||||
fd_object: FdObject {
|
||||
file_type,
|
||||
@@ -124,8 +133,8 @@ impl FdEntry {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn duplicate_stderr() -> Result<Self> {
|
||||
fdentry_impl::determine_type_and_access_rights(&io::stderr()).map(
|
||||
pub(crate) fn duplicate_stderr() -> Result<Self> {
|
||||
determine_type_and_access_rights(&io::stderr()).map(
|
||||
|(file_type, rights_base, rights_inheriting)| Self {
|
||||
fd_object: FdObject {
|
||||
file_type,
|
||||
|
||||
Reference in New Issue
Block a user