Fast-forward snapshot_0 to match wasi-common upstream

While we are waiting for the Rust toolchain to use the new ABI,
I thought it might be useful to sync `snapshot_0` with the latest
code in `wasi-common` "upstream". This mainly includes the latest
refactoring effort to unify the machinery for `fd_readdir` between
Linux, Windows and BSD.
This commit is contained in:
Jakub Konka
2019-11-27 23:42:29 +01:00
committed by Jakub Konka
parent 1f9d764d5d
commit d733ebf3ab
7 changed files with 283 additions and 287 deletions

View File

@@ -1,16 +1,15 @@
// Based on src/dir.rs from nix
#![allow(unused)] // temporarily, until BSD catches up with this change
use crate::old::snapshot_0::hostcalls_impl::FileType;
use libc;
use nix::{errno::Errno, Error, Result};
use nix::{Error, Result};
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
use std::{ffi, ptr};
#[cfg(target_os = "linux")]
use libc::{dirent64 as dirent, readdir64_r as readdir_r};
use libc::dirent64 as dirent;
#[cfg(not(target_os = "linux"))]
use libc::{dirent, readdir_r};
#[cfg(not(target_os = "linux",))]
use libc::dirent;
/// An open directory.
///
@@ -26,7 +25,7 @@ use libc::{dirent, readdir_r};
/// * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
/// does).
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(crate) struct Dir(ptr::NonNull<libc::DIR>);
pub(crate) struct Dir(pub(crate) ptr::NonNull<libc::DIR>);
impl Dir {
/// Converts from a descriptor-based object, closing the descriptor on success or failure.
@@ -90,53 +89,12 @@ impl Drop for Dir {
}
}
pub(crate) struct IntoIter(Dir);
impl Iterator for IntoIter {
type Item = Result<Entry>;
fn next(&mut self) -> Option<Self::Item> {
unsafe {
// Note: POSIX specifies that portable applications should dynamically allocate a
// buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
// for the NUL byte. It doesn't look like the std library does this; it just uses
// fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
// Probably fine here too then.
//
// See `impl Iterator for ReadDir` [1] for more details.
// [1] https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/fs.rs
let mut ent = std::mem::MaybeUninit::<dirent>::uninit();
let mut result = ptr::null_mut();
if let Err(e) = Errno::result(readdir_r(
(self.0).0.as_ptr(),
ent.as_mut_ptr(),
&mut result,
)) {
return Some(Err(e));
}
if result.is_null() {
None
} else {
assert_eq!(result, ent.as_mut_ptr(), "readdir_r specification violated");
Some(Ok(Entry(ent.assume_init())))
}
}
}
}
impl IntoIterator for Dir {
type IntoIter = IntoIter;
type Item = Result<Entry>;
fn into_iter(self) -> IntoIter {
IntoIter(self)
}
}
/// A directory entry, similar to `std::fs::DirEntry`.
///
/// Note that unlike the std version, this may represent the `.` or `..` entries.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub(crate) struct Entry(dirent);
pub(crate) struct Entry(pub(crate) dirent);
pub(crate) type Type = FileType;