summaryrefslogtreecommitdiffstats
path: root/vendor/rustix-0.37.6/src/backend/libc/fs/dir.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix-0.37.6/src/backend/libc/fs/dir.rs')
-rw-r--r--vendor/rustix-0.37.6/src/backend/libc/fs/dir.rs405
1 files changed, 0 insertions, 405 deletions
diff --git a/vendor/rustix-0.37.6/src/backend/libc/fs/dir.rs b/vendor/rustix-0.37.6/src/backend/libc/fs/dir.rs
deleted file mode 100644
index d1c901323..000000000
--- a/vendor/rustix-0.37.6/src/backend/libc/fs/dir.rs
+++ /dev/null
@@ -1,405 +0,0 @@
-use super::super::c;
-use super::super::conv::owned_fd;
-#[cfg(not(any(solarish, target_os = "haiku")))]
-use super::types::FileType;
-use crate::fd::{AsFd, BorrowedFd};
-use crate::ffi::CStr;
-#[cfg(target_os = "wasi")]
-use crate::ffi::CString;
-use crate::fs::{fcntl_getfl, fstat, openat, Mode, OFlags, Stat};
-#[cfg(not(any(
- solarish,
- target_os = "haiku",
- target_os = "netbsd",
- target_os = "redox",
- target_os = "wasi",
-)))]
-use crate::fs::{fstatfs, StatFs};
-#[cfg(not(any(solarish, target_os = "haiku", target_os = "redox", target_os = "wasi")))]
-use crate::fs::{fstatvfs, StatVfs};
-use crate::io;
-#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
-use crate::process::fchdir;
-#[cfg(target_os = "wasi")]
-use alloc::borrow::ToOwned;
-#[cfg(not(any(linux_like, target_os = "openbsd")))]
-use c::dirent as libc_dirent;
-#[cfg(not(linux_like))]
-use c::readdir as libc_readdir;
-#[cfg(linux_like)]
-use c::{dirent64 as libc_dirent, readdir64 as libc_readdir};
-use core::fmt;
-use core::mem::zeroed;
-use core::ptr::NonNull;
-use libc_errno::{errno, set_errno, Errno};
-
-/// `DIR*`
-#[repr(transparent)]
-pub struct Dir(NonNull<c::DIR>);
-
-impl Dir {
- /// Construct a `Dir` that reads entries from the given directory
- /// file descriptor.
- #[inline]
- pub fn read_from<Fd: AsFd>(fd: Fd) -> io::Result<Self> {
- Self::_read_from(fd.as_fd())
- }
-
- #[inline]
- fn _read_from(fd: BorrowedFd<'_>) -> io::Result<Self> {
- // Given an arbitrary `OwnedFd`, it's impossible to know whether the
- // user holds a `dup`'d copy which could continue to modify the
- // file description state, which would cause Undefined Behavior after
- // our call to `fdopendir`. To prevent this, we obtain an independent
- // `OwnedFd`.
- let flags = fcntl_getfl(fd)?;
- let fd_for_dir = openat(fd, cstr!("."), flags | OFlags::CLOEXEC, Mode::empty())?;
-
- let raw = owned_fd(fd_for_dir);
- unsafe {
- let libc_dir = c::fdopendir(raw);
-
- if let Some(libc_dir) = NonNull::new(libc_dir) {
- Ok(Self(libc_dir))
- } else {
- let err = io::Errno::last_os_error();
- let _ = c::close(raw);
- Err(err)
- }
- }
- }
-
- /// `rewinddir(self)`
- #[inline]
- pub fn rewind(&mut self) {
- unsafe { c::rewinddir(self.0.as_ptr()) }
- }
-
- /// `readdir(self)`, where `None` means the end of the directory.
- pub fn read(&mut self) -> Option<io::Result<DirEntry>> {
- set_errno(Errno(0));
- let dirent_ptr = unsafe { libc_readdir(self.0.as_ptr()) };
- if dirent_ptr.is_null() {
- let curr_errno = errno().0;
- if curr_errno == 0 {
- // We successfully reached the end of the stream.
- None
- } else {
- // `errno` is unknown or non-zero, so an error occurred.
- Some(Err(io::Errno(curr_errno)))
- }
- } else {
- // We successfully read an entry.
- unsafe {
- // We have our own copy of OpenBSD's dirent; check that the
- // layout minimally matches libc's.
- #[cfg(target_os = "openbsd")]
- check_dirent_layout(&*dirent_ptr);
-
- let result = DirEntry {
- dirent: read_dirent(&*dirent_ptr.cast()),
-
- #[cfg(target_os = "wasi")]
- name: CStr::from_ptr((*dirent_ptr).d_name.as_ptr()).to_owned(),
- };
-
- Some(Ok(result))
- }
- }
- }
-
- /// `fstat(self)`
- #[inline]
- pub fn stat(&self) -> io::Result<Stat> {
- fstat(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
- }
-
- /// `fstatfs(self)`
- #[cfg(not(any(
- solarish,
- target_os = "haiku",
- target_os = "netbsd",
- target_os = "redox",
- target_os = "wasi",
- )))]
- #[inline]
- pub fn statfs(&self) -> io::Result<StatFs> {
- fstatfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
- }
-
- /// `fstatvfs(self)`
- #[cfg(not(any(solarish, target_os = "haiku", target_os = "redox", target_os = "wasi")))]
- #[inline]
- pub fn statvfs(&self) -> io::Result<StatVfs> {
- fstatvfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
- }
-
- /// `fchdir(self)`
- #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
- #[inline]
- pub fn chdir(&self) -> io::Result<()> {
- fchdir(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
- }
-}
-
-// A `dirent` pointer returned from `readdir` may not point to a full `dirent`
-// struct, as the name is NUL-terminated and memory may not be allocated for
-// the full extent of the struct. Copy the fields one at a time.
-unsafe fn read_dirent(input: &libc_dirent) -> libc_dirent {
- #[cfg(not(any(solarish, target_os = "aix", target_os = "haiku")))]
- let d_type = input.d_type;
-
- #[cfg(not(any(
- apple,
- freebsdlike,
- target_os = "aix",
- target_os = "haiku",
- target_os = "netbsd",
- target_os = "wasi",
- )))]
- let d_off = input.d_off;
-
- #[cfg(target_os = "aix")]
- let d_offset = input.d_offset;
-
- #[cfg(not(any(freebsdlike, netbsdlike)))]
- let d_ino = input.d_ino;
-
- #[cfg(any(freebsdlike, netbsdlike))]
- let d_fileno = input.d_fileno;
-
- #[cfg(not(any(target_os = "dragonfly", target_os = "wasi")))]
- let d_reclen = input.d_reclen;
-
- #[cfg(any(bsd, target_os = "aix"))]
- let d_namlen = input.d_namlen;
-
- #[cfg(apple)]
- let d_seekoff = input.d_seekoff;
-
- #[cfg(target_os = "haiku")]
- let d_dev = input.d_dev;
- #[cfg(target_os = "haiku")]
- let d_pdev = input.d_pdev;
- #[cfg(target_os = "haiku")]
- let d_pino = input.d_pino;
-
- // Construct the input. Rust will give us an error if any OS has a input
- // with a field that we missed here. And we can avoid blindly copying the
- // whole `d_name` field, which may not be entirely allocated.
- #[cfg_attr(target_os = "wasi", allow(unused_mut))]
- #[cfg(not(freebsdlike))]
- let mut dirent = libc_dirent {
- #[cfg(not(any(solarish, target_os = "aix", target_os = "haiku")))]
- d_type,
- #[cfg(not(any(
- apple,
- target_os = "aix",
- target_os = "freebsd", // Until FreeBSD 12
- target_os = "haiku",
- target_os = "netbsd",
- target_os = "wasi",
- )))]
- d_off,
- #[cfg(target_os = "aix")]
- d_offset,
- #[cfg(not(any(netbsdlike, target_os = "freebsd")))]
- d_ino,
- #[cfg(any(netbsdlike, target_os = "freebsd"))]
- d_fileno,
- #[cfg(not(target_os = "wasi"))]
- d_reclen,
- #[cfg(any(apple, netbsdlike, target_os = "aix", target_os = "freebsd"))]
- d_namlen,
- #[cfg(apple)]
- d_seekoff,
- // The `d_name` field is NUL-terminated, and we need to be careful not
- // to read bytes past the NUL, even though they're within the nominal
- // extent of the `struct dirent`, because they may not be allocated. So
- // don't read it from `dirent_ptr`.
- //
- // In theory this could use `MaybeUninit::uninit().assume_init()`, but
- // that [invokes undefined behavior].
- //
- // [invokes undefined behavior]: https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#initialization-invariant
- d_name: zeroed(),
- #[cfg(target_os = "openbsd")]
- __d_padding: zeroed(),
- #[cfg(target_os = "haiku")]
- d_dev,
- #[cfg(target_os = "haiku")]
- d_pdev,
- #[cfg(target_os = "haiku")]
- d_pino,
- };
- /*
- pub d_ino: ino_t,
- pub d_pino: i64,
- pub d_reclen: ::c_ushort,
- pub d_name: [::c_char; 1024], // Max length is _POSIX_PATH_MAX
- */
-
- // On dragonfly and FreeBSD 12, `dirent` has some non-public padding fields
- // so we can't directly initialize it.
- #[cfg(freebsdlike)]
- let mut dirent = {
- let mut dirent: libc_dirent = zeroed();
- dirent.d_fileno = d_fileno;
- dirent.d_namlen = d_namlen;
- dirent.d_type = d_type;
- #[cfg(target_os = "freebsd")]
- {
- dirent.d_reclen = d_reclen;
- }
- dirent
- };
-
- // Copy from d_name, reading up to and including the first NUL.
- #[cfg(not(target_os = "wasi"))]
- {
- let name_len = CStr::from_ptr(input.d_name.as_ptr())
- .to_bytes_with_nul()
- .len();
- dirent.d_name[..name_len].copy_from_slice(&input.d_name[..name_len]);
- }
-
- dirent
-}
-
-/// `Dir` implements `Send` but not `Sync`, because we use `readdir` which is
-/// not guaranteed to be thread-safe. Users can wrap this in a `Mutex` if they
-/// need `Sync`, which is effectively what'd need to do to implement `Sync`
-/// ourselves.
-unsafe impl Send for Dir {}
-
-impl Drop for Dir {
- #[inline]
- fn drop(&mut self) {
- unsafe { c::closedir(self.0.as_ptr()) };
- }
-}
-
-impl Iterator for Dir {
- type Item = io::Result<DirEntry>;
-
- #[inline]
- fn next(&mut self) -> Option<Self::Item> {
- Self::read(self)
- }
-}
-
-impl fmt::Debug for Dir {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Dir")
- .field("fd", unsafe { &c::dirfd(self.0.as_ptr()) })
- .finish()
- }
-}
-
-/// `struct dirent`
-#[derive(Debug)]
-pub struct DirEntry {
- dirent: libc_dirent,
-
- #[cfg(target_os = "wasi")]
- name: CString,
-}
-
-impl DirEntry {
- /// Returns the file name of this directory entry.
- #[inline]
- pub fn file_name(&self) -> &CStr {
- #[cfg(not(target_os = "wasi"))]
- unsafe {
- CStr::from_ptr(self.dirent.d_name.as_ptr())
- }
-
- #[cfg(target_os = "wasi")]
- &self.name
- }
-
- /// Returns the type of this directory entry.
- #[cfg(not(any(solarish, target_os = "aix", target_os = "haiku")))]
- #[inline]
- pub fn file_type(&self) -> FileType {
- FileType::from_dirent_d_type(self.dirent.d_type)
- }
-
- /// Return the inode number of this directory entry.
- #[cfg(not(any(freebsdlike, netbsdlike)))]
- #[inline]
- pub fn ino(&self) -> u64 {
- self.dirent.d_ino as u64
- }
-
- /// Return the inode number of this directory entry.
- #[cfg(any(freebsdlike, netbsdlike))]
- #[inline]
- pub fn ino(&self) -> u64 {
- #[allow(clippy::useless_conversion)]
- self.dirent.d_fileno.into()
- }
-}
-
-/// libc's OpenBSD `dirent` has a private field so we can't construct it
-/// directly, so we declare it ourselves to make all fields accessible.
-#[cfg(target_os = "openbsd")]
-#[repr(C)]
-#[derive(Debug)]
-struct libc_dirent {
- d_fileno: c::ino_t,
- d_off: c::off_t,
- d_reclen: u16,
- d_type: u8,
- d_namlen: u8,
- __d_padding: [u8; 4],
- d_name: [c::c_char; 256],
-}
-
-/// We have our own copy of OpenBSD's dirent; check that the layout
-/// minimally matches libc's.
-#[cfg(target_os = "openbsd")]
-fn check_dirent_layout(dirent: &c::dirent) {
- use crate::utils::as_ptr;
- use core::mem::{align_of, size_of};
-
- // Check that the basic layouts match.
- assert_eq!(size_of::<libc_dirent>(), size_of::<c::dirent>());
- assert_eq!(align_of::<libc_dirent>(), align_of::<c::dirent>());
-
- // Check that the field offsets match.
- assert_eq!(
- {
- let z = libc_dirent {
- d_fileno: 0_u64,
- d_off: 0_i64,
- d_reclen: 0_u16,
- d_type: 0_u8,
- d_namlen: 0_u8,
- __d_padding: [0_u8; 4],
- d_name: [0 as c::c_char; 256],
- };
- let base = as_ptr(&z) as usize;
- (
- (as_ptr(&z.d_fileno) as usize) - base,
- (as_ptr(&z.d_off) as usize) - base,
- (as_ptr(&z.d_reclen) as usize) - base,
- (as_ptr(&z.d_type) as usize) - base,
- (as_ptr(&z.d_namlen) as usize) - base,
- (as_ptr(&z.d_name) as usize) - base,
- )
- },
- {
- let z = dirent;
- let base = as_ptr(z) as usize;
- (
- (as_ptr(&z.d_fileno) as usize) - base,
- (as_ptr(&z.d_off) as usize) - base,
- (as_ptr(&z.d_reclen) as usize) - base,
- (as_ptr(&z.d_type) as usize) - base,
- (as_ptr(&z.d_namlen) as usize) - base,
- (as_ptr(&z.d_name) as usize) - base,
- )
- }
- );
-}