diff options
Diffstat (limited to 'vendor/rustix/src/backend/libc/fs')
-rw-r--r-- | vendor/rustix/src/backend/libc/fs/dir.rs | 423 | ||||
-rw-r--r-- | vendor/rustix/src/backend/libc/fs/inotify.rs | 131 | ||||
-rw-r--r-- | vendor/rustix/src/backend/libc/fs/makedev.rs | 138 | ||||
-rw-r--r-- | vendor/rustix/src/backend/libc/fs/mod.rs | 23 | ||||
-rw-r--r-- | vendor/rustix/src/backend/libc/fs/syscalls.rs | 2514 | ||||
-rw-r--r-- | vendor/rustix/src/backend/libc/fs/types.rs | 1164 |
6 files changed, 0 insertions, 4393 deletions
diff --git a/vendor/rustix/src/backend/libc/fs/dir.rs b/vendor/rustix/src/backend/libc/fs/dir.rs deleted file mode 100644 index 82a0a90..0000000 --- a/vendor/rustix/src/backend/libc/fs/dir.rs +++ /dev/null @@ -1,423 +0,0 @@ -#[cfg(not(any(solarish, target_os = "haiku", target_os = "nto", target_os = "vita")))] -use super::types::FileType; -use crate::backend::c; -use crate::backend::conv::owned_fd; -use crate::fd::{AsFd, BorrowedFd, OwnedFd}; -use crate::ffi::{CStr, CString}; -use crate::fs::{fcntl_getfl, openat, Mode, OFlags}; -#[cfg(not(target_os = "vita"))] -use crate::fs::{fstat, Stat}; -#[cfg(not(any( - solarish, - target_os = "haiku", - target_os = "netbsd", - target_os = "nto", - target_os = "redox", - target_os = "vita", - target_os = "wasi", -)))] -use crate::fs::{fstatfs, StatFs}; -#[cfg(not(any( - solarish, - target_os = "haiku", - target_os = "redox", - target_os = "vita", - target_os = "wasi" -)))] -use crate::fs::{fstatvfs, StatVfs}; -use crate::io; -#[cfg(not(any(target_os = "fuchsia", target_os = "vita", target_os = "wasi")))] -#[cfg(feature = "process")] -use crate::process::fchdir; -use alloc::borrow::ToOwned; -#[cfg(not(any(linux_like, target_os = "hurd")))] -use c::readdir as libc_readdir; -#[cfg(any(linux_like, target_os = "hurd"))] -use c::readdir64 as libc_readdir; -use core::fmt; -use core::ptr::NonNull; -use libc_errno::{errno, set_errno, Errno}; - -/// `DIR*` -pub struct Dir { - /// The `libc` `DIR` pointer. - libc_dir: NonNull<c::DIR>, - - /// Have we seen any errors in this iteration? - any_errors: bool, -} - -impl Dir { - /// Take ownership of `fd` and construct a `Dir` that reads entries from - /// the given directory file descriptor. - #[inline] - pub fn new<Fd: Into<OwnedFd>>(fd: Fd) -> io::Result<Self> { - Self::_new(fd.into()) - } - - #[inline] - fn _new(fd: OwnedFd) -> io::Result<Self> { - let raw = owned_fd(fd); - unsafe { - let libc_dir = c::fdopendir(raw); - - if let Some(libc_dir) = NonNull::new(libc_dir) { - Ok(Self { - libc_dir, - any_errors: false, - }) - } else { - let err = io::Errno::last_os_error(); - let _ = c::close(raw); - Err(err) - } - } - } - - /// Borrow `fd` and 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] - #[allow(unused_mut)] - fn _read_from(fd: BorrowedFd<'_>) -> io::Result<Self> { - let mut any_errors = false; - - // 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 = match openat(fd, cstr!("."), flags | OFlags::CLOEXEC, Mode::empty()) { - Ok(fd) => fd, - #[cfg(not(target_os = "wasi"))] - Err(io::Errno::NOENT) => { - // If "." doesn't exist, it means the directory was removed. - // We treat that as iterating through a directory with no - // entries. - any_errors = true; - crate::io::dup(fd)? - } - Err(err) => return Err(err), - }; - - 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, - any_errors, - }) - } else { - let err = io::Errno::last_os_error(); - let _ = c::close(raw); - Err(err) - } - } - } - - /// `rewinddir(self)` - #[inline] - pub fn rewind(&mut self) { - self.any_errors = false; - unsafe { c::rewinddir(self.libc_dir.as_ptr()) } - } - - /// `readdir(self)`, where `None` means the end of the directory. - pub fn read(&mut self) -> Option<io::Result<DirEntry>> { - // If we've seen errors, don't continue to try to read anyting further. - if self.any_errors { - return None; - } - - set_errno(Errno(0)); - let dirent_ptr = unsafe { libc_readdir(self.libc_dir.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. - self.any_errors = true; - Some(Err(io::Errno(curr_errno))) - } - } else { - // We successfully read an entry. - unsafe { - let dirent = &*dirent_ptr; - - // 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); - - let result = DirEntry { - #[cfg(not(any( - solarish, - target_os = "aix", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - )))] - d_type: dirent.d_type, - - #[cfg(not(any(freebsdlike, netbsdlike, target_os = "vita")))] - d_ino: dirent.d_ino, - - #[cfg(any(freebsdlike, netbsdlike))] - d_fileno: dirent.d_fileno, - - name: CStr::from_ptr(dirent.d_name.as_ptr()).to_owned(), - }; - - Some(Ok(result)) - } - } - } - - /// `fstat(self)` - #[cfg(not(target_os = "vita"))] - #[inline] - pub fn stat(&self) -> io::Result<Stat> { - fstat(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.libc_dir.as_ptr())) }) - } - - /// `fstatfs(self)` - #[cfg(not(any( - solarish, - target_os = "haiku", - target_os = "netbsd", - target_os = "nto", - target_os = "redox", - target_os = "vita", - target_os = "wasi", - )))] - #[inline] - pub fn statfs(&self) -> io::Result<StatFs> { - fstatfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.libc_dir.as_ptr())) }) - } - - /// `fstatvfs(self)` - #[cfg(not(any( - solarish, - target_os = "haiku", - target_os = "redox", - target_os = "vita", - target_os = "wasi" - )))] - #[inline] - pub fn statvfs(&self) -> io::Result<StatVfs> { - fstatvfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.libc_dir.as_ptr())) }) - } - - /// `fchdir(self)` - #[cfg(feature = "process")] - #[cfg(not(any(target_os = "fuchsia", target_os = "vita", target_os = "wasi")))] - #[cfg_attr(doc_cfg, doc(cfg(feature = "process")))] - #[inline] - pub fn chdir(&self) -> io::Result<()> { - fchdir(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.libc_dir.as_ptr())) }) - } -} - -/// `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.libc_dir.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 { - let mut s = f.debug_struct("Dir"); - #[cfg(not(target_os = "vita"))] - s.field("fd", unsafe { &c::dirfd(self.libc_dir.as_ptr()) }); - s.finish() - } -} - -/// `struct dirent` -#[derive(Debug)] -pub struct DirEntry { - #[cfg(not(any( - solarish, - target_os = "aix", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - )))] - d_type: u8, - - #[cfg(not(any(freebsdlike, netbsdlike, target_os = "vita")))] - d_ino: c::ino_t, - - #[cfg(any(freebsdlike, netbsdlike))] - d_fileno: c::ino_t, - - name: CString, -} - -impl DirEntry { - /// Returns the file name of this directory entry. - #[inline] - pub fn file_name(&self) -> &CStr { - &self.name - } - - /// Returns the type of this directory entry. - #[cfg(not(any( - solarish, - target_os = "aix", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - )))] - #[inline] - pub fn file_type(&self) -> FileType { - FileType::from_dirent_d_type(self.d_type) - } - - /// Return the inode number of this directory entry. - #[cfg(not(any(freebsdlike, netbsdlike, target_os = "vita")))] - #[inline] - pub fn ino(&self) -> u64 { - self.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.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; - - // Check that the basic layouts match. - #[cfg(test)] - { - assert_eq_size!(libc_dirent, c::dirent); - assert_eq_size!(libc_dirent, 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, - ) - } - ); -} - -#[test] -fn dir_iterator_handles_io_errors() { - // create a dir, keep the FD, then delete the dir - let tmp = tempfile::tempdir().unwrap(); - let fd = crate::fs::openat( - crate::fs::CWD, - tmp.path(), - crate::fs::OFlags::RDONLY | crate::fs::OFlags::CLOEXEC, - crate::fs::Mode::empty(), - ) - .unwrap(); - - let file_fd = crate::fs::openat( - &fd, - tmp.path().join("test.txt"), - crate::fs::OFlags::WRONLY | crate::fs::OFlags::CREATE, - crate::fs::Mode::RWXU, - ) - .unwrap(); - - let mut dir = Dir::read_from(&fd).unwrap(); - - // Reach inside the `Dir` and replace its directory with a file, which - // will cause the subsequent `readdir` to fail. - unsafe { - let raw_fd = c::dirfd(dir.libc_dir.as_ptr()); - let mut owned_fd: crate::fd::OwnedFd = crate::fd::FromRawFd::from_raw_fd(raw_fd); - crate::io::dup2(&file_fd, &mut owned_fd).unwrap(); - core::mem::forget(owned_fd); - } - - // FreeBSD and macOS seem to read some directory entries before we call - // `.next()`. - #[cfg(any(apple, freebsdlike))] - { - dir.rewind(); - } - - assert!(matches!(dir.next(), Some(Err(_)))); - assert!(dir.next().is_none()); -} diff --git a/vendor/rustix/src/backend/libc/fs/inotify.rs b/vendor/rustix/src/backend/libc/fs/inotify.rs deleted file mode 100644 index 2044bd9..0000000 --- a/vendor/rustix/src/backend/libc/fs/inotify.rs +++ /dev/null @@ -1,131 +0,0 @@ -//! inotify support for working with inotifies - -use crate::backend::c; -use crate::backend::conv::{borrowed_fd, c_str, ret, ret_c_int, ret_owned_fd}; -use crate::fd::{BorrowedFd, OwnedFd}; -use crate::io; -use bitflags::bitflags; - -bitflags! { - /// `IN_*` for use with [`inotify_init`]. - /// - /// [`inotify_init`]: crate::fs::inotify::inotify_init - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct CreateFlags: u32 { - /// `IN_CLOEXEC` - const CLOEXEC = bitcast!(c::IN_CLOEXEC); - /// `IN_NONBLOCK` - const NONBLOCK = bitcast!(c::IN_NONBLOCK); - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -bitflags! { - /// `IN*` for use with [`inotify_add_watch`]. - /// - /// [`inotify_add_watch`]: crate::fs::inotify::inotify_add_watch - #[repr(transparent)] - #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct WatchFlags: u32 { - /// `IN_ACCESS` - const ACCESS = c::IN_ACCESS; - /// `IN_ATTRIB` - const ATTRIB = c::IN_ATTRIB; - /// `IN_CLOSE_NOWRITE` - const CLOSE_NOWRITE = c::IN_CLOSE_NOWRITE; - /// `IN_CLOSE_WRITE` - const CLOSE_WRITE = c::IN_CLOSE_WRITE; - /// `IN_CREATE` - const CREATE = c::IN_CREATE; - /// `IN_DELETE` - const DELETE = c::IN_DELETE; - /// `IN_DELETE_SELF` - const DELETE_SELF = c::IN_DELETE_SELF; - /// `IN_MODIFY` - const MODIFY = c::IN_MODIFY; - /// `IN_MOVE_SELF` - const MOVE_SELF = c::IN_MOVE_SELF; - /// `IN_MOVED_FROM` - const MOVED_FROM = c::IN_MOVED_FROM; - /// `IN_MOVED_TO` - const MOVED_TO = c::IN_MOVED_TO; - /// `IN_OPEN` - const OPEN = c::IN_OPEN; - - /// `IN_CLOSE` - const CLOSE = c::IN_CLOSE; - /// `IN_MOVE` - const MOVE = c::IN_MOVE; - /// `IN_ALL_EVENTS` - const ALL_EVENTS = c::IN_ALL_EVENTS; - - /// `IN_DONT_FOLLOW` - const DONT_FOLLOW = c::IN_DONT_FOLLOW; - /// `IN_EXCL_UNLINK` - const EXCL_UNLINK = 1; - /// `IN_MASK_ADD` - const MASK_ADD = 1; - /// `IN_MASK_CREATE` - const MASK_CREATE = 1; - /// `IN_ONESHOT` - const ONESHOT = c::IN_ONESHOT; - /// `IN_ONLYDIR` - const ONLYDIR = c::IN_ONLYDIR; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -/// `inotify_init1(flags)`—Creates a new inotify object. -/// -/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file -/// descriptor from being implicitly passed across `exec` boundaries. -#[doc(alias = "inotify_init1")] -pub fn inotify_init(flags: CreateFlags) -> io::Result<OwnedFd> { - // SAFETY: `inotify_init1` has no safety preconditions. - unsafe { ret_owned_fd(c::inotify_init1(bitflags_bits!(flags))) } -} - -/// `inotify_add_watch(self, path, flags)`—Adds a watch to inotify. -/// -/// This registers or updates a watch for the filesystem path `path` and -/// returns a watch descriptor corresponding to this watch. -/// -/// Note: Due to the existence of hardlinks, providing two different paths to -/// this method may result in it returning the same watch descriptor. An -/// application should keep track of this externally to avoid logic errors. -pub fn inotify_add_watch<P: crate::path::Arg>( - inot: BorrowedFd<'_>, - path: P, - flags: WatchFlags, -) -> io::Result<i32> { - path.into_with_c_str(|path| { - // SAFETY: The fd and path we are passing is guaranteed valid by the - // type system. - unsafe { - ret_c_int(c::inotify_add_watch( - borrowed_fd(inot), - c_str(path), - flags.bits(), - )) - } - }) -} - -/// `inotify_rm_watch(self, wd)`—Removes a watch from this inotify. -/// -/// The watch descriptor provided should have previously been returned by -/// [`inotify_add_watch`] and not previously have been removed. -#[doc(alias = "inotify_rm_watch")] -pub fn inotify_remove_watch(inot: BorrowedFd<'_>, wd: i32) -> io::Result<()> { - // Android's `inotify_rm_watch` takes `u32` despite that - // `inotify_add_watch` expects a `i32`. - #[cfg(target_os = "android")] - let wd = wd as u32; - // SAFETY: The fd is valid and closing an arbitrary wd is valid. - unsafe { ret(c::inotify_rm_watch(borrowed_fd(inot), wd)) } -} diff --git a/vendor/rustix/src/backend/libc/fs/makedev.rs b/vendor/rustix/src/backend/libc/fs/makedev.rs deleted file mode 100644 index aa12102..0000000 --- a/vendor/rustix/src/backend/libc/fs/makedev.rs +++ /dev/null @@ -1,138 +0,0 @@ -#[cfg(not(all(target_os = "android", target_pointer_width = "32")))] -use crate::backend::c; -use crate::fs::Dev; - -#[cfg(not(any( - apple, - solarish, - target_os = "aix", - target_os = "android", - target_os = "emscripten", -)))] -#[inline] -pub(crate) fn makedev(maj: u32, min: u32) -> Dev { - c::makedev(maj, min) -} - -#[cfg(solarish)] -pub(crate) fn makedev(maj: u32, min: u32) -> Dev { - // SAFETY: Solarish's `makedev` is marked unsafe but it isn't doing - // anything unsafe. - unsafe { c::makedev(maj, min) } -} - -#[cfg(all(target_os = "android", not(target_pointer_width = "32")))] -#[inline] -pub(crate) fn makedev(maj: u32, min: u32) -> Dev { - c::makedev(maj, min) -} - -#[cfg(all(target_os = "android", target_pointer_width = "32"))] -#[inline] -pub(crate) fn makedev(maj: u32, min: u32) -> Dev { - // 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit, so we do - // it ourselves. - ((u64::from(maj) & 0xffff_f000_u64) << 32) - | ((u64::from(maj) & 0x0000_0fff_u64) << 8) - | ((u64::from(min) & 0xffff_ff00_u64) << 12) - | (u64::from(min) & 0x0000_00ff_u64) -} - -#[cfg(target_os = "emscripten")] -#[inline] -pub(crate) fn makedev(maj: u32, min: u32) -> Dev { - // Emscripten's `makedev` has a 32-bit return value. - Dev::from(c::makedev(maj, min)) -} - -#[cfg(apple)] -#[inline] -pub(crate) fn makedev(maj: u32, min: u32) -> Dev { - // Apple's `makedev` oddly has signed argument types and is `unsafe`. - unsafe { c::makedev(maj as i32, min as i32) } -} - -#[cfg(target_os = "aix")] -#[inline] -pub(crate) fn makedev(maj: u32, min: u32) -> Dev { - // AIX's `makedev` oddly is `unsafe`. - unsafe { c::makedev(maj, min) } -} - -#[cfg(not(any( - apple, - freebsdlike, - target_os = "android", - target_os = "emscripten", - target_os = "netbsd" -)))] -#[inline] -pub(crate) fn major(dev: Dev) -> u32 { - unsafe { c::major(dev) } -} - -#[cfg(any( - apple, - freebsdlike, - target_os = "netbsd", - all(target_os = "android", not(target_pointer_width = "32")), -))] -#[inline] -pub(crate) fn major(dev: Dev) -> u32 { - // On some platforms `major` oddly has signed return types. - (unsafe { c::major(dev) }) as u32 -} - -#[cfg(all(target_os = "android", target_pointer_width = "32"))] -#[inline] -pub(crate) fn major(dev: Dev) -> u32 { - // 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit, so we do - // it ourselves. - (((dev >> 31 >> 1) & 0xffff_f000) | ((dev >> 8) & 0x0000_0fff)) as u32 -} - -#[cfg(target_os = "emscripten")] -#[inline] -pub(crate) fn major(dev: Dev) -> u32 { - // Emscripten's `major` has a 32-bit argument value. - unsafe { c::major(dev as u32) } -} - -#[cfg(not(any( - apple, - freebsdlike, - target_os = "android", - target_os = "emscripten", - target_os = "netbsd" -)))] -#[inline] -pub(crate) fn minor(dev: Dev) -> u32 { - unsafe { c::minor(dev) } -} - -#[cfg(any( - apple, - freebsdlike, - target_os = "netbsd", - all(target_os = "android", not(target_pointer_width = "32")) -))] -#[inline] -pub(crate) fn minor(dev: Dev) -> u32 { - // On some platforms, `minor` oddly has signed return types. - (unsafe { c::minor(dev) }) as u32 -} - -#[cfg(all(target_os = "android", target_pointer_width = "32"))] -#[inline] -pub(crate) fn minor(dev: Dev) -> u32 { - // 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit, so we do - // it ourselves. - (((dev >> 12) & 0xffff_ff00) | (dev & 0x0000_00ff)) as u32 -} - -#[cfg(target_os = "emscripten")] -#[inline] -pub(crate) fn minor(dev: Dev) -> u32 { - // Emscripten's `minor` has a 32-bit argument value. - unsafe { c::minor(dev as u32) } -} diff --git a/vendor/rustix/src/backend/libc/fs/mod.rs b/vendor/rustix/src/backend/libc/fs/mod.rs deleted file mode 100644 index c17e863..0000000 --- a/vendor/rustix/src/backend/libc/fs/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -#[cfg(all(feature = "alloc", not(any(target_os = "espidf", target_os = "redox"))))] -pub(crate) mod dir; -#[cfg(linux_kernel)] -pub mod inotify; -#[cfg(not(any( - target_os = "espidf", - target_os = "haiku", - target_os = "redox", - target_os = "vita", - target_os = "wasi" -)))] -pub(crate) mod makedev; -#[cfg(not(windows))] -pub(crate) mod syscalls; -pub(crate) mod types; - -// TODO: Fix linux-raw-sys to define ioctl codes for sparc. -#[cfg(all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")))] -pub(crate) const EXT4_IOC_RESIZE_FS: crate::ioctl::RawOpcode = 0x8008_6610; - -#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))] -pub(crate) const EXT4_IOC_RESIZE_FS: crate::ioctl::RawOpcode = - linux_raw_sys::ioctl::EXT4_IOC_RESIZE_FS as crate::ioctl::RawOpcode; diff --git a/vendor/rustix/src/backend/libc/fs/syscalls.rs b/vendor/rustix/src/backend/libc/fs/syscalls.rs deleted file mode 100644 index 70e86cf..0000000 --- a/vendor/rustix/src/backend/libc/fs/syscalls.rs +++ /dev/null @@ -1,2514 +0,0 @@ -//! libc syscalls supporting `rustix::fs`. - -use crate::backend::c; -#[cfg(any( - not(target_os = "redox"), - feature = "alloc", - all(linux_kernel, feature = "procfs") -))] -use crate::backend::conv::ret_usize; -use crate::backend::conv::{borrowed_fd, c_str, ret, ret_c_int, ret_off_t, ret_owned_fd}; -use crate::fd::{BorrowedFd, OwnedFd}; -use crate::ffi::CStr; -#[cfg(all(apple, feature = "alloc"))] -use crate::ffi::CString; -#[cfg(not(any(target_os = "espidf", target_os = "vita")))] -use crate::fs::Access; -#[cfg(not(any( - apple, - netbsdlike, - solarish, - target_os = "dragonfly", - target_os = "espidf", - target_os = "haiku", - target_os = "redox", - target_os = "vita", -)))] -use crate::fs::Advice; -#[cfg(not(any(target_os = "espidf", target_os = "redox")))] -use crate::fs::AtFlags; -#[cfg(not(any( - netbsdlike, - solarish, - target_os = "aix", - target_os = "dragonfly", - target_os = "espidf", - target_os = "nto", - target_os = "redox", - target_os = "vita", -)))] -use crate::fs::FallocateFlags; -#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "wasi")))] -use crate::fs::FlockOperation; -#[cfg(any(linux_kernel, target_os = "freebsd"))] -use crate::fs::MemfdFlags; -#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] -use crate::fs::SealFlags; -#[cfg(not(any( - solarish, - target_os = "espidf", - target_os = "haiku", - target_os = "netbsd", - target_os = "nto", - target_os = "redox", - target_os = "vita", - target_os = "wasi", -)))] -use crate::fs::StatFs; -#[cfg(not(any(target_os = "espidf", target_os = "vita")))] -use crate::fs::Timestamps; -#[cfg(not(any( - apple, - target_os = "espidf", - target_os = "redox", - target_os = "vita", - target_os = "wasi" -)))] -use crate::fs::{Dev, FileType}; -use crate::fs::{Mode, OFlags, SeekFrom, Stat}; -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -use crate::fs::{StatVfs, StatVfsMountFlags}; -use crate::io; -#[cfg(all(target_env = "gnu", fix_y2038))] -use crate::timespec::LibcTimespec; -#[cfg(not(target_os = "wasi"))] -use crate::ugid::{Gid, Uid}; -#[cfg(all(apple, feature = "alloc"))] -use alloc::vec; -use core::mem::MaybeUninit; -#[cfg(apple)] -use { - crate::backend::conv::nonnegative_ret, - crate::fs::{copyfile_state_t, CloneFlags, CopyfileFlags}, -}; -#[cfg(any(apple, linux_kernel))] -use {crate::fs::XattrFlags, core::mem::size_of, core::ptr::null_mut}; -#[cfg(linux_kernel)] -use { - crate::fs::{RenameFlags, ResolveFlags, Statx, StatxFlags, CWD}, - core::ptr::null, -}; - -#[cfg(all(target_env = "gnu", fix_y2038))] -weak!(fn __utimensat64(c::c_int, *const c::c_char, *const LibcTimespec, c::c_int) -> c::c_int); -#[cfg(all(target_env = "gnu", fix_y2038))] -weak!(fn __futimens64(c::c_int, *const LibcTimespec) -> c::c_int); - -/// Use a direct syscall (via libc) for `open`. -/// -/// This is only currently necessary as a workaround for old glibc; see below. -#[cfg(all(unix, target_env = "gnu"))] -fn open_via_syscall(path: &CStr, oflags: OFlags, mode: Mode) -> io::Result<OwnedFd> { - // Linux on aarch64, loongarch64 and riscv64 has no `open` syscall so use - // `openat`. - #[cfg(any( - target_arch = "aarch64", - target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "csky", - target_arch = "loongarch64" - ))] - { - openat_via_syscall(CWD, path, oflags, mode) - } - - // Use the `open` syscall. - #[cfg(not(any( - target_arch = "aarch64", - target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "csky", - target_arch = "loongarch64" - )))] - unsafe { - syscall! { - fn open( - pathname: *const c::c_char, - oflags: c::c_int, - mode: c::mode_t - ) via SYS_open -> c::c_int - } - - ret_owned_fd(open( - c_str(path), - bitflags_bits!(oflags), - bitflags_bits!(mode), - )) - } -} - -pub(crate) fn open(path: &CStr, oflags: OFlags, mode: Mode) -> io::Result<OwnedFd> { - // Work around <https://sourceware.org/bugzilla/show_bug.cgi?id=17523>. - // glibc versions before 2.25 don't handle `O_TMPFILE` correctly. - #[cfg(all(unix, target_env = "gnu", not(target_os = "hurd")))] - if oflags.contains(OFlags::TMPFILE) && crate::backend::if_glibc_is_less_than_2_25() { - return open_via_syscall(path, oflags, mode); - } - - // On these platforms, `mode_t` is `u16` and can't be passed directly to a - // variadic function. - #[cfg(any( - apple, - freebsdlike, - all(target_os = "android", target_pointer_width = "32") - ))] - let mode: c::c_uint = mode.bits().into(); - - // Otherwise, cast to `mode_t` as that's what `open` is documented to take. - #[cfg(not(any( - apple, - freebsdlike, - all(target_os = "android", target_pointer_width = "32") - )))] - let mode: c::mode_t = mode.bits() as _; - - unsafe { ret_owned_fd(c::open(c_str(path), bitflags_bits!(oflags), mode)) } -} - -/// Use a direct syscall (via libc) for `openat`. -/// -/// This is only currently necessary as a workaround for old glibc; see below. -#[cfg(all(unix, target_env = "gnu", not(target_os = "hurd")))] -fn openat_via_syscall( - dirfd: BorrowedFd<'_>, - path: &CStr, - oflags: OFlags, - mode: Mode, -) -> io::Result<OwnedFd> { - syscall! { - fn openat( - base_dirfd: c::c_int, - pathname: *const c::c_char, - oflags: c::c_int, - mode: c::mode_t - ) via SYS_openat -> c::c_int - } - - unsafe { - ret_owned_fd(openat( - borrowed_fd(dirfd), - c_str(path), - bitflags_bits!(oflags), - bitflags_bits!(mode), - )) - } -} - -#[cfg(not(target_os = "redox"))] -pub(crate) fn openat( - dirfd: BorrowedFd<'_>, - path: &CStr, - oflags: OFlags, - mode: Mode, -) -> io::Result<OwnedFd> { - // Work around <https://sourceware.org/bugzilla/show_bug.cgi?id=17523>. - // glibc versions before 2.25 don't handle `O_TMPFILE` correctly. - #[cfg(all(unix, target_env = "gnu", not(target_os = "hurd")))] - if oflags.contains(OFlags::TMPFILE) && crate::backend::if_glibc_is_less_than_2_25() { - return openat_via_syscall(dirfd, path, oflags, mode); - } - - // On these platforms, `mode_t` is `u16` and can't be passed directly to a - // variadic function. - #[cfg(any( - apple, - freebsdlike, - all(target_os = "android", target_pointer_width = "32") - ))] - let mode: c::c_uint = mode.bits().into(); - - // Otherwise, cast to `mode_t` as that's what `open` is documented to take. - #[cfg(not(any( - apple, - freebsdlike, - all(target_os = "android", target_pointer_width = "32") - )))] - let mode: c::mode_t = mode.bits() as _; - - unsafe { - ret_owned_fd(c::openat( - borrowed_fd(dirfd), - c_str(path), - bitflags_bits!(oflags), - mode, - )) - } -} - -#[cfg(not(any( - solarish, - target_os = "espidf", - target_os = "haiku", - target_os = "netbsd", - target_os = "nto", - target_os = "redox", - target_os = "vita", - target_os = "wasi", -)))] -#[inline] -pub(crate) fn statfs(filename: &CStr) -> io::Result<StatFs> { - unsafe { - let mut result = MaybeUninit::<StatFs>::uninit(); - ret(c::statfs(c_str(filename), result.as_mut_ptr()))?; - Ok(result.assume_init()) - } -} - -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -#[inline] -pub(crate) fn statvfs(filename: &CStr) -> io::Result<StatVfs> { - unsafe { - let mut result = MaybeUninit::<c::statvfs>::uninit(); - ret(c::statvfs(c_str(filename), result.as_mut_ptr()))?; - Ok(libc_statvfs_to_statvfs(result.assume_init())) - } -} - -#[cfg(feature = "alloc")] -#[inline] -pub(crate) fn readlink(path: &CStr, buf: &mut [u8]) -> io::Result<usize> { - unsafe { - ret_usize( - c::readlink(c_str(path), buf.as_mut_ptr().cast::<c::c_char>(), buf.len()) as isize, - ) - } -} - -#[cfg(not(target_os = "redox"))] -#[inline] -pub(crate) fn readlinkat( - dirfd: BorrowedFd<'_>, - path: &CStr, - buf: &mut [MaybeUninit<u8>], -) -> io::Result<usize> { - unsafe { - ret_usize(c::readlinkat( - borrowed_fd(dirfd), - c_str(path), - buf.as_mut_ptr().cast::<c::c_char>(), - buf.len(), - ) as isize) - } -} - -pub(crate) fn mkdir(path: &CStr, mode: Mode) -> io::Result<()> { - unsafe { ret(c::mkdir(c_str(path), mode.bits() as c::mode_t)) } -} - -#[cfg(not(target_os = "redox"))] -pub(crate) fn mkdirat(dirfd: BorrowedFd<'_>, path: &CStr, mode: Mode) -> io::Result<()> { - unsafe { - ret(c::mkdirat( - borrowed_fd(dirfd), - c_str(path), - mode.bits() as c::mode_t, - )) - } -} - -#[cfg(linux_kernel)] -pub(crate) fn getdents_uninit( - fd: BorrowedFd<'_>, - buf: &mut [MaybeUninit<u8>], -) -> io::Result<usize> { - syscall! { - fn getdents64( - fd: c::c_int, - dirp: *mut c::c_void, - count: usize - ) via SYS_getdents64 -> c::ssize_t - } - unsafe { - ret_usize(getdents64( - borrowed_fd(fd), - buf.as_mut_ptr().cast::<c::c_void>(), - buf.len(), - )) - } -} - -pub(crate) fn link(old_path: &CStr, new_path: &CStr) -> io::Result<()> { - unsafe { ret(c::link(c_str(old_path), c_str(new_path))) } -} - -#[cfg(not(any(target_os = "espidf", target_os = "redox")))] -pub(crate) fn linkat( - old_dirfd: BorrowedFd<'_>, - old_path: &CStr, - new_dirfd: BorrowedFd<'_>, - new_path: &CStr, - flags: AtFlags, -) -> io::Result<()> { - // macOS <= 10.9 lacks `linkat`. - #[cfg(target_os = "macos")] - unsafe { - weak! { - fn linkat( - c::c_int, - *const c::c_char, - c::c_int, - *const c::c_char, - c::c_int - ) -> c::c_int - } - // If we have `linkat`, use it. - if let Some(libc_linkat) = linkat.get() { - return ret(libc_linkat( - borrowed_fd(old_dirfd), - c_str(old_path), - borrowed_fd(new_dirfd), - c_str(new_path), - bitflags_bits!(flags), - )); - } - // Otherwise, see if we can emulate the `AT_FDCWD` case. - if borrowed_fd(old_dirfd) != c::AT_FDCWD || borrowed_fd(new_dirfd) != c::AT_FDCWD { - return Err(io::Errno::NOSYS); - } - if flags.intersects(!AtFlags::SYMLINK_FOLLOW) { - return Err(io::Errno::INVAL); - } - if !flags.is_empty() { - return Err(io::Errno::OPNOTSUPP); - } - ret(c::link(c_str(old_path), c_str(new_path))) - } - - #[cfg(not(target_os = "macos"))] - unsafe { - ret(c::linkat( - borrowed_fd(old_dirfd), - c_str(old_path), - borrowed_fd(new_dirfd), - c_str(new_path), - bitflags_bits!(flags), - )) - } -} - -pub(crate) fn rmdir(path: &CStr) -> io::Result<()> { - unsafe { ret(c::rmdir(c_str(path))) } -} - -pub(crate) fn unlink(path: &CStr) -> io::Result<()> { - unsafe { ret(c::unlink(c_str(path))) } -} - -#[cfg(not(any(target_os = "espidf", target_os = "redox")))] -pub(crate) fn unlinkat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result<()> { - // macOS <= 10.9 lacks `unlinkat`. - #[cfg(target_os = "macos")] - unsafe { - weak! { - fn unlinkat( - c::c_int, - *const c::c_char, - c::c_int - ) -> c::c_int - } - // If we have `unlinkat`, use it. - if let Some(libc_unlinkat) = unlinkat.get() { - return ret(libc_unlinkat( - borrowed_fd(dirfd), - c_str(path), - bitflags_bits!(flags), - )); - } - // Otherwise, see if we can emulate the `AT_FDCWD` case. - if borrowed_fd(dirfd) != c::AT_FDCWD { - return Err(io::Errno::NOSYS); - } - if flags.intersects(!AtFlags::REMOVEDIR) { - return Err(io::Errno::INVAL); - } - if flags.contains(AtFlags::REMOVEDIR) { - ret(c::rmdir(c_str(path))) - } else { - ret(c::unlink(c_str(path))) - } - } - - #[cfg(not(target_os = "macos"))] - unsafe { - ret(c::unlinkat( - borrowed_fd(dirfd), - c_str(path), - bitflags_bits!(flags), - )) - } -} - -pub(crate) fn rename(old_path: &CStr, new_path: &CStr) -> io::Result<()> { - unsafe { ret(c::rename(c_str(old_path), c_str(new_path))) } -} - -#[cfg(not(target_os = "redox"))] -pub(crate) fn renameat( - old_dirfd: BorrowedFd<'_>, - old_path: &CStr, - new_dirfd: BorrowedFd<'_>, - new_path: &CStr, -) -> io::Result<()> { - // macOS <= 10.9 lacks `renameat`. - #[cfg(target_os = "macos")] - unsafe { - weak! { - fn renameat( - c::c_int, - *const c::c_char, - c::c_int, - *const c::c_char - ) -> c::c_int - } - // If we have `renameat`, use it. - if let Some(libc_renameat) = renameat.get() { - return ret(libc_renameat( - borrowed_fd(old_dirfd), - c_str(old_path), - borrowed_fd(new_dirfd), - c_str(new_path), - )); - } - // Otherwise, see if we can emulate the `AT_FDCWD` case. - if borrowed_fd(old_dirfd) != c::AT_FDCWD || borrowed_fd(new_dirfd) != c::AT_FDCWD { - return Err(io::Errno::NOSYS); - } - ret(c::rename(c_str(old_path), c_str(new_path))) - } - - #[cfg(not(target_os = "macos"))] - unsafe { - ret(c::renameat( - borrowed_fd(old_dirfd), - c_str(old_path), - borrowed_fd(new_dirfd), - c_str(new_path), - )) - } -} - -#[cfg(all(target_os = "linux", target_env = "gnu"))] -pub(crate) fn renameat2( - old_dirfd: BorrowedFd<'_>, - old_path: &CStr, - new_dirfd: BorrowedFd<'_>, - new_path: &CStr, - flags: RenameFlags, -) -> io::Result<()> { - // `renameat2` wasn't supported in glibc until 2.28. - weak_or_syscall! { - fn renameat2( - olddirfd: c::c_int, - oldpath: *const c::c_char, - newdirfd: c::c_int, - newpath: *const c::c_char, - flags: c::c_uint - ) via SYS_renameat2 -> c::c_int - } - - unsafe { - ret(renameat2( - borrowed_fd(old_dirfd), - c_str(old_path), - borrowed_fd(new_dirfd), - c_str(new_path), - flags.bits(), - )) - } -} - -#[cfg(any( - target_os = "android", - all(target_os = "linux", not(target_env = "gnu")), -))] -#[inline] -pub(crate) fn renameat2( - old_dirfd: BorrowedFd<'_>, - old_path: &CStr, - new_dirfd: BorrowedFd<'_>, - new_path: &CStr, - flags: RenameFlags, -) -> io::Result<()> { - // At present, `libc` only has `renameat2` defined for glibc. If we have - // no flags, we can use plain `renameat`, but otherwise we use `syscall!`. - // to call `renameat2` ourselves. - if flags.is_empty() { - renameat(old_dirfd, old_path, new_dirfd, new_path) - } else { - syscall! { - fn renameat2( - olddirfd: c::c_int, - oldpath: *const c::c_char, - newdirfd: c::c_int, - newpath: *const c::c_char, - flags: c::c_uint - ) via SYS_renameat2 -> c::c_int - } - - unsafe { - ret(renameat2( - borrowed_fd(old_dirfd), - c_str(old_path), - borrowed_fd(new_dirfd), - c_str(new_path), - flags.bits(), - )) - } - } -} - -pub(crate) fn symlink(old_path: &CStr, new_path: &CStr) -> io::Result<()> { - unsafe { ret(c::symlink(c_str(old_path), c_str(new_path))) } -} - -#[cfg(not(target_os = "redox"))] -pub(crate) fn symlinkat( - old_path: &CStr, - new_dirfd: BorrowedFd<'_>, - new_path: &CStr, -) -> io::Result<()> { - unsafe { - ret(c::symlinkat( - c_str(old_path), - borrowed_fd(new_dirfd), - c_str(new_path), - )) - } -} - -pub(crate) fn stat(path: &CStr) -> io::Result<Stat> { - // See the comments in `fstat` about using `crate::fs::statx` here. - #[cfg(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) - ))] - { - match crate::fs::statx( - crate::fs::CWD, - path, - AtFlags::empty(), - StatxFlags::BASIC_STATS, - ) { - Ok(x) => statx_to_stat(x), - Err(io::Errno::NOSYS) => statat_old(crate::fs::CWD, path, AtFlags::empty()), - Err(err) => Err(err), - } - } - - // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and - // there's nothing practical we can do. - #[cfg(not(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) - )))] - unsafe { - let mut stat = MaybeUninit::<Stat>::uninit(); - ret(c::stat(c_str(path), stat.as_mut_ptr()))?; - Ok(stat.assume_init()) - } -} - -pub(crate) fn lstat(path: &CStr) -> io::Result<Stat> { - // See the comments in `fstat` about using `crate::fs::statx` here. - #[cfg(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) - ))] - { - match crate::fs::statx( - crate::fs::CWD, - path, - AtFlags::SYMLINK_NOFOLLOW, - StatxFlags::BASIC_STATS, - ) { - Ok(x) => statx_to_stat(x), - Err(io::Errno::NOSYS) => statat_old(crate::fs::CWD, path, AtFlags::SYMLINK_NOFOLLOW), - Err(err) => Err(err), - } - } - - // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and - // there's nothing practical we can do. - #[cfg(not(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) - )))] - unsafe { - let mut stat = MaybeUninit::<Stat>::uninit(); - ret(c::lstat(c_str(path), stat.as_mut_ptr()))?; - Ok(stat.assume_init()) - } -} - -#[cfg(not(any(target_os = "espidf", target_os = "redox")))] -pub(crate) fn statat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result<Stat> { - // See the comments in `fstat` about using `crate::fs::statx` here. - #[cfg(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) - ))] - { - match crate::fs::statx(dirfd, path, flags, StatxFlags::BASIC_STATS) { - Ok(x) => statx_to_stat(x), - Err(io::Errno::NOSYS) => statat_old(dirfd, path, flags), - Err(err) => Err(err), - } - } - - // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and - // there's nothing practical we can do. - #[cfg(not(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) - )))] - unsafe { - let mut stat = MaybeUninit::<Stat>::uninit(); - ret(c::fstatat( - borrowed_fd(dirfd), - c_str(path), - stat.as_mut_ptr(), - bitflags_bits!(flags), - ))?; - Ok(stat.assume_init()) - } -} - -#[cfg(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) -))] -fn statat_old(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result<Stat> { - unsafe { - let mut result = MaybeUninit::<c::stat64>::uninit(); - ret(c::fstatat( - borrowed_fd(dirfd), - c_str(path), - result.as_mut_ptr(), - bitflags_bits!(flags), - ))?; - stat64_to_stat(result.assume_init()) - } -} - -#[cfg(not(any(target_os = "espidf", target_os = "emscripten", target_os = "vita")))] -pub(crate) fn access(path: &CStr, access: Access) -> io::Result<()> { - unsafe { ret(c::access(c_str(path), access.bits())) } -} - -#[cfg(not(any( - target_os = "emscripten", - target_os = "espidf", - target_os = "redox", - target_os = "vita" -)))] -pub(crate) fn accessat( - dirfd: BorrowedFd<'_>, - path: &CStr, - access: Access, - flags: AtFlags, -) -> io::Result<()> { - // macOS <= 10.9 lacks `faccessat`. - #[cfg(target_os = "macos")] - unsafe { - weak! { - fn faccessat( - c::c_int, - *const c::c_char, - c::c_int, - c::c_int - ) -> c::c_int - } - // If we have `faccessat`, use it. - if let Some(libc_faccessat) = faccessat.get() { - return ret(libc_faccessat( - borrowed_fd(dirfd), - c_str(path), - bitflags_bits!(access), - bitflags_bits!(flags), - )); - } - // Otherwise, see if we can emulate the `AT_FDCWD` case. - if borrowed_fd(dirfd) != c::AT_FDCWD { - return Err(io::Errno::NOSYS); - } - if flags.intersects(!(AtFlags::EACCESS | AtFlags::SYMLINK_NOFOLLOW)) { - return Err(io::Errno::INVAL); - } - if !flags.is_empty() { - return Err(io::Errno::OPNOTSUPP); - } - ret(c::access(c_str(path), bitflags_bits!(access))) - } - - #[cfg(not(target_os = "macos"))] - unsafe { - ret(c::faccessat( - borrowed_fd(dirfd), - c_str(path), - bitflags_bits!(access), - bitflags_bits!(flags), - )) - } -} - -#[cfg(target_os = "emscripten")] -pub(crate) fn access(_path: &CStr, _access: Access) -> io::Result<()> { - Ok(()) -} - -#[cfg(target_os = "emscripten")] -pub(crate) fn accessat( - _dirfd: BorrowedFd<'_>, - _path: &CStr, - _access: Access, - _flags: AtFlags, -) -> io::Result<()> { - Ok(()) -} - -#[cfg(not(any(target_os = "espidf", target_os = "redox", target_os = "vita")))] -pub(crate) fn utimensat( - dirfd: BorrowedFd<'_>, - path: &CStr, - times: &Timestamps, - flags: AtFlags, -) -> io::Result<()> { - // Old 32-bit version: libc has `utimensat` but it is not y2038 safe by - // default. But there may be a `__utimensat16` we can use. - #[cfg(fix_y2038)] - { - #[cfg(target_env = "gnu")] - if let Some(libc_utimensat) = __utimensat64.get() { - let libc_times: [LibcTimespec; 2] = [ - times.last_access.clone().into(), - times.last_modification.clone().into(), - ]; - - unsafe { - return ret(libc_utimensat( - borrowed_fd(dirfd), - c_str(path), - libc_times.as_ptr(), - bitflags_bits!(flags), - )); - } - } - - utimensat_old(dirfd, path, times, flags) - } - - // Main version: libc is y2038 safe and has `utimensat`. Or, the platform - // is not y2038 safe and there's nothing practical we can do. - #[cfg(not(any(apple, fix_y2038)))] - unsafe { - use crate::utils::as_ptr; - - ret(c::utimensat( - borrowed_fd(dirfd), - c_str(path), - as_ptr(times).cast(), - bitflags_bits!(flags), - )) - } - - // Apple version: `utimensat` was introduced in macOS 10.13. - #[cfg(apple)] - unsafe { - use crate::utils::as_ptr; - - // ABI details - weak! { - fn utimensat( - c::c_int, - *const c::c_char, - *const c::timespec, - c::c_int - ) -> c::c_int - } - extern "C" { - fn setattrlist( - path: *const c::c_char, - attr_list: *const Attrlist, - attr_buf: *const c::c_void, - attr_buf_size: c::size_t, - options: c::c_ulong, - ) -> c::c_int; - } - const FSOPT_NOFOLLOW: c::c_ulong = 0x0000_0001; - - // If we have `utimensat`, use it. - if let Some(have_utimensat) = utimensat.get() { - return ret(have_utimensat( - borrowed_fd(dirfd), - c_str(path), - as_ptr(times).cast(), - bitflags_bits!(flags), - )); - } - - // `setattrlistat` was introduced in 10.13 along with `utimensat`, so - // if we don't have `utimensat`, we don't have `setattrlistat` either. - // Emulate it using `fork`, and `fchdir` and [`setattrlist`]. - // - // [`setattrlist`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setattrlist.2.html - match c::fork() { - -1 => Err(io::Errno::IO), - 0 => { - if c::fchdir(borrowed_fd(dirfd)) != 0 { - let code = match libc_errno::errno().0 { - c::EACCES => 2, - c::ENOTDIR => 3, - _ => 1, - }; - c::_exit(code); - } - - let mut flags_arg = 0; - if flags.contains(AtFlags::SYMLINK_NOFOLLOW) { - flags_arg |= FSOPT_NOFOLLOW; - } - - let (attrbuf_size, times, attrs) = times_to_attrlist(times); - - if setattrlist( - c_str(path), - &attrs, - as_ptr(×).cast(), - attrbuf_size, - flags_arg, - ) != 0 - { - // Translate expected `errno` codes into ad-hoc integer - // values suitable for exit statuses. - let code = match libc_errno::errno().0 { - c::EACCES => 2, - c::ENOTDIR => 3, - c::EPERM => 4, - c::EROFS => 5, - c::ELOOP => 6, - c::ENOENT => 7, - c::ENAMETOOLONG => 8, - c::EINVAL => 9, - c::ESRCH => 10, - c::ENOTSUP => 11, - _ => 1, - }; - c::_exit(code); - } - - c::_exit(0); - } - child_pid => { - let mut wstatus = 0; - let _ = ret_c_int(c::waitpid(child_pid, &mut wstatus, 0))?; - if c::WIFEXITED(wstatus) { - // Translate our ad-hoc exit statuses back to `errno` - // codes. - match c::WEXITSTATUS(wstatus) { - 0 => Ok(()), - 2 => Err(io::Errno::ACCESS), - 3 => Err(io::Errno::NOTDIR), - 4 => Err(io::Errno::PERM), - 5 => Err(io::Errno::ROFS), - 6 => Err(io::Errno::LOOP), - 7 => Err(io::Errno::NOENT), - 8 => Err(io::Errno::NAMETOOLONG), - 9 => Err(io::Errno::INVAL), - 10 => Err(io::Errno::SRCH), - 11 => Err(io::Errno::NOTSUP), - _ => Err(io::Errno::IO), - } - } else { - Err(io::Errno::IO) - } - } - } - } -} - -#[cfg(fix_y2038)] -fn utimensat_old( - dirfd: BorrowedFd<'_>, - path: &CStr, - times: &Timestamps, - flags: AtFlags, -) -> io::Result<()> { - let old_times = [ - c::timespec { - tv_sec: times - .last_access - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: times - .last_access - .tv_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - }, - c::timespec { - tv_sec: times - .last_modification - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: times - .last_modification - .tv_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - }, - ]; - unsafe { - ret(c::utimensat( - borrowed_fd(dirfd), - c_str(path), - old_times.as_ptr(), - bitflags_bits!(flags), - )) - } -} - -#[cfg(not(target_os = "wasi"))] -pub(crate) fn chmod(path: &CStr, mode: Mode) -> io::Result<()> { - unsafe { ret(c::chmod(c_str(path), mode.bits() as c::mode_t)) } -} - -#[cfg(not(any( - linux_kernel, - target_os = "espidf", - target_os = "redox", - target_os = "wasi" -)))] -pub(crate) fn chmodat( - dirfd: BorrowedFd<'_>, - path: &CStr, - mode: Mode, - flags: AtFlags, -) -> io::Result<()> { - unsafe { - ret(c::fchmodat( - borrowed_fd(dirfd), - c_str(path), - mode.bits() as c::mode_t, - bitflags_bits!(flags), - )) - } -} - -#[cfg(linux_kernel)] -pub(crate) fn chmodat( - dirfd: BorrowedFd<'_>, - path: &CStr, - mode: Mode, - flags: AtFlags, -) -> io::Result<()> { - // Linux's `fchmodat` does not have a flags argument. - // - // Use `c::syscall` rather than `c::fchmodat` because some libc - // implementations, such as musl, add extra logic to `fchmod` to emulate - // support for `AT_SYMLINK_NOFOLLOW`, which uses `/proc` outside our - // control. - syscall! { - fn fchmodat( - base_dirfd: c::c_int, - pathname: *const c::c_char, - mode: c::mode_t - ) via SYS_fchmodat -> c::c_int - } - if flags == AtFlags::SYMLINK_NOFOLLOW { - return Err(io::Errno::OPNOTSUPP); - } - if !flags.is_empty() { - return Err(io::Errno::INVAL); - } - unsafe { - ret(fchmodat( - borrowed_fd(dirfd), - c_str(path), - mode.bits() as c::mode_t, - )) - } -} - -#[cfg(apple)] -pub(crate) fn fclonefileat( - srcfd: BorrowedFd<'_>, - dst_dirfd: BorrowedFd<'_>, - dst: &CStr, - flags: CloneFlags, -) -> io::Result<()> { - syscall! { - fn fclonefileat( - srcfd: BorrowedFd<'_>, - dst_dirfd: BorrowedFd<'_>, - dst: *const c::c_char, - flags: c::c_int - ) via SYS_fclonefileat -> c::c_int - } - - unsafe { - ret(fclonefileat( - srcfd, - dst_dirfd, - c_str(dst), - bitflags_bits!(flags), - )) - } -} - -#[cfg(not(any(target_os = "espidf", target_os = "redox", target_os = "wasi")))] -pub(crate) fn chownat( - dirfd: BorrowedFd<'_>, - path: &CStr, - owner: Option<Uid>, - group: Option<Gid>, - flags: AtFlags, -) -> io::Result<()> { - unsafe { - let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); - ret(c::fchownat( - borrowed_fd(dirfd), - c_str(path), - ow, - gr, - bitflags_bits!(flags), - )) - } -} - -#[cfg(not(any( - apple, - target_os = "espidf", - target_os = "redox", - target_os = "vita", - target_os = "wasi" -)))] -pub(crate) fn mknodat( - dirfd: BorrowedFd<'_>, - path: &CStr, - file_type: FileType, - mode: Mode, - dev: Dev, -) -> io::Result<()> { - unsafe { - ret(c::mknodat( - borrowed_fd(dirfd), - c_str(path), - (mode.bits() | file_type.as_raw_mode()) as c::mode_t, - dev.try_into().map_err(|_e| io::Errno::PERM)?, - )) - } -} - -#[cfg(linux_kernel)] -pub(crate) fn copy_file_range( - fd_in: BorrowedFd<'_>, - off_in: Option<&mut u64>, - fd_out: BorrowedFd<'_>, - off_out: Option<&mut u64>, - len: usize, -) -> io::Result<usize> { - syscall! { - fn copy_file_range( - fd_in: c::c_int, - off_in: *mut c::loff_t, - fd_out: c::c_int, - off_out: *mut c::loff_t, - len: usize, - flags: c::c_uint - ) via SYS_copy_file_range -> c::ssize_t - } - - let mut off_in_val: c::loff_t = 0; - let mut off_out_val: c::loff_t = 0; - // Silently cast; we'll get `EINVAL` if the value is negative. - let off_in_ptr = if let Some(off_in) = &off_in { - off_in_val = **off_in as i64; - &mut off_in_val - } else { - null_mut() - }; - let off_out_ptr = if let Some(off_out) = &off_out { - off_out_val = **off_out as i64; - &mut off_out_val - } else { - null_mut() - }; - let copied = unsafe { - ret_usize(copy_file_range( - borrowed_fd(fd_in), - off_in_ptr, - borrowed_fd(fd_out), - off_out_ptr, - len, - 0, // no flags are defined yet - ))? - }; - if let Some(off_in) = off_in { - *off_in = off_in_val as u64; - } - if let Some(off_out) = off_out { - *off_out = off_out_val as u64; - } - Ok(copied) -} - -#[cfg(not(any( - apple, - netbsdlike, - solarish, - target_os = "dragonfly", - target_os = "espidf", - target_os = "haiku", - target_os = "redox", - target_os = "vita", -)))] -pub(crate) fn fadvise(fd: BorrowedFd<'_>, offset: u64, len: u64, advice: Advice) -> io::Result<()> { - let offset = offset as i64; - let len = len as i64; - - // FreeBSD returns `EINVAL` on invalid offsets; emulate the POSIX behavior. - #[cfg(target_os = "freebsd")] - let offset = if (offset as i64) < 0 { - i64::MAX - } else { - offset - }; - - // FreeBSD returns `EINVAL` on overflow; emulate the POSIX behavior. - #[cfg(target_os = "freebsd")] - let len = if len > 0 && offset.checked_add(len).is_none() { - i64::MAX - offset - } else { - len - }; - - let err = unsafe { c::posix_fadvise(borrowed_fd(fd), offset, len, advice as c::c_int) }; - - // `posix_fadvise` returns its error status rather than using `errno`. - if err == 0 { - Ok(()) - } else { - Err(io::Errno(err)) - } -} - -pub(crate) fn fcntl_getfl(fd: BorrowedFd<'_>) -> io::Result<OFlags> { - let flags = unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFL))? }; - Ok(OFlags::from_bits_retain(bitcast!(flags))) -} - -pub(crate) fn fcntl_setfl(fd: BorrowedFd<'_>, flags: OFlags) -> io::Result<()> { - unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETFL, flags.bits())) } -} - -#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] -pub(crate) fn fcntl_get_seals(fd: BorrowedFd<'_>) -> io::Result<SealFlags> { - let flags = unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GET_SEALS))? }; - Ok(SealFlags::from_bits_retain(bitcast!(flags))) -} - -#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] -pub(crate) fn fcntl_add_seals(fd: BorrowedFd<'_>, seals: SealFlags) -> io::Result<()> { - unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_ADD_SEALS, seals.bits())) } -} - -#[cfg(not(any( - target_os = "emscripten", - target_os = "espidf", - target_os = "fuchsia", - target_os = "redox", - target_os = "vita", - target_os = "wasi" -)))] -#[inline] -pub(crate) fn fcntl_lock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::Result<()> { - use c::{flock, F_RDLCK, F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, SEEK_SET}; - - let (cmd, l_type) = match operation { - FlockOperation::LockShared => (F_SETLKW, F_RDLCK), - FlockOperation::LockExclusive => (F_SETLKW, F_WRLCK), - FlockOperation::Unlock => (F_SETLKW, F_UNLCK), - FlockOperation::NonBlockingLockShared => (F_SETLK, F_RDLCK), - FlockOperation::NonBlockingLockExclusive => (F_SETLK, F_WRLCK), - FlockOperation::NonBlockingUnlock => (F_SETLK, F_UNLCK), - }; - - unsafe { - let mut lock: flock = core::mem::zeroed(); - lock.l_type = l_type as _; - - // When `l_len` is zero, this locks all the bytes from - // `l_whence`/`l_start` to the end of the file, even as the - // file grows dynamically. - lock.l_whence = SEEK_SET as _; - lock.l_start = 0; - lock.l_len = 0; - - ret(c::fcntl(borrowed_fd(fd), cmd, &lock)) - } -} - -pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result<u64> { - let (whence, offset) = match pos { - SeekFrom::Start(pos) => { - let pos: u64 = pos; - // Silently cast; we'll get `EINVAL` if the value is negative. - (c::SEEK_SET, pos as i64) - } - SeekFrom::End(offset) => (c::SEEK_END, offset), - SeekFrom::Current(offset) => (c::SEEK_CUR, offset), - #[cfg(any(apple, freebsdlike, linux_kernel, solarish))] - SeekFrom::Data(offset) => (c::SEEK_DATA, offset), - #[cfg(any(apple, freebsdlike, linux_kernel, solarish))] - SeekFrom::Hole(offset) => (c::SEEK_HOLE, offset), - }; - - // ESP-IDF and Vita don't support 64-bit offsets. - #[cfg(any(target_os = "espidf", target_os = "vita"))] - let offset: i32 = offset.try_into().map_err(|_| io::Errno::OVERFLOW)?; - - let offset = unsafe { ret_off_t(c::lseek(borrowed_fd(fd), offset, whence))? }; - Ok(offset as u64) -} - -pub(crate) fn tell(fd: BorrowedFd<'_>) -> io::Result<u64> { - let offset = unsafe { ret_off_t(c::lseek(borrowed_fd(fd), 0, c::SEEK_CUR))? }; - Ok(offset as u64) -} - -#[cfg(not(any(linux_kernel, target_os = "wasi")))] -pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> { - unsafe { ret(c::fchmod(borrowed_fd(fd), bitflags_bits!(mode))) } -} - -#[cfg(linux_kernel)] -pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> { - // Use `c::syscall` rather than `c::fchmod` because some libc - // implementations, such as musl, add extra logic to `fchmod` to emulate - // support for `O_PATH`, which uses `/proc` outside our control and - // interferes with our own use of `O_PATH`. - syscall! { - fn fchmod( - fd: c::c_int, - mode: c::mode_t - ) via SYS_fchmod -> c::c_int - } - unsafe { ret(fchmod(borrowed_fd(fd), mode.bits() as c::mode_t)) } -} - -#[cfg(not(target_os = "wasi"))] -pub(crate) fn chown(path: &CStr, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> { - unsafe { - let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); - ret(c::chown(c_str(path), ow, gr)) - } -} - -#[cfg(linux_kernel)] -pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> { - // Use `c::syscall` rather than `c::fchown` because some libc - // implementations, such as musl, add extra logic to `fchown` to emulate - // support for `O_PATH`, which uses `/proc` outside our control and - // interferes with our own use of `O_PATH`. - syscall! { - fn fchown( - fd: c::c_int, - owner: c::uid_t, - group: c::gid_t - ) via SYS_fchown -> c::c_int - } - unsafe { - let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); - ret(fchown(borrowed_fd(fd), ow, gr)) - } -} - -#[cfg(not(any(linux_kernel, target_os = "wasi")))] -pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> { - unsafe { - let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); - ret(c::fchown(borrowed_fd(fd), ow, gr)) - } -} - -#[cfg(not(any( - target_os = "espidf", - target_os = "solaris", - target_os = "vita", - target_os = "wasi" -)))] -pub(crate) fn flock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::Result<()> { - unsafe { ret(c::flock(borrowed_fd(fd), operation as c::c_int)) } -} - -#[cfg(linux_kernel)] -pub(crate) fn syncfs(fd: BorrowedFd<'_>) -> io::Result<()> { - // Some versions of Android libc lack a `syncfs` function. - #[cfg(target_os = "android")] - syscall! { - fn syncfs(fd: c::c_int) via SYS_syncfs -> c::c_int - } - - // `syncfs` was added to glibc in 2.20. - #[cfg(not(target_os = "android"))] - weak_or_syscall! { - fn syncfs(fd: c::c_int) via SYS_syncfs -> c::c_int - } - - unsafe { ret(syncfs(borrowed_fd(fd))) } -} - -#[cfg(not(any( - target_os = "espidf", - target_os = "redox", - target_os = "vita", - target_os = "wasi" -)))] -pub(crate) fn sync() { - unsafe { c::sync() } -} - -pub(crate) fn fstat(fd: BorrowedFd<'_>) -> io::Result<Stat> { - // 32-bit and mips64 Linux: `struct stat64` is not y2038 compatible; use - // `statx`. - // - // And, some old platforms don't support `statx`, and some fail with a - // confusing error code, so we call `crate::fs::statx` to handle that. If - // `statx` isn't available, fall back to the buggy system call. - #[cfg(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) - ))] - { - match crate::fs::statx(fd, cstr!(""), AtFlags::EMPTY_PATH, StatxFlags::BASIC_STATS) { - Ok(x) => statx_to_stat(x), - Err(io::Errno::NOSYS) => fstat_old(fd), - Err(err) => Err(err), - } - } - - // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and - // there's nothing practical we can do. - #[cfg(not(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) - )))] - unsafe { - let mut stat = MaybeUninit::<Stat>::uninit(); - ret(c::fstat(borrowed_fd(fd), stat.as_mut_ptr()))?; - Ok(stat.assume_init()) - } -} - -#[cfg(all( - linux_kernel, - any( - target_pointer_width = "32", - target_arch = "mips64", - target_arch = "mips64r6" - ) -))] -fn fstat_old(fd: BorrowedFd<'_>) -> io::Result<Stat> { - unsafe { - let mut result = MaybeUninit::<c::stat64>::uninit(); - ret(c::fstat(borrowed_fd(fd), result.as_mut_ptr()))?; - stat64_to_stat(result.assume_init()) - } -} - -#[cfg(not(any( - solarish, - target_os = "espidf", - target_os = "haiku", - target_os = "netbsd", - target_os = "nto", - target_os = "redox", - target_os = "vita", - target_os = "wasi", -)))] -pub(crate) fn fstatfs(fd: BorrowedFd<'_>) -> io::Result<StatFs> { - let mut statfs = MaybeUninit::<StatFs>::uninit(); - unsafe { - ret(c::fstatfs(borrowed_fd(fd), statfs.as_mut_ptr()))?; - Ok(statfs.assume_init()) - } -} - -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -pub(crate) fn fstatvfs(fd: BorrowedFd<'_>) -> io::Result<StatVfs> { - let mut statvfs = MaybeUninit::<c::statvfs>::uninit(); - unsafe { - ret(c::fstatvfs(borrowed_fd(fd), statvfs.as_mut_ptr()))?; - Ok(libc_statvfs_to_statvfs(statvfs.assume_init())) - } -} - -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -fn libc_statvfs_to_statvfs(from: c::statvfs) -> StatVfs { - StatVfs { - f_bsize: from.f_bsize as u64, - f_frsize: from.f_frsize as u64, - f_blocks: from.f_blocks as u64, - f_bfree: from.f_bfree as u64, - f_bavail: from.f_bavail as u64, - f_files: from.f_files as u64, - f_ffree: from.f_ffree as u64, - f_favail: from.f_ffree as u64, - #[cfg(not(target_os = "aix"))] - f_fsid: from.f_fsid as u64, - #[cfg(target_os = "aix")] - f_fsid: ((from.f_fsid.val[0] as u64) << 32) | from.f_fsid.val[1], - f_flag: StatVfsMountFlags::from_bits_retain(from.f_flag as u64), - f_namemax: from.f_namemax as u64, - } -} - -#[cfg(not(any(target_os = "espidf", target_os = "vita")))] -pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> { - // Old 32-bit version: libc has `futimens` but it is not y2038 safe by - // default. But there may be a `__futimens64` we can use. - #[cfg(fix_y2038)] - { - #[cfg(target_env = "gnu")] - if let Some(libc_futimens) = __futimens64.get() { - let libc_times: [LibcTimespec; 2] = [ - times.last_access.clone().into(), - times.last_modification.clone().into(), - ]; - - unsafe { - return ret(libc_futimens(borrowed_fd(fd), libc_times.as_ptr())); - } - } - - futimens_old(fd, times) - } - - // Main version: libc is y2038 safe and has `futimens`. Or, the platform - // is not y2038 safe and there's nothing practical we can do. - #[cfg(not(any(apple, fix_y2038)))] - unsafe { - use crate::utils::as_ptr; - - ret(c::futimens(borrowed_fd(fd), as_ptr(times).cast())) - } - - // Apple version: `futimens` was introduced in macOS 10.13. - #[cfg(apple)] - unsafe { - use crate::utils::as_ptr; - - // ABI details. - weak! { - fn futimens(c::c_int, *const c::timespec) -> c::c_int - } - extern "C" { - fn fsetattrlist( - fd: c::c_int, - attr_list: *const Attrlist, - attr_buf: *const c::c_void, - attr_buf_size: c::size_t, - options: c::c_ulong, - ) -> c::c_int; - } - - // If we have `futimens`, use it. - if let Some(have_futimens) = futimens.get() { - return ret(have_futimens(borrowed_fd(fd), as_ptr(times).cast())); - } - - // Otherwise use `fsetattrlist`. - let (attrbuf_size, times, attrs) = times_to_attrlist(times); - - ret(fsetattrlist( - borrowed_fd(fd), - &attrs, - as_ptr(×).cast(), - attrbuf_size, - 0, - )) - } -} - -#[cfg(fix_y2038)] -fn futimens_old(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> { - let old_times = [ - c::timespec { - tv_sec: times - .last_access - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: times - .last_access - .tv_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - }, - c::timespec { - tv_sec: times - .last_modification - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: times - .last_modification - .tv_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - }, - ]; - - unsafe { ret(c::futimens(borrowed_fd(fd), old_times.as_ptr())) } -} - -#[cfg(not(any( - apple, - netbsdlike, - solarish, - target_os = "aix", - target_os = "dragonfly", - target_os = "espidf", - target_os = "nto", - target_os = "redox", - target_os = "vita", -)))] -pub(crate) fn fallocate( - fd: BorrowedFd<'_>, - mode: FallocateFlags, - offset: u64, - len: u64, -) -> io::Result<()> { - // Silently cast; we'll get `EINVAL` if the value is negative. - let offset = offset as i64; - let len = len as i64; - - #[cfg(any(linux_kernel, target_os = "fuchsia"))] - unsafe { - ret(c::fallocate( - borrowed_fd(fd), - bitflags_bits!(mode), - offset, - len, - )) - } - - #[cfg(not(any(linux_kernel, target_os = "fuchsia")))] - { - assert!(mode.is_empty()); - let err = unsafe { c::posix_fallocate(borrowed_fd(fd), offset, len) }; - - // `posix_fallocate` returns its error status rather than using - // `errno`. - if err == 0 { - Ok(()) - } else { - Err(io::Errno(err)) - } - } -} - -#[cfg(apple)] -pub(crate) fn fallocate( - fd: BorrowedFd<'_>, - mode: FallocateFlags, - offset: u64, - len: u64, -) -> io::Result<()> { - let offset: i64 = offset.try_into().map_err(|_e| io::Errno::INVAL)?; - let len = len as i64; - - assert!(mode.is_empty()); - - let new_len = offset.checked_add(len).ok_or(io::Errno::FBIG)?; - let mut store = c::fstore_t { - fst_flags: c::F_ALLOCATECONTIG, - fst_posmode: c::F_PEOFPOSMODE, - fst_offset: 0, - fst_length: new_len, - fst_bytesalloc: 0, - }; - unsafe { - if c::fcntl(borrowed_fd(fd), c::F_PREALLOCATE, &store) == -1 { - // Unable to allocate contiguous disk space; attempt to allocate - // non-contiguously. - store.fst_flags = c::F_ALLOCATEALL; - let _ = ret_c_int(c::fcntl(borrowed_fd(fd), c::F_PREALLOCATE, &store))?; - } - ret(c::ftruncate(borrowed_fd(fd), new_len)) - } -} - -pub(crate) fn fsync(fd: BorrowedFd<'_>) -> io::Result<()> { - unsafe { ret(c::fsync(borrowed_fd(fd))) } -} - -#[cfg(not(any( - apple, - target_os = "dragonfly", - target_os = "espidf", - target_os = "haiku", - target_os = "redox", - target_os = "vita", -)))] -pub(crate) fn fdatasync(fd: BorrowedFd<'_>) -> io::Result<()> { - unsafe { ret(c::fdatasync(borrowed_fd(fd))) } -} - -pub(crate) fn ftruncate(fd: BorrowedFd<'_>, length: u64) -> io::Result<()> { - let length = length.try_into().map_err(|_overflow_err| io::Errno::FBIG)?; - unsafe { ret(c::ftruncate(borrowed_fd(fd), length)) } -} - -#[cfg(any(linux_kernel, target_os = "freebsd"))] -pub(crate) fn memfd_create(name: &CStr, flags: MemfdFlags) -> io::Result<OwnedFd> { - #[cfg(target_os = "freebsd")] - weakcall! { - fn memfd_create( - name: *const c::c_char, - flags: c::c_uint - ) -> c::c_int - } - - #[cfg(linux_kernel)] - weak_or_syscall! { - fn memfd_create( - name: *const c::c_char, - flags: c::c_uint - ) via SYS_memfd_create -> c::c_int - } - - unsafe { ret_owned_fd(memfd_create(c_str(name), bitflags_bits!(flags))) } -} - -#[cfg(linux_kernel)] -pub(crate) fn openat2( - dirfd: BorrowedFd<'_>, - path: &CStr, - oflags: OFlags, - mode: Mode, - resolve: ResolveFlags, -) -> io::Result<OwnedFd> { - use linux_raw_sys::general::open_how; - - syscall! { - fn openat2( - base_dirfd: c::c_int, - pathname: *const c::c_char, - how: *mut open_how, - size: usize - ) via SYS_OPENAT2 -> c::c_int - } - - let oflags = oflags.bits(); - let mut open_how = open_how { - flags: u64::from(oflags), - mode: u64::from(mode.bits()), - resolve: resolve.bits(), - }; - - unsafe { - ret_owned_fd(openat2( - borrowed_fd(dirfd), - c_str(path), - &mut open_how, - size_of::<open_how>(), - )) - } -} -#[cfg(all(linux_kernel, target_pointer_width = "32"))] -const SYS_OPENAT2: i32 = 437; -#[cfg(all(linux_kernel, target_pointer_width = "64"))] -const SYS_OPENAT2: i64 = 437; - -#[cfg(target_os = "linux")] -pub(crate) fn sendfile( - out_fd: BorrowedFd<'_>, - in_fd: BorrowedFd<'_>, - offset: Option<&mut u64>, - count: usize, -) -> io::Result<usize> { - unsafe { - ret_usize(c::sendfile64( - borrowed_fd(out_fd), - borrowed_fd(in_fd), - offset.map_or(null_mut(), crate::utils::as_mut_ptr).cast(), - count, - )) - } -} - -/// Convert from a Linux `statx` value to rustix's `Stat`. -#[cfg(all(linux_kernel, target_pointer_width = "32"))] -fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> { - Ok(Stat { - st_dev: crate::fs::makedev(x.stx_dev_major, x.stx_dev_minor).into(), - st_mode: x.stx_mode.into(), - st_nlink: x.stx_nlink.into(), - st_uid: x.stx_uid.into(), - st_gid: x.stx_gid.into(), - st_rdev: crate::fs::makedev(x.stx_rdev_major, x.stx_rdev_minor).into(), - st_size: x.stx_size.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_blksize: x.stx_blksize.into(), - st_blocks: x.stx_blocks.into(), - st_atime: x - .stx_atime - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - st_atime_nsec: x.stx_atime.tv_nsec as _, - st_mtime: x - .stx_mtime - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - st_mtime_nsec: x.stx_mtime.tv_nsec as _, - st_ctime: x - .stx_ctime - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - st_ctime_nsec: x.stx_ctime.tv_nsec as _, - st_ino: x.stx_ino.into(), - }) -} - -/// Convert from a Linux `statx` value to rustix's `Stat`. -/// -/// mips64' `struct stat64` in libc has private fields, and `stx_blocks` -#[cfg(all(linux_kernel, any(target_arch = "mips64", target_arch = "mips64r6")))] -fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> { - let mut result: Stat = unsafe { core::mem::zeroed() }; - - result.st_dev = crate::fs::makedev(x.stx_dev_major, x.stx_dev_minor); - result.st_mode = x.stx_mode.into(); - result.st_nlink = x.stx_nlink.into(); - result.st_uid = x.stx_uid.into(); - result.st_gid = x.stx_gid.into(); - result.st_rdev = crate::fs::makedev(x.stx_rdev_major, x.stx_rdev_minor); - result.st_size = x.stx_size.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_blksize = x.stx_blksize.into(); - result.st_blocks = x.stx_blocks.try_into().map_err(|_e| io::Errno::OVERFLOW)?; - result.st_atime = x - .stx_atime - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?; - result.st_atime_nsec = x.stx_atime.tv_nsec as _; - result.st_mtime = x - .stx_mtime - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?; - result.st_mtime_nsec = x.stx_mtime.tv_nsec as _; - result.st_ctime = x - .stx_ctime - .tv_sec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?; - result.st_ctime_nsec = x.stx_ctime.tv_nsec as _; - result.st_ino = x.stx_ino.into(); - - Ok(result) -} - -/// Convert from a Linux `stat64` value to rustix's `Stat`. -#[cfg(all(linux_kernel, target_pointer_width = "32"))] -fn stat64_to_stat(s64: c::stat64) -> io::Result<Stat> { - Ok(Stat { - st_dev: s64.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_mode: s64.st_mode.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_nlink: s64.st_nlink.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_uid: s64.st_uid.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_gid: s64.st_gid.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_rdev: s64.st_rdev.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_size: s64.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_blksize: s64.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_blocks: s64.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_atime: s64.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_atime_nsec: s64 - .st_atime_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - st_mtime: s64.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_mtime_nsec: s64 - .st_mtime_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - st_ctime: s64.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?, - st_ctime_nsec: s64 - .st_ctime_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - st_ino: s64.st_ino.try_into().map_err(|_| io::Errno::OVERFLOW)?, - }) -} - -/// Convert from a Linux `stat64` value to rustix's `Stat`. -/// -/// mips64' `struct stat64` in libc has private fields, and `st_blocks` has -/// type `i64`. -#[cfg(all(linux_kernel, any(target_arch = "mips64", target_arch = "mips64r6")))] -fn stat64_to_stat(s64: c::stat64) -> io::Result<Stat> { - let mut result: Stat = unsafe { core::mem::zeroed() }; - - result.st_dev = s64.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_mode = s64.st_mode.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_nlink = s64.st_nlink.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_uid = s64.st_uid.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_gid = s64.st_gid.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_rdev = s64.st_rdev.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_size = s64.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_blksize = s64.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_blocks = s64.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_atime = s64.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_atime_nsec = s64 - .st_atime_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?; - result.st_mtime = s64.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_mtime_nsec = s64 - .st_mtime_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?; - result.st_ctime = s64.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?; - result.st_ctime_nsec = s64 - .st_ctime_nsec - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?; - result.st_ino = s64.st_ino.try_into().map_err(|_| io::Errno::OVERFLOW)?; - - Ok(result) -} - -#[cfg(linux_kernel)] -#[allow(non_upper_case_globals)] -mod sys { - use super::{c, BorrowedFd, Statx}; - - weak_or_syscall! { - pub(super) fn statx( - dirfd_: BorrowedFd<'_>, - path: *const c::c_char, - flags: c::c_int, - mask: c::c_uint, - buf: *mut Statx - ) via SYS_statx -> c::c_int - } -} - -#[cfg(linux_kernel)] -#[allow(non_upper_case_globals)] -pub(crate) fn statx( - dirfd: BorrowedFd<'_>, - path: &CStr, - flags: AtFlags, - mask: StatxFlags, -) -> io::Result<Statx> { - // If a future Linux kernel adds more fields to `struct statx` and users - // passing flags unknown to rustix in `StatxFlags`, we could end up - // writing outside of the buffer. To prevent this possibility, we mask off - // any flags that we don't know about. - // - // This includes `STATX__RESERVED`, which has a value that we know, but - // which could take on arbitrary new meaning in the future. Linux currently - // rejects this flag with `EINVAL`, so we do the same. - // - // This doesn't rely on `STATX_ALL` because [it's deprecated] and already - // doesn't represent all the known flags. - // - // [it's deprecated]: https://patchwork.kernel.org/project/linux-fsdevel/patch/20200505095915.11275-7-mszeredi@redhat.com/ - #[cfg(not(any(target_os = "android", target_env = "musl")))] - const STATX__RESERVED: u32 = c::STATX__RESERVED as u32; - #[cfg(any(target_os = "android", target_env = "musl"))] - const STATX__RESERVED: u32 = linux_raw_sys::general::STATX__RESERVED; - if (mask.bits() & STATX__RESERVED) == STATX__RESERVED { - return Err(io::Errno::INVAL); - } - let mask = mask & StatxFlags::all(); - - let mut statx_buf = MaybeUninit::<Statx>::uninit(); - unsafe { - ret(sys::statx( - dirfd, - c_str(path), - bitflags_bits!(flags), - mask.bits(), - statx_buf.as_mut_ptr(), - ))?; - Ok(statx_buf.assume_init()) - } -} - -#[cfg(linux_kernel)] -#[inline] -pub(crate) fn is_statx_available() -> bool { - unsafe { - // Call `statx` with null pointers so that if it fails for any reason - // other than `EFAULT`, we know it's not supported. - matches!( - ret(sys::statx(CWD, null(), 0, 0, null_mut())), - Err(io::Errno::FAULT) - ) - } -} - -#[cfg(apple)] -pub(crate) unsafe fn fcopyfile( - from: BorrowedFd<'_>, - to: BorrowedFd<'_>, - state: copyfile_state_t, - flags: CopyfileFlags, -) -> io::Result<()> { - extern "C" { - fn fcopyfile( - from: c::c_int, - to: c::c_int, - state: copyfile_state_t, - flags: c::c_uint, - ) -> c::c_int; - } - - nonnegative_ret(fcopyfile( - borrowed_fd(from), - borrowed_fd(to), - state, - bitflags_bits!(flags), - )) -} - -#[cfg(apple)] -pub(crate) fn copyfile_state_alloc() -> io::Result<copyfile_state_t> { - extern "C" { - fn copyfile_state_alloc() -> copyfile_state_t; - } - - let result = unsafe { copyfile_state_alloc() }; - if result.0.is_null() { - Err(io::Errno::last_os_error()) - } else { - Ok(result) - } -} - -#[cfg(apple)] -pub(crate) unsafe fn copyfile_state_free(state: copyfile_state_t) -> io::Result<()> { - extern "C" { - fn copyfile_state_free(state: copyfile_state_t) -> c::c_int; - } - - nonnegative_ret(copyfile_state_free(state)) -} - -#[cfg(apple)] -const COPYFILE_STATE_COPIED: u32 = 8; - -#[cfg(apple)] -pub(crate) unsafe fn copyfile_state_get_copied(state: copyfile_state_t) -> io::Result<u64> { - let mut copied = MaybeUninit::<u64>::uninit(); - copyfile_state_get(state, COPYFILE_STATE_COPIED, copied.as_mut_ptr().cast())?; - Ok(copied.assume_init()) -} - -#[cfg(apple)] -pub(crate) unsafe fn copyfile_state_get( - state: copyfile_state_t, - flag: u32, - dst: *mut c::c_void, -) -> io::Result<()> { - extern "C" { - fn copyfile_state_get(state: copyfile_state_t, flag: u32, dst: *mut c::c_void) -> c::c_int; - } - - nonnegative_ret(copyfile_state_get(state, flag, dst)) -} - -#[cfg(all(apple, feature = "alloc"))] -pub(crate) fn getpath(fd: BorrowedFd<'_>) -> io::Result<CString> { - // The use of `PATH_MAX` is generally not encouraged, but it - // is inevitable in this case because macOS defines `fcntl` with - // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no - // alternatives. If a better method is invented, it should be used - // instead. - let mut buf = vec![0; c::PATH_MAX as usize]; - - // From the [macOS `fcntl` manual page]: - // `F_GETPATH` - Get the path of the file descriptor `Fildes`. The argument - // must be a buffer of size `MAXPATHLEN` or greater. - // - // [macOS `fcntl` manual page]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html - unsafe { - ret(c::fcntl(borrowed_fd(fd), c::F_GETPATH, buf.as_mut_ptr()))?; - } - - let l = buf.iter().position(|&c| c == 0).unwrap(); - buf.truncate(l); - buf.shrink_to_fit(); - - Ok(CString::new(buf).unwrap()) -} - -#[cfg(apple)] -pub(crate) fn fcntl_rdadvise(fd: BorrowedFd<'_>, offset: u64, len: u64) -> io::Result<()> { - // From the [macOS `fcntl` manual page]: - // `F_RDADVISE` - Issue an advisory read async with no copy to user. - // - // The `F_RDADVISE` command operates on the following structure which holds - // information passed from the user to the system: - // - // ```c - // struct radvisory { - // off_t ra_offset; /* offset into the file */ - // int ra_count; /* size of the read */ - // }; - // ``` - // - // [macOS `fcntl` manual page]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html - let ra_offset = match offset.try_into() { - Ok(len) => len, - // If this conversion fails, the user is providing an offset outside - // any possible file extent, so just ignore it. - Err(_) => return Ok(()), - }; - let ra_count = match len.try_into() { - Ok(len) => len, - // If this conversion fails, the user is providing a dubiously large - // hint which is unlikely to improve performance. - Err(_) => return Ok(()), - }; - unsafe { - let radvisory = c::radvisory { - ra_offset, - ra_count, - }; - ret(c::fcntl(borrowed_fd(fd), c::F_RDADVISE, &radvisory)) - } -} - -#[cfg(apple)] -pub(crate) fn fcntl_fullfsync(fd: BorrowedFd<'_>) -> io::Result<()> { - unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_FULLFSYNC)) } -} - -#[cfg(apple)] -pub(crate) fn fcntl_nocache(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> { - unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_NOCACHE, value as c::c_int)) } -} - -#[cfg(apple)] -pub(crate) fn fcntl_global_nocache(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> { - unsafe { - ret(c::fcntl( - borrowed_fd(fd), - c::F_GLOBAL_NOCACHE, - value as c::c_int, - )) - } -} - -/// Convert `times` from a `futimens`/`utimensat` argument into `setattrlist` -/// arguments. -#[cfg(apple)] -fn times_to_attrlist(times: &Timestamps) -> (c::size_t, [c::timespec; 2], Attrlist) { - // ABI details. - const ATTR_CMN_MODTIME: u32 = 0x0000_0400; - const ATTR_CMN_ACCTIME: u32 = 0x0000_1000; - const ATTR_BIT_MAP_COUNT: u16 = 5; - - let mut times = times.clone(); - - // If we have any `UTIME_NOW` elements, replace them with the current time. - if times.last_access.tv_nsec == c::UTIME_NOW || times.last_modification.tv_nsec == c::UTIME_NOW - { - let now = { - let mut tv = c::timeval { - tv_sec: 0, - tv_usec: 0, - }; - unsafe { - let r = c::gettimeofday(&mut tv, null_mut()); - assert_eq!(r, 0); - } - c::timespec { - tv_sec: tv.tv_sec, - tv_nsec: (tv.tv_usec * 1000) as _, - } - }; - if times.last_access.tv_nsec == c::UTIME_NOW { - times.last_access = now; - } - if times.last_modification.tv_nsec == c::UTIME_NOW { - times.last_modification = now; - } - } - - // Pack the return values following the rules for [`getattrlist`]. - // - // [`getattrlist`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getattrlist.2.html - let mut times_size = 0; - let mut attrs = Attrlist { - bitmapcount: ATTR_BIT_MAP_COUNT, - reserved: 0, - commonattr: 0, - volattr: 0, - dirattr: 0, - fileattr: 0, - forkattr: 0, - }; - let mut return_times = [c::timespec { - tv_sec: 0, - tv_nsec: 0, - }; 2]; - let mut times_index = 0; - if times.last_modification.tv_nsec != c::UTIME_OMIT { - attrs.commonattr |= ATTR_CMN_MODTIME; - return_times[times_index] = times.last_modification; - times_index += 1; - times_size += size_of::<c::timespec>(); - } - if times.last_access.tv_nsec != c::UTIME_OMIT { - attrs.commonattr |= ATTR_CMN_ACCTIME; - return_times[times_index] = times.last_access; - times_size += size_of::<c::timespec>(); - } - - (times_size, return_times, attrs) -} - -/// Support type for `Attrlist`. -#[cfg(apple)] -type Attrgroup = u32; - -/// Attribute list for use with `setattrlist`. -#[cfg(apple)] -#[repr(C)] -struct Attrlist { - bitmapcount: u16, - reserved: u16, - commonattr: Attrgroup, - volattr: Attrgroup, - dirattr: Attrgroup, - fileattr: Attrgroup, - forkattr: Attrgroup, -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn getxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result<usize> { - let value_ptr = value.as_mut_ptr(); - - #[cfg(not(apple))] - unsafe { - ret_usize(c::getxattr( - path.as_ptr(), - name.as_ptr(), - value_ptr.cast::<c::c_void>(), - value.len(), - )) - } - - #[cfg(apple)] - unsafe { - ret_usize(c::getxattr( - path.as_ptr(), - name.as_ptr(), - value_ptr.cast::<c::c_void>(), - value.len(), - 0, - 0, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn lgetxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result<usize> { - let value_ptr = value.as_mut_ptr(); - - #[cfg(not(apple))] - unsafe { - ret_usize(c::lgetxattr( - path.as_ptr(), - name.as_ptr(), - value_ptr.cast::<c::c_void>(), - value.len(), - )) - } - - #[cfg(apple)] - unsafe { - ret_usize(c::getxattr( - path.as_ptr(), - name.as_ptr(), - value_ptr.cast::<c::c_void>(), - value.len(), - 0, - c::XATTR_NOFOLLOW, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn fgetxattr(fd: BorrowedFd<'_>, name: &CStr, value: &mut [u8]) -> io::Result<usize> { - let value_ptr = value.as_mut_ptr(); - - #[cfg(not(apple))] - unsafe { - ret_usize(c::fgetxattr( - borrowed_fd(fd), - name.as_ptr(), - value_ptr.cast::<c::c_void>(), - value.len(), - )) - } - - #[cfg(apple)] - unsafe { - ret_usize(c::fgetxattr( - borrowed_fd(fd), - name.as_ptr(), - value_ptr.cast::<c::c_void>(), - value.len(), - 0, - 0, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn setxattr( - path: &CStr, - name: &CStr, - value: &[u8], - flags: XattrFlags, -) -> io::Result<()> { - #[cfg(not(apple))] - unsafe { - ret(c::setxattr( - path.as_ptr(), - name.as_ptr(), - value.as_ptr().cast::<c::c_void>(), - value.len(), - flags.bits() as i32, - )) - } - - #[cfg(apple)] - unsafe { - ret(c::setxattr( - path.as_ptr(), - name.as_ptr(), - value.as_ptr().cast::<c::c_void>(), - value.len(), - 0, - flags.bits() as i32, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn lsetxattr( - path: &CStr, - name: &CStr, - value: &[u8], - flags: XattrFlags, -) -> io::Result<()> { - #[cfg(not(apple))] - unsafe { - ret(c::lsetxattr( - path.as_ptr(), - name.as_ptr(), - value.as_ptr().cast::<c::c_void>(), - value.len(), - flags.bits() as i32, - )) - } - - #[cfg(apple)] - unsafe { - ret(c::setxattr( - path.as_ptr(), - name.as_ptr(), - value.as_ptr().cast::<c::c_void>(), - value.len(), - 0, - flags.bits() as i32 | c::XATTR_NOFOLLOW, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn fsetxattr( - fd: BorrowedFd<'_>, - name: &CStr, - value: &[u8], - flags: XattrFlags, -) -> io::Result<()> { - #[cfg(not(apple))] - unsafe { - ret(c::fsetxattr( - borrowed_fd(fd), - name.as_ptr(), - value.as_ptr().cast::<c::c_void>(), - value.len(), - flags.bits() as i32, - )) - } - - #[cfg(apple)] - unsafe { - ret(c::fsetxattr( - borrowed_fd(fd), - name.as_ptr(), - value.as_ptr().cast::<c::c_void>(), - value.len(), - 0, - flags.bits() as i32, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn listxattr(path: &CStr, list: &mut [c::c_char]) -> io::Result<usize> { - #[cfg(not(apple))] - unsafe { - ret_usize(c::listxattr(path.as_ptr(), list.as_mut_ptr(), list.len())) - } - - #[cfg(apple)] - unsafe { - ret_usize(c::listxattr( - path.as_ptr(), - list.as_mut_ptr(), - list.len(), - 0, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn llistxattr(path: &CStr, list: &mut [c::c_char]) -> io::Result<usize> { - #[cfg(not(apple))] - unsafe { - ret_usize(c::llistxattr(path.as_ptr(), list.as_mut_ptr(), list.len())) - } - - #[cfg(apple)] - unsafe { - ret_usize(c::listxattr( - path.as_ptr(), - list.as_mut_ptr(), - list.len(), - c::XATTR_NOFOLLOW, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn flistxattr(fd: BorrowedFd<'_>, list: &mut [c::c_char]) -> io::Result<usize> { - let fd = borrowed_fd(fd); - - #[cfg(not(apple))] - unsafe { - ret_usize(c::flistxattr(fd, list.as_mut_ptr(), list.len())) - } - - #[cfg(apple)] - unsafe { - ret_usize(c::flistxattr(fd, list.as_mut_ptr(), list.len(), 0)) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn removexattr(path: &CStr, name: &CStr) -> io::Result<()> { - #[cfg(not(apple))] - unsafe { - ret(c::removexattr(path.as_ptr(), name.as_ptr())) - } - - #[cfg(apple)] - unsafe { - ret(c::removexattr(path.as_ptr(), name.as_ptr(), 0)) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn lremovexattr(path: &CStr, name: &CStr) -> io::Result<()> { - #[cfg(not(apple))] - unsafe { - ret(c::lremovexattr(path.as_ptr(), name.as_ptr())) - } - - #[cfg(apple)] - unsafe { - ret(c::removexattr( - path.as_ptr(), - name.as_ptr(), - c::XATTR_NOFOLLOW, - )) - } -} - -#[cfg(any(apple, linux_kernel))] -pub(crate) fn fremovexattr(fd: BorrowedFd<'_>, name: &CStr) -> io::Result<()> { - let fd = borrowed_fd(fd); - - #[cfg(not(apple))] - unsafe { - ret(c::fremovexattr(fd, name.as_ptr())) - } - - #[cfg(apple)] - unsafe { - ret(c::fremovexattr(fd, name.as_ptr(), 0)) - } -} - -#[test] -fn test_sizes() { - #[cfg(linux_kernel)] - assert_eq_size!(c::loff_t, u64); - - // Assert that `Timestamps` has the expected layout. If we're not fixing - // y2038, libc's type should match ours. If we are, it's smaller. - #[cfg(not(fix_y2038))] - assert_eq_size!([c::timespec; 2], Timestamps); - #[cfg(fix_y2038)] - assert!(core::mem::size_of::<[c::timespec; 2]>() < core::mem::size_of::<Timestamps>()); -} diff --git a/vendor/rustix/src/backend/libc/fs/types.rs b/vendor/rustix/src/backend/libc/fs/types.rs deleted file mode 100644 index 19508c2..0000000 --- a/vendor/rustix/src/backend/libc/fs/types.rs +++ /dev/null @@ -1,1164 +0,0 @@ -use crate::backend::c; -use bitflags::bitflags; - -#[cfg(not(any(target_os = "espidf", target_os = "vita")))] -bitflags! { - /// `*_OK` constants for use with [`accessat`]. - /// - /// [`accessat`]: fn.accessat.html - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct Access: c::c_int { - /// `R_OK` - const READ_OK = c::R_OK; - - /// `W_OK` - const WRITE_OK = c::W_OK; - - /// `X_OK` - const EXEC_OK = c::X_OK; - - /// `F_OK` - const EXISTS = c::F_OK; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(not(any(target_os = "espidf", target_os = "redox")))] -bitflags! { - /// `AT_*` constants for use with [`openat`], [`statat`], and other `*at` - /// functions. - /// - /// [`openat`]: crate::fs::openat - /// [`statat`]: crate::fs::statat - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct AtFlags: u32 { - /// `AT_SYMLINK_NOFOLLOW` - const SYMLINK_NOFOLLOW = bitcast!(c::AT_SYMLINK_NOFOLLOW); - - /// `AT_EACCESS` - #[cfg(not(any(target_os = "emscripten", target_os = "android")))] - const EACCESS = bitcast!(c::AT_EACCESS); - - /// `AT_REMOVEDIR` - const REMOVEDIR = bitcast!(c::AT_REMOVEDIR); - - /// `AT_SYMLINK_FOLLOW` - const SYMLINK_FOLLOW = bitcast!(c::AT_SYMLINK_FOLLOW); - - /// `AT_NO_AUTOMOUNT` - #[cfg(any(linux_like, target_os = "fuchsia"))] - const NO_AUTOMOUNT = bitcast!(c::AT_NO_AUTOMOUNT); - - /// `AT_EMPTY_PATH` - #[cfg(any( - linux_kernel, - target_os = "freebsd", - target_os = "fuchsia", - ))] - const EMPTY_PATH = bitcast!(c::AT_EMPTY_PATH); - - /// `AT_RESOLVE_BENEATH` - #[cfg(target_os = "freebsd")] - const RESOLVE_BENEATH = bitcast!(c::AT_RESOLVE_BENEATH); - - /// `AT_STATX_SYNC_AS_STAT` - #[cfg(all(target_os = "linux", target_env = "gnu"))] - const STATX_SYNC_AS_STAT = bitcast!(c::AT_STATX_SYNC_AS_STAT); - - /// `AT_STATX_FORCE_SYNC` - #[cfg(all(target_os = "linux", target_env = "gnu"))] - const STATX_FORCE_SYNC = bitcast!(c::AT_STATX_FORCE_SYNC); - - /// `AT_STATX_DONT_SYNC` - #[cfg(all(target_os = "linux", target_env = "gnu"))] - const STATX_DONT_SYNC = bitcast!(c::AT_STATX_DONT_SYNC); - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -bitflags! { - /// `S_I*` constants for use with [`openat`], [`chmodat`], and [`fchmod`]. - /// - /// [`openat`]: crate::fs::openat - /// [`chmodat`]: crate::fs::chmodat - /// [`fchmod`]: crate::fs::fchmod - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct Mode: RawMode { - /// `S_IRWXU` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const RWXU = c::S_IRWXU as RawMode; - - /// `S_IRUSR` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const RUSR = c::S_IRUSR as RawMode; - - /// `S_IWUSR` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const WUSR = c::S_IWUSR as RawMode; - - /// `S_IXUSR` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const XUSR = c::S_IXUSR as RawMode; - - /// `S_IRWXG` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const RWXG = c::S_IRWXG as RawMode; - - /// `S_IRGRP` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const RGRP = c::S_IRGRP as RawMode; - - /// `S_IWGRP` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const WGRP = c::S_IWGRP as RawMode; - - /// `S_IXGRP` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const XGRP = c::S_IXGRP as RawMode; - - /// `S_IRWXO` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const RWXO = c::S_IRWXO as RawMode; - - /// `S_IROTH` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const ROTH = c::S_IROTH as RawMode; - - /// `S_IWOTH` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const WOTH = c::S_IWOTH as RawMode; - - /// `S_IXOTH` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const XOTH = c::S_IXOTH as RawMode; - - /// `S_ISUID` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const SUID = c::S_ISUID as RawMode; - - /// `S_ISGID` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const SGID = c::S_ISGID as RawMode; - - /// `S_ISVTX` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const SVTX = c::S_ISVTX as RawMode; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(not(target_os = "espidf"))] -impl Mode { - /// Construct a `Mode` from the mode bits of the `st_mode` field of a - /// `Mode`. - #[inline] - pub const fn from_raw_mode(st_mode: RawMode) -> Self { - Self::from_bits_truncate(st_mode) - } - - /// Construct an `st_mode` value from a `Mode`. - #[inline] - pub const fn as_raw_mode(self) -> RawMode { - self.bits() - } -} - -#[cfg(not(target_os = "espidf"))] -impl From<RawMode> for Mode { - /// Support conversions from raw mode values to `Mode`. - /// - /// ``` - /// use rustix::fs::{Mode, RawMode}; - /// assert_eq!(Mode::from(0o700), Mode::RWXU); - /// ``` - #[inline] - fn from(st_mode: RawMode) -> Self { - Self::from_raw_mode(st_mode) - } -} - -#[cfg(not(target_os = "espidf"))] -impl From<Mode> for RawMode { - /// Support conversions from `Mode` to raw mode values. - /// - /// ``` - /// use rustix::fs::{Mode, RawMode}; - /// assert_eq!(RawMode::from(Mode::RWXU), 0o700); - /// ``` - #[inline] - fn from(mode: Mode) -> Self { - mode.as_raw_mode() - } -} - -bitflags! { - /// `O_*` constants for use with [`openat`]. - /// - /// [`openat`]: crate::fs::openat - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct OFlags: u32 { - /// `O_ACCMODE` - const ACCMODE = bitcast!(c::O_ACCMODE); - - /// Similar to `ACCMODE`, but just includes the read/write flags, and - /// no other flags. - /// - /// On some platforms, `PATH` may be included in `ACCMODE`, when - /// sometimes we really just want the read/write bits. Caution is - /// indicated, as the presence of `PATH` may mean that the read/write - /// bits don't have their usual meaning. - const RWMODE = bitcast!(c::O_RDONLY | c::O_WRONLY | c::O_RDWR); - - /// `O_APPEND` - const APPEND = bitcast!(c::O_APPEND); - - /// `O_CREAT` - #[doc(alias = "CREAT")] - const CREATE = bitcast!(c::O_CREAT); - - /// `O_DIRECTORY` - #[cfg(not(target_os = "espidf"))] - const DIRECTORY = bitcast!(c::O_DIRECTORY); - - /// `O_DSYNC` - #[cfg(not(any(target_os = "dragonfly", target_os = "espidf", target_os = "l4re", target_os = "redox", target_os = "vita")))] - const DSYNC = bitcast!(c::O_DSYNC); - - /// `O_EXCL` - const EXCL = bitcast!(c::O_EXCL); - - /// `O_FSYNC` - #[cfg(any( - bsd, - all(target_os = "linux", not(target_env = "musl")), - ))] - const FSYNC = bitcast!(c::O_FSYNC); - - /// `O_NOFOLLOW` - #[cfg(not(target_os = "espidf"))] - const NOFOLLOW = bitcast!(c::O_NOFOLLOW); - - /// `O_NONBLOCK` - const NONBLOCK = bitcast!(c::O_NONBLOCK); - - /// `O_RDONLY` - const RDONLY = bitcast!(c::O_RDONLY); - - /// `O_WRONLY` - const WRONLY = bitcast!(c::O_WRONLY); - - /// `O_RDWR` - /// - /// This is not equal to `RDONLY | WRONLY`. It's a distinct flag. - const RDWR = bitcast!(c::O_RDWR); - - /// `O_NOCTTY` - #[cfg(not(any(target_os = "espidf", target_os = "l4re", target_os = "redox", target_os = "vita")))] - const NOCTTY = bitcast!(c::O_NOCTTY); - - /// `O_RSYNC` - #[cfg(any( - linux_kernel, - netbsdlike, - target_os = "emscripten", - target_os = "wasi", - ))] - const RSYNC = bitcast!(c::O_RSYNC); - - /// `O_SYNC` - #[cfg(not(any(target_os = "l4re", target_os = "redox")))] - const SYNC = bitcast!(c::O_SYNC); - - /// `O_TRUNC` - const TRUNC = bitcast!(c::O_TRUNC); - - /// `O_PATH` - #[cfg(any( - linux_kernel, - target_os = "emscripten", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "redox", - ))] - const PATH = bitcast!(c::O_PATH); - - /// `O_CLOEXEC` - const CLOEXEC = bitcast!(c::O_CLOEXEC); - - /// `O_TMPFILE` - #[cfg(any( - linux_kernel, - target_os = "emscripten", - target_os = "fuchsia", - ))] - const TMPFILE = bitcast!(c::O_TMPFILE); - - /// `O_NOATIME` - #[cfg(any( - linux_kernel, - target_os = "fuchsia", - ))] - const NOATIME = bitcast!(c::O_NOATIME); - - /// `O_DIRECT` - #[cfg(any( - linux_kernel, - target_os = "emscripten", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "netbsd", - ))] - const DIRECT = bitcast!(c::O_DIRECT); - - /// `O_RESOLVE_BENEATH` - #[cfg(target_os = "freebsd")] - const RESOLVE_BENEATH = bitcast!(c::O_RESOLVE_BENEATH); - - /// `O_EMPTY_PATH` - #[cfg(target_os = "freebsd")] - const EMPTY_PATH = bitcast!(c::O_EMPTY_PATH); - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(apple)] -bitflags! { - /// `CLONE_*` constants for use with [`fclonefileat`]. - /// - /// [`fclonefileat`]: crate::fs::fclonefileat - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct CloneFlags: u32 { - /// `CLONE_NOFOLLOW` - const NOFOLLOW = 1; - - /// `CLONE_NOOWNERCOPY` - const NOOWNERCOPY = 2; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(apple)] -mod copyfile { - pub(super) const ACL: u32 = 1 << 0; - pub(super) const STAT: u32 = 1 << 1; - pub(super) const XATTR: u32 = 1 << 2; - pub(super) const DATA: u32 = 1 << 3; - pub(super) const SECURITY: u32 = STAT | ACL; - pub(super) const METADATA: u32 = SECURITY | XATTR; - pub(super) const ALL: u32 = METADATA | DATA; -} - -#[cfg(apple)] -bitflags! { - /// `COPYFILE_*` constants for use with [`fcopyfile`]. - /// - /// [`fcopyfile`]: crate::fs::fcopyfile - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct CopyfileFlags: c::c_uint { - /// `COPYFILE_ACL` - const ACL = copyfile::ACL; - - /// `COPYFILE_STAT` - const STAT = copyfile::STAT; - - /// `COPYFILE_XATTR` - const XATTR = copyfile::XATTR; - - /// `COPYFILE_DATA` - const DATA = copyfile::DATA; - - /// `COPYFILE_SECURITY` - const SECURITY = copyfile::SECURITY; - - /// `COPYFILE_METADATA` - const METADATA = copyfile::METADATA; - - /// `COPYFILE_ALL` - const ALL = copyfile::ALL; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(linux_kernel)] -bitflags! { - /// `RESOLVE_*` constants for use with [`openat2`]. - /// - /// [`openat2`]: crate::fs::openat2 - #[repr(transparent)] - #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct ResolveFlags: u64 { - /// `RESOLVE_NO_XDEV` - const NO_XDEV = 0x01; - - /// `RESOLVE_NO_MAGICLINKS` - const NO_MAGICLINKS = 0x02; - - /// `RESOLVE_NO_SYMLINKS` - const NO_SYMLINKS = 0x04; - - /// `RESOLVE_BENEATH` - const BENEATH = 0x08; - - /// `RESOLVE_IN_ROOT` - const IN_ROOT = 0x10; - - /// `RESOLVE_CACHED` (since Linux 5.12) - const CACHED = 0x20; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(linux_kernel)] -bitflags! { - /// `RENAME_*` constants for use with [`renameat_with`]. - /// - /// [`renameat_with`]: crate::fs::renameat_with - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct RenameFlags: c::c_uint { - /// `RENAME_EXCHANGE` - const EXCHANGE = bitcast!(c::RENAME_EXCHANGE); - - /// `RENAME_NOREPLACE` - const NOREPLACE = bitcast!(c::RENAME_NOREPLACE); - - /// `RENAME_WHITEOUT` - const WHITEOUT = bitcast!(c::RENAME_WHITEOUT); - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -/// `S_IF*` constants for use with [`mknodat`] and [`Stat`]'s `st_mode` field. -/// -/// [`mknodat`]: crate::fs::mknodat -/// [`Stat`]: crate::fs::Stat -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum FileType { - /// `S_IFREG` - RegularFile = c::S_IFREG as isize, - - /// `S_IFDIR` - Directory = c::S_IFDIR as isize, - - /// `S_IFLNK` - Symlink = c::S_IFLNK as isize, - - /// `S_IFIFO` - #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`. - #[doc(alias = "IFO")] - Fifo = c::S_IFIFO as isize, - - /// `S_IFSOCK` - #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`. - Socket = c::S_IFSOCK as isize, - - /// `S_IFCHR` - CharacterDevice = c::S_IFCHR as isize, - - /// `S_IFBLK` - BlockDevice = c::S_IFBLK as isize, - - /// An unknown filesystem object. - Unknown, -} - -impl FileType { - /// Construct a `FileType` from the `S_IFMT` bits of the `st_mode` field of - /// a `Stat`. - #[inline] - pub const fn from_raw_mode(st_mode: RawMode) -> Self { - match (st_mode as c::mode_t) & c::S_IFMT { - c::S_IFREG => Self::RegularFile, - c::S_IFDIR => Self::Directory, - c::S_IFLNK => Self::Symlink, - #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`. - c::S_IFIFO => Self::Fifo, - #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`. - c::S_IFSOCK => Self::Socket, - c::S_IFCHR => Self::CharacterDevice, - c::S_IFBLK => Self::BlockDevice, - _ => Self::Unknown, - } - } - - /// Construct an `st_mode` value from a `FileType`. - #[inline] - pub const fn as_raw_mode(self) -> RawMode { - match self { - Self::RegularFile => c::S_IFREG as RawMode, - Self::Directory => c::S_IFDIR as RawMode, - Self::Symlink => c::S_IFLNK as RawMode, - #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`. - Self::Fifo => c::S_IFIFO as RawMode, - #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`. - Self::Socket => c::S_IFSOCK as RawMode, - Self::CharacterDevice => c::S_IFCHR as RawMode, - Self::BlockDevice => c::S_IFBLK as RawMode, - Self::Unknown => c::S_IFMT as RawMode, - } - } - - /// Construct a `FileType` from the `d_type` field of a `c::dirent`. - #[cfg(not(any( - solarish, - target_os = "aix", - target_os = "espidf", - target_os = "haiku", - target_os = "nto", - target_os = "redox", - target_os = "vita" - )))] - #[inline] - pub(crate) const fn from_dirent_d_type(d_type: u8) -> Self { - match d_type { - c::DT_REG => Self::RegularFile, - c::DT_DIR => Self::Directory, - c::DT_LNK => Self::Symlink, - #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `DT_SOCK`. - c::DT_SOCK => Self::Socket, - #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `DT_FIFO`. - c::DT_FIFO => Self::Fifo, - c::DT_CHR => Self::CharacterDevice, - c::DT_BLK => Self::BlockDevice, - // c::DT_UNKNOWN | - _ => Self::Unknown, - } - } -} - -/// `POSIX_FADV_*` constants for use with [`fadvise`]. -/// -/// [`fadvise`]: crate::fs::fadvise -#[cfg(not(any( - apple, - netbsdlike, - solarish, - target_os = "dragonfly", - target_os = "espidf", - target_os = "haiku", - target_os = "redox", - target_os = "vita", -)))] -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[repr(u32)] -pub enum Advice { - /// `POSIX_FADV_NORMAL` - Normal = c::POSIX_FADV_NORMAL as c::c_uint, - - /// `POSIX_FADV_SEQUENTIAL` - Sequential = c::POSIX_FADV_SEQUENTIAL as c::c_uint, - - /// `POSIX_FADV_RANDOM` - Random = c::POSIX_FADV_RANDOM as c::c_uint, - - /// `POSIX_FADV_NOREUSE` - NoReuse = c::POSIX_FADV_NOREUSE as c::c_uint, - - /// `POSIX_FADV_WILLNEED` - WillNeed = c::POSIX_FADV_WILLNEED as c::c_uint, - - /// `POSIX_FADV_DONTNEED` - DontNeed = c::POSIX_FADV_DONTNEED as c::c_uint, -} - -#[cfg(any(linux_kernel, target_os = "freebsd"))] -bitflags! { - /// `MFD_*` constants for use with [`memfd_create`]. - /// - /// [`memfd_create`]: crate::fs::memfd_create - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct MemfdFlags: c::c_uint { - /// `MFD_CLOEXEC` - const CLOEXEC = c::MFD_CLOEXEC; - - /// `MFD_ALLOW_SEALING` - const ALLOW_SEALING = c::MFD_ALLOW_SEALING; - - /// `MFD_HUGETLB` (since Linux 4.14) - const HUGETLB = c::MFD_HUGETLB; - - /// `MFD_HUGE_64KB` - const HUGE_64KB = c::MFD_HUGE_64KB; - /// `MFD_HUGE_512JB` - const HUGE_512KB = c::MFD_HUGE_512KB; - /// `MFD_HUGE_1MB` - const HUGE_1MB = c::MFD_HUGE_1MB; - /// `MFD_HUGE_2MB` - const HUGE_2MB = c::MFD_HUGE_2MB; - /// `MFD_HUGE_8MB` - const HUGE_8MB = c::MFD_HUGE_8MB; - /// `MFD_HUGE_16MB` - const HUGE_16MB = c::MFD_HUGE_16MB; - /// `MFD_HUGE_32MB` - const HUGE_32MB = c::MFD_HUGE_32MB; - /// `MFD_HUGE_256MB` - const HUGE_256MB = c::MFD_HUGE_256MB; - /// `MFD_HUGE_512MB` - const HUGE_512MB = c::MFD_HUGE_512MB; - /// `MFD_HUGE_1GB` - const HUGE_1GB = c::MFD_HUGE_1GB; - /// `MFD_HUGE_2GB` - const HUGE_2GB = c::MFD_HUGE_2GB; - /// `MFD_HUGE_16GB` - const HUGE_16GB = c::MFD_HUGE_16GB; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] -bitflags! { - /// `F_SEAL_*` constants for use with [`fcntl_add_seals`] and - /// [`fcntl_get_seals`]. - /// - /// [`fcntl_add_seals`]: crate::fs::fcntl_add_seals - /// [`fcntl_get_seals`]: crate::fs::fcntl_get_seals - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct SealFlags: u32 { - /// `F_SEAL_SEAL` - const SEAL = bitcast!(c::F_SEAL_SEAL); - /// `F_SEAL_SHRINK` - const SHRINK = bitcast!(c::F_SEAL_SHRINK); - /// `F_SEAL_GROW` - const GROW = bitcast!(c::F_SEAL_GROW); - /// `F_SEAL_WRITE` - const WRITE = bitcast!(c::F_SEAL_WRITE); - /// `F_SEAL_FUTURE_WRITE` (since Linux 5.1) - #[cfg(linux_kernel)] - const FUTURE_WRITE = bitcast!(c::F_SEAL_FUTURE_WRITE); - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(all(target_os = "linux", target_env = "gnu"))] -bitflags! { - /// `STATX_*` constants for use with [`statx`]. - /// - /// [`statx`]: crate::fs::statx - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct StatxFlags: u32 { - /// `STATX_TYPE` - const TYPE = c::STATX_TYPE; - - /// `STATX_MODE` - const MODE = c::STATX_MODE; - - /// `STATX_NLINK` - const NLINK = c::STATX_NLINK; - - /// `STATX_UID` - const UID = c::STATX_UID; - - /// `STATX_GID` - const GID = c::STATX_GID; - - /// `STATX_ATIME` - const ATIME = c::STATX_ATIME; - - /// `STATX_MTIME` - const MTIME = c::STATX_MTIME; - - /// `STATX_CTIME` - const CTIME = c::STATX_CTIME; - - /// `STATX_INO` - const INO = c::STATX_INO; - - /// `STATX_SIZE` - const SIZE = c::STATX_SIZE; - - /// `STATX_BLOCKS` - const BLOCKS = c::STATX_BLOCKS; - - /// `STATX_BASIC_STATS` - const BASIC_STATS = c::STATX_BASIC_STATS; - - /// `STATX_BTIME` - const BTIME = c::STATX_BTIME; - - /// `STATX_MNT_ID` (since Linux 5.8) - const MNT_ID = c::STATX_MNT_ID; - - /// `STATX_DIOALIGN` (since Linux 6.1) - const DIOALIGN = c::STATX_DIOALIGN; - - /// `STATX_ALL` - const ALL = c::STATX_ALL; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(any( - target_os = "android", - all(target_os = "linux", not(target_env = "gnu")), -))] -bitflags! { - /// `STATX_*` constants for use with [`statx`]. - /// - /// [`statx`]: crate::fs::statx - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct StatxFlags: u32 { - /// `STATX_TYPE` - const TYPE = 0x0001; - - /// `STATX_MODE` - const MODE = 0x0002; - - /// `STATX_NLINK` - const NLINK = 0x0004; - - /// `STATX_UID` - const UID = 0x0008; - - /// `STATX_GID` - const GID = 0x0010; - - /// `STATX_ATIME` - const ATIME = 0x0020; - - /// `STATX_MTIME` - const MTIME = 0x0040; - - /// `STATX_CTIME` - const CTIME = 0x0080; - - /// `STATX_INO` - const INO = 0x0100; - - /// `STATX_SIZE` - const SIZE = 0x0200; - - /// `STATX_BLOCKS` - const BLOCKS = 0x0400; - - /// `STATX_BASIC_STATS` - const BASIC_STATS = 0x07ff; - - /// `STATX_BTIME` - const BTIME = 0x800; - - /// `STATX_MNT_ID` (since Linux 5.8) - const MNT_ID = 0x1000; - - /// `STATX_ALL` - const ALL = 0xfff; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(not(any( - netbsdlike, - solarish, - target_os = "aix", - target_os = "espidf", - target_os = "nto", - target_os = "redox", - target_os = "vita" -)))] -bitflags! { - /// `FALLOC_FL_*` constants for use with [`fallocate`]. - /// - /// [`fallocate`]: crate::fs::fallocate - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct FallocateFlags: u32 { - /// `FALLOC_FL_KEEP_SIZE` - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "hurd", - target_os = "wasi", - )))] - const KEEP_SIZE = bitcast!(c::FALLOC_FL_KEEP_SIZE); - /// `FALLOC_FL_PUNCH_HOLE` - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "hurd", - target_os = "wasi", - )))] - const PUNCH_HOLE = bitcast!(c::FALLOC_FL_PUNCH_HOLE); - /// `FALLOC_FL_NO_HIDE_STALE` - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "haiku", - target_os = "hurd", - target_os = "l4re", - target_os = "linux", - target_os = "wasi", - )))] - const NO_HIDE_STALE = bitcast!(c::FALLOC_FL_NO_HIDE_STALE); - /// `FALLOC_FL_COLLAPSE_RANGE` - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "hurd", - target_os = "emscripten", - target_os = "wasi", - )))] - const COLLAPSE_RANGE = bitcast!(c::FALLOC_FL_COLLAPSE_RANGE); - /// `FALLOC_FL_ZERO_RANGE` - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "hurd", - target_os = "emscripten", - target_os = "wasi", - )))] - const ZERO_RANGE = bitcast!(c::FALLOC_FL_ZERO_RANGE); - /// `FALLOC_FL_INSERT_RANGE` - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "hurd", - target_os = "emscripten", - target_os = "wasi", - )))] - const INSERT_RANGE = bitcast!(c::FALLOC_FL_INSERT_RANGE); - /// `FALLOC_FL_UNSHARE_RANGE` - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "hurd", - target_os = "emscripten", - target_os = "wasi", - )))] - const UNSHARE_RANGE = bitcast!(c::FALLOC_FL_UNSHARE_RANGE); - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -bitflags! { - /// `ST_*` constants for use with [`StatVfs`]. - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct StatVfsMountFlags: u64 { - /// `ST_MANDLOCK` - #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] - const MANDLOCK = c::ST_MANDLOCK as u64; - - /// `ST_NOATIME` - #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] - const NOATIME = c::ST_NOATIME as u64; - - /// `ST_NODEV` - #[cfg(any( - linux_kernel, - target_os = "aix", - target_os = "emscripten", - target_os = "fuchsia" - ))] - const NODEV = c::ST_NODEV as u64; - - /// `ST_NODIRATIME` - #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] - const NODIRATIME = c::ST_NODIRATIME as u64; - - /// `ST_NOEXEC` - #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] - const NOEXEC = c::ST_NOEXEC as u64; - - /// `ST_NOSUID` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const NOSUID = c::ST_NOSUID as u64; - - /// `ST_RDONLY` - #[cfg(not(any(target_os = "espidf", target_os = "vita")))] - const RDONLY = c::ST_RDONLY as u64; - - /// `ST_RELATIME` - #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] - const RELATIME = c::ST_RELATIME as u64; - - /// `ST_SYNCHRONOUS` - #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] - const SYNCHRONOUS = c::ST_SYNCHRONOUS as u64; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -/// `LOCK_*` constants for use with [`flock`] and [`fcntl_lock`]. -/// -/// [`flock`]: crate::fs::flock -/// [`fcntl_lock`]: crate::fs::fcntl_lock -#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "wasi")))] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(u32)] -pub enum FlockOperation { - /// `LOCK_SH` - LockShared = bitcast!(c::LOCK_SH), - /// `LOCK_EX` - LockExclusive = bitcast!(c::LOCK_EX), - /// `LOCK_UN` - Unlock = bitcast!(c::LOCK_UN), - /// `LOCK_SH | LOCK_NB` - NonBlockingLockShared = bitcast!(c::LOCK_SH | c::LOCK_NB), - /// `LOCK_EX | LOCK_NB` - NonBlockingLockExclusive = bitcast!(c::LOCK_EX | c::LOCK_NB), - /// `LOCK_UN | LOCK_NB` - NonBlockingUnlock = bitcast!(c::LOCK_UN | c::LOCK_NB), -} - -/// `struct stat` for use with [`statat`] and [`fstat`]. -/// -/// [`statat`]: crate::fs::statat -/// [`fstat`]: crate::fs::fstat -#[cfg(not(any(linux_like, target_os = "hurd")))] -pub type Stat = c::stat; - -/// `struct stat` for use with [`statat`] and [`fstat`]. -/// -/// [`statat`]: crate::fs::statat -/// [`fstat`]: crate::fs::fstat -#[cfg(any( - all(linux_kernel, target_pointer_width = "64"), - target_os = "hurd", - target_os = "emscripten", - target_os = "l4re", -))] -pub type Stat = c::stat64; - -/// `struct stat` for use with [`statat`] and [`fstat`]. -/// -/// [`statat`]: crate::fs::statat -/// [`fstat`]: crate::fs::fstat -// On 32-bit, Linux's `struct stat64` has a 32-bit `st_mtime` and friends, so -// we use our own struct, populated from `statx` where possible, to avoid the -// y2038 bug. -#[cfg(all(linux_kernel, target_pointer_width = "32"))] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -#[allow(missing_docs)] -pub struct Stat { - pub st_dev: u64, - pub st_mode: u32, - pub st_nlink: u32, - pub st_uid: u32, - pub st_gid: u32, - pub st_rdev: u64, - pub st_size: i64, - pub st_blksize: u32, - pub st_blocks: u64, - pub st_atime: u64, - pub st_atime_nsec: u32, - pub st_mtime: u64, - pub st_mtime_nsec: u32, - pub st_ctime: u64, - pub st_ctime_nsec: u32, - pub st_ino: u64, -} - -/// `struct statfs` for use with [`statfs`] and [`fstatfs`]. -/// -/// [`statfs`]: crate::fs::statfs -/// [`fstatfs`]: crate::fs::fstatfs -#[cfg(not(any( - linux_like, - solarish, - target_os = "espidf", - target_os = "haiku", - target_os = "netbsd", - target_os = "nto", - target_os = "redox", - target_os = "vita", - target_os = "wasi", -)))] -#[allow(clippy::module_name_repetitions)] -pub type StatFs = c::statfs; - -/// `struct statfs` for use with [`statfs`] and [`fstatfs`]. -/// -/// [`statfs`]: crate::fs::statfs -/// [`fstatfs`]: crate::fs::fstatfs -#[cfg(linux_like)] -pub type StatFs = c::statfs64; - -/// `struct statvfs` for use with [`statvfs`] and [`fstatvfs`]. -/// -/// [`statvfs`]: crate::fs::statvfs -/// [`fstatvfs`]: crate::fs::fstatvfs -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -#[allow(missing_docs)] -pub struct StatVfs { - pub f_bsize: u64, - pub f_frsize: u64, - pub f_blocks: u64, - pub f_bfree: u64, - pub f_bavail: u64, - pub f_files: u64, - pub f_ffree: u64, - pub f_favail: u64, - pub f_fsid: u64, - pub f_flag: StatVfsMountFlags, - pub f_namemax: u64, -} - -/// `struct statx` for use with [`statx`]. -/// -/// [`statx`]: crate::fs::statx -#[cfg(all(target_os = "linux", target_env = "gnu"))] -// Use the glibc `struct statx`. -pub type Statx = c::statx; - -/// `struct statx_timestamp` for use with [`Statx`]. -#[cfg(all(target_os = "linux", target_env = "gnu"))] -// Use the glibc `struct statx_timestamp`. -pub type StatxTimestamp = c::statx; - -/// `struct statx` for use with [`statx`]. -/// -/// [`statx`]: crate::fs::statx -// Non-glibc ABIs don't currently declare a `struct statx`, so we declare it -// ourselves. -#[cfg(any( - target_os = "android", - all(target_os = "linux", not(target_env = "gnu")), -))] -#[repr(C)] -#[allow(missing_docs)] -pub struct Statx { - pub stx_mask: u32, - pub stx_blksize: u32, - pub stx_attributes: u64, - pub stx_nlink: u32, - pub stx_uid: u32, - pub stx_gid: u32, - pub stx_mode: u16, - __statx_pad1: [u16; 1], - pub stx_ino: u64, - pub stx_size: u64, - pub stx_blocks: u64, - pub stx_attributes_mask: u64, - pub stx_atime: StatxTimestamp, - pub stx_btime: StatxTimestamp, - pub stx_ctime: StatxTimestamp, - pub stx_mtime: StatxTimestamp, - pub stx_rdev_major: u32, - pub stx_rdev_minor: u32, - pub stx_dev_major: u32, - pub stx_dev_minor: u32, - pub stx_mnt_id: u64, - __statx_pad2: u64, - __statx_pad3: [u64; 12], -} - -/// `struct statx_timestamp` for use with [`Statx`]. -// Non-glibc ABIs don't currently declare a `struct statx_timestamp`, so we -// declare it ourselves. -#[cfg(any( - target_os = "android", - all(target_os = "linux", not(target_env = "gnu")), -))] -#[repr(C)] -#[allow(missing_docs)] -pub struct StatxTimestamp { - pub tv_sec: i64, - pub tv_nsec: u32, - pub __statx_timestamp_pad1: [i32; 1], -} - -/// `mode_t` -#[cfg(not(all(target_os = "android", target_pointer_width = "32")))] -pub type RawMode = c::mode_t; - -/// `mode_t` -#[cfg(all(target_os = "android", target_pointer_width = "32"))] -pub type RawMode = c::c_uint; - -/// `dev_t` -#[cfg(not(all(target_os = "android", target_pointer_width = "32")))] -pub type Dev = c::dev_t; - -/// `dev_t` -#[cfg(all(target_os = "android", target_pointer_width = "32"))] -pub type Dev = c::c_ulonglong; - -/// `__fsword_t` -#[cfg(all( - target_os = "linux", - not(target_env = "musl"), - not(target_arch = "s390x"), -))] -pub type FsWord = c::__fsword_t; - -/// `__fsword_t` -#[cfg(all( - any(target_os = "android", all(target_os = "linux", target_env = "musl")), - target_pointer_width = "32", -))] -pub type FsWord = u32; - -/// `__fsword_t` -#[cfg(all( - any(target_os = "android", all(target_os = "linux", target_env = "musl")), - not(target_arch = "s390x"), - target_pointer_width = "64", -))] -pub type FsWord = u64; - -/// `__fsword_t` -// s390x uses `u32` for `statfs` entries on glibc, even though `__fsword_t` is -// `u64`. -#[cfg(all(target_os = "linux", target_arch = "s390x", target_env = "gnu"))] -pub type FsWord = u32; - -/// `__fsword_t` -// s390x uses `u64` for `statfs` entries on musl. -#[cfg(all(target_os = "linux", target_arch = "s390x", target_env = "musl"))] -pub type FsWord = u64; - -/// `copyfile_state_t`—State for use with [`fcopyfile`]. -/// -/// [`fcopyfile`]: crate::fs::fcopyfile -#[cfg(apple)] -#[allow(non_camel_case_types)] -#[repr(transparent)] -#[derive(Copy, Clone)] -pub struct copyfile_state_t(pub(crate) *mut c::c_void); |