summaryrefslogtreecommitdiff
path: root/vendor/rustix/src/fs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/fs')
-rw-r--r--vendor/rustix/src/fs/abs.rs304
-rw-r--r--vendor/rustix/src/fs/at.rs494
-rw-r--r--vendor/rustix/src/fs/constants.rs355
-rw-r--r--vendor/rustix/src/fs/copy_file_range.rs20
-rw-r--r--vendor/rustix/src/fs/dir.rs5
-rw-r--r--vendor/rustix/src/fs/fadvise.rs28
-rw-r--r--vendor/rustix/src/fs/fcntl.rs107
-rw-r--r--vendor/rustix/src/fs/fcntl_apple.rs66
-rw-r--r--vendor/rustix/src/fs/fcopyfile.rs88
-rw-r--r--vendor/rustix/src/fs/fd.rs331
-rw-r--r--vendor/rustix/src/fs/getpath.rs14
-rw-r--r--vendor/rustix/src/fs/id.rs1
-rw-r--r--vendor/rustix/src/fs/inotify.rs219
-rw-r--r--vendor/rustix/src/fs/ioctl.rs169
-rw-r--r--vendor/rustix/src/fs/makedev.rs35
-rw-r--r--vendor/rustix/src/fs/memfd_create.rs22
-rw-r--r--vendor/rustix/src/fs/mod.rs141
-rw-r--r--vendor/rustix/src/fs/openat2.rs24
-rw-r--r--vendor/rustix/src/fs/raw_dir.rs236
-rw-r--r--vendor/rustix/src/fs/seek_from.rs53
-rw-r--r--vendor/rustix/src/fs/sendfile.rs20
-rw-r--r--vendor/rustix/src/fs/special.rs80
-rw-r--r--vendor/rustix/src/fs/statx.rs275
-rw-r--r--vendor/rustix/src/fs/sync.rs14
-rw-r--r--vendor/rustix/src/fs/xattr.rs256
25 files changed, 3357 insertions, 0 deletions
diff --git a/vendor/rustix/src/fs/abs.rs b/vendor/rustix/src/fs/abs.rs
new file mode 100644
index 00000000..236a833a
--- /dev/null
+++ b/vendor/rustix/src/fs/abs.rs
@@ -0,0 +1,304 @@
+//! POSIX-style filesystem functions which operate on bare paths.
+
+use crate::fd::OwnedFd;
+#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
+use crate::fs::Access;
+#[cfg(not(any(
+ solarish,
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "netbsd",
+ target_os = "nto",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi",
+)))]
+use crate::fs::StatFs;
+#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
+use crate::fs::StatVfs;
+use crate::fs::{Mode, OFlags, Stat};
+#[cfg(not(target_os = "wasi"))]
+use crate::ugid::{Gid, Uid};
+use crate::{backend, io, path};
+#[cfg(feature = "alloc")]
+use {
+ crate::ffi::{CStr, CString},
+ crate::path::SMALL_PATH_BUFFER_SIZE,
+ alloc::vec::Vec,
+};
+
+/// `open(path, oflags, mode)`—Opens a file.
+///
+/// POSIX guarantees that `open` will use the lowest unused file descriptor,
+/// however it is not safe in general to rely on this, as file descriptors may
+/// be unexpectedly allocated on other threads or in libraries.
+///
+/// The `Mode` argument is only significant when creating a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/open.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/open.2.html
+#[inline]
+pub fn open<P: path::Arg>(path: P, flags: OFlags, mode: Mode) -> io::Result<OwnedFd> {
+ path.into_with_c_str(|path| backend::fs::syscalls::open(path, flags, mode))
+}
+
+/// `chmod(path, mode)`—Sets file or directory permissions.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/chmod.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/chmod.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn chmod<P: path::Arg>(path: P, mode: Mode) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::chmod(path, mode))
+}
+
+/// `stat(path)`—Queries metadata for a file or directory.
+///
+/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to
+/// interpret the `st_mode` field.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/stat.2.html
+/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode
+/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode
+#[inline]
+pub fn stat<P: path::Arg>(path: P) -> io::Result<Stat> {
+ path.into_with_c_str(backend::fs::syscalls::stat)
+}
+
+/// `lstat(path)`—Queries metadata for a file or directory, without following
+/// symlinks.
+///
+/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to
+/// interpret the `st_mode` field.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/lstat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/lstat.2.html
+/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode
+/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode
+#[inline]
+pub fn lstat<P: path::Arg>(path: P) -> io::Result<Stat> {
+ path.into_with_c_str(backend::fs::syscalls::lstat)
+}
+
+/// `readlink(path)`—Reads the contents of a symlink.
+///
+/// If `reuse` is non-empty, reuse its buffer to store the result if possible.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/readlink.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/readlink.2.html
+#[cfg(feature = "alloc")]
+#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+#[inline]
+pub fn readlink<P: path::Arg, B: Into<Vec<u8>>>(path: P, reuse: B) -> io::Result<CString> {
+ path.into_with_c_str(|path| _readlink(path, reuse.into()))
+}
+
+#[cfg(feature = "alloc")]
+fn _readlink(path: &CStr, mut buffer: Vec<u8>) -> io::Result<CString> {
+ // This code would benefit from having a better way to read into
+ // uninitialized memory, but that requires `unsafe`.
+ buffer.clear();
+ buffer.reserve(SMALL_PATH_BUFFER_SIZE);
+ buffer.resize(buffer.capacity(), 0_u8);
+
+ loop {
+ let nread = backend::fs::syscalls::readlink(path, &mut buffer)?;
+
+ let nread = nread as usize;
+ assert!(nread <= buffer.len());
+ if nread < buffer.len() {
+ buffer.resize(nread, 0_u8);
+ return Ok(CString::new(buffer).unwrap());
+ }
+ // Use `Vec` reallocation strategy to grow capacity exponentially.
+ buffer.reserve(1);
+ buffer.resize(buffer.capacity(), 0_u8);
+ }
+}
+
+/// `rename(old_path, new_path)`—Renames a file or directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/rename.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/rename.2.html
+#[inline]
+pub fn rename<P: path::Arg, Q: path::Arg>(old_path: P, new_path: Q) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| backend::fs::syscalls::rename(old_path, new_path))
+ })
+}
+
+/// `unlink(path)`—Unlinks a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/unlink.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/unlink.2.html
+#[inline]
+pub fn unlink<P: path::Arg>(path: P) -> io::Result<()> {
+ path.into_with_c_str(backend::fs::syscalls::unlink)
+}
+
+/// `rmdir(path)`—Removes a directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/rmdir.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/rmdir.2.html
+#[inline]
+pub fn rmdir<P: path::Arg>(path: P) -> io::Result<()> {
+ path.into_with_c_str(backend::fs::syscalls::rmdir)
+}
+
+/// `link(old_path, new_path)`—Creates a hard link.
+///
+/// POSIX leaves it implementation-defined whether `link` follows a symlink in
+/// `old_path`, or creates a new link to the symbolic link itself. On platforms
+/// which have it, [`linkat`] avoids this problem since it has an [`AtFlags`]
+/// parameter and the [`AtFlags::SYMLINK_FOLLOW`] flag determines whether
+/// symlinks should be followed.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/link.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/link.2.html
+/// [`linkat`]: crate::fs::linkat
+/// [`AtFlags`]: crate::fs::AtFlags
+/// [`AtFlags::SYMLINK_FOLLOW`]: crate::fs::AtFlags::SYMLINK_FOLLOW
+#[inline]
+pub fn link<P: path::Arg, Q: path::Arg>(old_path: P, new_path: Q) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| backend::fs::syscalls::link(old_path, new_path))
+ })
+}
+
+/// `symlink(old_path, new_path)`—Creates a symlink.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/symlink.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/symlink.2.html
+#[inline]
+pub fn symlink<P: path::Arg, Q: path::Arg>(old_path: P, new_path: Q) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| backend::fs::syscalls::symlink(old_path, new_path))
+ })
+}
+
+/// `mkdir(path, mode)`—Creates a directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/mkdir.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mkdir.2.html
+#[inline]
+pub fn mkdir<P: path::Arg>(path: P, mode: Mode) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::mkdir(path, mode))
+}
+
+/// `access(path, access)`—Tests permissions for a file or directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/access.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/access.2.html
+#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
+#[inline]
+pub fn access<P: path::Arg>(path: P, access: Access) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::access(path, access))
+}
+
+/// `statfs`—Queries filesystem metadata.
+///
+/// Compared to [`statvfs`], this function often provides more information,
+/// though it's less portable.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/statfs.2.html
+#[cfg(not(any(
+ solarish,
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "netbsd",
+ target_os = "nto",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi",
+)))]
+#[inline]
+pub fn statfs<P: path::Arg>(path: P) -> io::Result<StatFs> {
+ path.into_with_c_str(backend::fs::syscalls::statfs)
+}
+
+/// `statvfs`—Queries filesystem metadata, POSIX version.
+///
+/// Compared to [`statfs`], this function often provides less information, but
+/// it is more portable. But even so, filesystems are very diverse and not all
+/// the fields are meaningful for every filesystem. And `f_fsid` doesn't seem
+/// to have a clear meaning anywhere.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/statvfs.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/statvfs.2.html
+#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub fn statvfs<P: path::Arg>(path: P) -> io::Result<StatVfs> {
+ path.into_with_c_str(backend::fs::syscalls::statvfs)
+}
+
+/// `chown(path, owner, group)`—Sets open file or directory ownership.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/chown.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/chown.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn chown<P: path::Arg>(path: P, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::chown(path, owner, group))
+}
diff --git a/vendor/rustix/src/fs/at.rs b/vendor/rustix/src/fs/at.rs
new file mode 100644
index 00000000..4ad2df89
--- /dev/null
+++ b/vendor/rustix/src/fs/at.rs
@@ -0,0 +1,494 @@
+//! POSIX-style `*at` functions.
+//!
+//! The `dirfd` argument to these functions may be a file descriptor for a
+//! directory, the special value [`CWD`], or the special value [`ABS`].
+//!
+//! [`CWD`]: crate::fs::CWD
+//! [`ABS`]: crate::fs::ABS
+
+#![allow(unsafe_code)]
+
+use crate::buffer::Buffer;
+use crate::fd::OwnedFd;
+#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
+use crate::fs::Access;
+#[cfg(not(target_os = "espidf"))]
+use crate::fs::AtFlags;
+#[cfg(apple)]
+use crate::fs::CloneFlags;
+#[cfg(any(linux_kernel, apple))]
+use crate::fs::RenameFlags;
+#[cfg(not(target_os = "espidf"))]
+use crate::fs::Stat;
+#[cfg(not(any(apple, target_os = "espidf", target_os = "vita", target_os = "wasi")))]
+use crate::fs::{Dev, FileType};
+#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
+use crate::fs::{Gid, Uid};
+use crate::fs::{Mode, OFlags};
+use crate::{backend, io, path};
+use backend::fd::AsFd;
+#[cfg(feature = "alloc")]
+use {
+ crate::ffi::{CStr, CString},
+ crate::path::SMALL_PATH_BUFFER_SIZE,
+ alloc::vec::Vec,
+ backend::fd::BorrowedFd,
+};
+#[cfg(not(any(target_os = "espidf", target_os = "vita")))]
+use {crate::fs::Timestamps, crate::timespec::Nsecs};
+
+/// `UTIME_NOW` for use with [`utimensat`].
+///
+/// [`utimensat`]: crate::fs::utimensat
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita"
+)))]
+pub const UTIME_NOW: Nsecs = backend::c::UTIME_NOW as Nsecs;
+
+/// `UTIME_OMIT` for use with [`utimensat`].
+///
+/// [`utimensat`]: crate::fs::utimensat
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita"
+)))]
+pub const UTIME_OMIT: Nsecs = backend::c::UTIME_OMIT as Nsecs;
+
+/// `openat(dirfd, path, oflags, mode)`—Opens a file.
+///
+/// POSIX guarantees that `openat` will use the lowest unused file descriptor,
+/// however it is not safe in general to rely on this, as file descriptors may
+/// be unexpectedly allocated on other threads or in libraries.
+///
+/// The `Mode` argument is only significant when creating a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/openat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/openat.2.html
+#[inline]
+pub fn openat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ oflags: OFlags,
+ create_mode: Mode,
+) -> io::Result<OwnedFd> {
+ path.into_with_c_str(|path| {
+ backend::fs::syscalls::openat(dirfd.as_fd(), path, oflags, create_mode)
+ })
+}
+
+/// `readlinkat(fd, path)`—Reads the contents of a symlink.
+///
+/// If `reuse` already has available capacity, reuse it if possible.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/readlinkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/readlinkat.2.html
+#[cfg(feature = "alloc")]
+#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+#[inline]
+pub fn readlinkat<P: path::Arg, Fd: AsFd, B: Into<Vec<u8>>>(
+ dirfd: Fd,
+ path: P,
+ reuse: B,
+) -> io::Result<CString> {
+ path.into_with_c_str(|path| _readlinkat(dirfd.as_fd(), path, reuse.into()))
+}
+
+#[cfg(feature = "alloc")]
+#[allow(unsafe_code)]
+fn _readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, mut buffer: Vec<u8>) -> io::Result<CString> {
+ buffer.clear();
+ buffer.reserve(SMALL_PATH_BUFFER_SIZE);
+
+ loop {
+ let buf = buffer.spare_capacity_mut();
+
+ // SAFETY: `readlinkat` behaves.
+ let nread = unsafe {
+ backend::fs::syscalls::readlinkat(
+ dirfd.as_fd(),
+ path,
+ (buf.as_mut_ptr().cast(), buf.len()),
+ )?
+ };
+
+ debug_assert!(nread <= buffer.capacity());
+ if nread < buffer.capacity() {
+ // SAFETY: From the [documentation]: “On success, these calls
+ // return the number of bytes placed in buf.”
+ //
+ // [documentation]: https://man7.org/linux/man-pages/man2/readlinkat.2.html
+ unsafe {
+ buffer.set_len(nread);
+ }
+
+ // SAFETY:
+ // - “readlink places the contents of the symbolic link pathname
+ // in the buffer buf”
+ // - [POSIX definition 3.271: Pathname]: “A string that is used
+ // to identify a file.”
+ // - [POSIX definition 3.375: String]: “A contiguous sequence of
+ // bytes terminated by and including the first null byte.”
+ // - “readlink does not append a terminating null byte to buf.”
+ //
+ // Thus, there will be no NUL bytes in the string.
+ //
+ // [POSIX definition 3.271: Pathname]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_271
+ // [POSIX definition 3.375: String]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_375
+ unsafe {
+ return Ok(CString::from_vec_unchecked(buffer));
+ }
+ }
+
+ // Use `Vec` reallocation strategy to grow capacity exponentially.
+ buffer.reserve(buffer.capacity() + 1);
+ }
+}
+
+/// `readlinkat(fd, path)`—Reads the contents of a symlink, without
+/// allocating.
+///
+/// This is the "raw" version which avoids allocating, but which truncates the
+/// string if it doesn't fit in the provided buffer, and doesn't NUL-terminate
+/// the string.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/readlinkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/readlinkat.2.html
+#[inline]
+pub fn readlinkat_raw<P: path::Arg, Fd: AsFd, Buf: Buffer<u8>>(
+ dirfd: Fd,
+ path: P,
+ mut buf: Buf,
+) -> io::Result<Buf::Output> {
+ // SAFETY: `readlinkat` behaves.
+ let len = path.into_with_c_str(|path| unsafe {
+ backend::fs::syscalls::readlinkat(dirfd.as_fd(), path, buf.parts_mut())
+ })?;
+ // SAFETY: `readlinkat` behaves.
+ unsafe { Ok(buf.assume_init(len)) }
+}
+
+/// `mkdirat(fd, path, mode)`—Creates a directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/mkdirat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mkdirat.2.html
+#[inline]
+pub fn mkdirat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, mode: Mode) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::mkdirat(dirfd.as_fd(), path, mode))
+}
+
+/// `linkat(old_dirfd, old_path, new_dirfd, new_path, flags)`—Creates a hard
+/// link.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/linkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/linkat.2.html
+#[cfg(not(target_os = "espidf"))]
+#[inline]
+pub fn linkat<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
+ old_dirfd: PFd,
+ old_path: P,
+ new_dirfd: QFd,
+ new_path: Q,
+ flags: AtFlags,
+) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| {
+ backend::fs::syscalls::linkat(
+ old_dirfd.as_fd(),
+ old_path,
+ new_dirfd.as_fd(),
+ new_path,
+ flags,
+ )
+ })
+ })
+}
+
+/// `unlinkat(fd, path, flags)`—Unlinks a file or remove a directory.
+///
+/// With the [`REMOVEDIR`] flag, this removes a directory. This is in place of
+/// a `rmdirat` function.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [`REMOVEDIR`]: AtFlags::REMOVEDIR
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/unlinkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/unlinkat.2.html
+#[cfg(not(target_os = "espidf"))]
+#[inline]
+pub fn unlinkat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, flags: AtFlags) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::unlinkat(dirfd.as_fd(), path, flags))
+}
+
+/// `renameat(old_dirfd, old_path, new_dirfd, new_path)`—Renames a file or
+/// directory.
+///
+/// See [`renameat_with`] to pass additional flags.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/renameat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/renameat.2.html
+#[inline]
+pub fn renameat<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
+ old_dirfd: PFd,
+ old_path: P,
+ new_dirfd: QFd,
+ new_path: Q,
+) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| {
+ backend::fs::syscalls::renameat(
+ old_dirfd.as_fd(),
+ old_path,
+ new_dirfd.as_fd(),
+ new_path,
+ )
+ })
+ })
+}
+
+/// `renameat2(old_dirfd, old_path, new_dirfd, new_path, flags)`—Renames a
+/// file or directory.
+///
+/// `renameat_with` is the same as [`renameat`] but adds an additional
+/// flags operand.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/renameat2.2.html
+#[cfg(any(apple, linux_kernel))]
+#[inline]
+#[doc(alias = "renameat2")]
+#[doc(alias = "renameatx_np")]
+pub fn renameat_with<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
+ old_dirfd: PFd,
+ old_path: P,
+ new_dirfd: QFd,
+ new_path: Q,
+ flags: RenameFlags,
+) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| {
+ backend::fs::syscalls::renameat2(
+ old_dirfd.as_fd(),
+ old_path,
+ new_dirfd.as_fd(),
+ new_path,
+ flags,
+ )
+ })
+ })
+}
+
+/// `symlinkat(old_path, new_dirfd, new_path)`—Creates a symlink.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/symlinkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/symlinkat.2.html
+#[inline]
+pub fn symlinkat<P: path::Arg, Q: path::Arg, Fd: AsFd>(
+ old_path: P,
+ new_dirfd: Fd,
+ new_path: Q,
+) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| {
+ backend::fs::syscalls::symlinkat(old_path, new_dirfd.as_fd(), new_path)
+ })
+ })
+}
+
+/// `fstatat(dirfd, path, flags)`—Queries metadata for a file or directory.
+///
+/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to
+/// interpret the `st_mode` field.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fstatat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fstatat.2.html
+/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode
+/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode
+#[cfg(not(target_os = "espidf"))]
+#[inline]
+#[doc(alias = "fstatat")]
+pub fn statat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, flags: AtFlags) -> io::Result<Stat> {
+ path.into_with_c_str(|path| backend::fs::syscalls::statat(dirfd.as_fd(), path, flags))
+}
+
+/// `faccessat(dirfd, path, access, flags)`—Tests permissions for a file or
+/// directory.
+///
+/// On Linux before 5.8, this function uses the `faccessat` system call which
+/// doesn't support any flags. This function emulates support for the
+/// [`AtFlags::EACCESS`] flag by checking whether the uid and gid of the
+/// process match the effective uid and gid, in which case the `EACCESS` flag
+/// can be ignored. In Linux 5.8 and beyond `faccessat2` is used, which
+/// supports flags.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/faccessat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/faccessat.2.html
+#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
+#[inline]
+#[doc(alias = "faccessat")]
+pub fn accessat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ access: Access,
+ flags: AtFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::accessat(dirfd.as_fd(), path, access, flags))
+}
+
+/// `utimensat(dirfd, path, times, flags)`—Sets file or directory timestamps.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/utimensat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/utimensat.2.html
+#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
+#[inline]
+pub fn utimensat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ times: &Timestamps,
+ flags: AtFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::utimensat(dirfd.as_fd(), path, times, flags))
+}
+
+/// `fchmodat(dirfd, path, mode, flags)`—Sets file or directory permissions.
+///
+/// Platform support for flags varies widely, for example on Linux
+/// [`AtFlags::SYMLINK_NOFOLLOW`] is not implemented and therefore
+/// [`io::Errno::OPNOTSUPP`] will be returned.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fchmodat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchmodat.2.html
+#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
+#[inline]
+#[doc(alias = "fchmodat")]
+pub fn chmodat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ mode: Mode,
+ flags: AtFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| backend::fs::syscalls::chmodat(dirfd.as_fd(), path, mode, flags))
+}
+
+/// `fclonefileat(src, dst_dir, dst, flags)`—Efficiently copies between files.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://github.com/apple-oss-distributions/xnu/blob/main/bsd/man/man2/clonefile.2
+#[cfg(apple)]
+#[inline]
+pub fn fclonefileat<Fd: AsFd, DstFd: AsFd, P: path::Arg>(
+ src: Fd,
+ dst_dir: DstFd,
+ dst: P,
+ flags: CloneFlags,
+) -> io::Result<()> {
+ dst.into_with_c_str(|dst| {
+ backend::fs::syscalls::fclonefileat(src.as_fd(), dst_dir.as_fd(), dst, flags)
+ })
+}
+
+/// `mknodat(dirfd, path, mode, dev)`—Creates special or normal files.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/mknodat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mknodat.2.html
+#[cfg(not(any(
+ apple,
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+#[inline]
+pub fn mknodat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ file_type: FileType,
+ mode: Mode,
+ dev: Dev,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| {
+ backend::fs::syscalls::mknodat(dirfd.as_fd(), path, file_type, mode, dev)
+ })
+}
+
+/// `fchownat(dirfd, path, owner, group, flags)`—Sets file or directory
+/// ownership.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fchownat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchownat.2.html
+#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
+#[inline]
+#[doc(alias = "fchownat")]
+pub fn chownat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ owner: Option<Uid>,
+ group: Option<Gid>,
+ flags: AtFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| {
+ backend::fs::syscalls::chownat(dirfd.as_fd(), path, owner, group, flags)
+ })
+}
diff --git a/vendor/rustix/src/fs/constants.rs b/vendor/rustix/src/fs/constants.rs
new file mode 100644
index 00000000..5f106342
--- /dev/null
+++ b/vendor/rustix/src/fs/constants.rs
@@ -0,0 +1,355 @@
+//! Filesystem API constants, translated into `bitflags` constants.
+
+use crate::backend;
+
+pub use crate::timespec::{Nsecs, Secs, Timespec};
+pub use backend::fs::types::*;
+
+impl FileType {
+ /// Returns `true` if this `FileType` is a regular file.
+ pub fn is_file(self) -> bool {
+ self == Self::RegularFile
+ }
+
+ /// Returns `true` if this `FileType` is a directory.
+ pub fn is_dir(self) -> bool {
+ self == Self::Directory
+ }
+
+ /// Returns `true` if this `FileType` is a symlink.
+ pub fn is_symlink(self) -> bool {
+ self == Self::Symlink
+ }
+
+ /// Returns `true` if this `FileType` is a fifo.
+ #[cfg(not(target_os = "wasi"))]
+ pub fn is_fifo(self) -> bool {
+ self == Self::Fifo
+ }
+
+ /// Returns `true` if this `FileType` is a socket.
+ #[cfg(not(target_os = "wasi"))]
+ pub fn is_socket(self) -> bool {
+ self == Self::Socket
+ }
+
+ /// Returns `true` if this `FileType` is a character device.
+ pub fn is_char_device(self) -> bool {
+ self == Self::CharacterDevice
+ }
+
+ /// Returns `true` if this `FileType` is a block device.
+ pub fn is_block_device(self) -> bool {
+ self == Self::BlockDevice
+ }
+}
+
+#[cfg(test)]
+#[allow(unused_imports)]
+#[allow(unsafe_code)]
+mod tests {
+ use super::*;
+ use crate::backend::c;
+ // Rust's libc crate lacks statx for Non-glibc targets.
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ use crate::fs::{Statx, StatxTimestamp};
+
+ #[test]
+ fn test_layouts() {
+ #[cfg(linux_kernel)]
+ assert_eq_size!(FsWord, linux_raw_sys::general::__fsword_t);
+
+ // Don't test against `__kernel_mode_t` on platforms where it's a
+ // `u16`.
+ #[cfg(linux_kernel)]
+ #[cfg(not(any(
+ target_arch = "x86",
+ target_arch = "sparc",
+ target_arch = "avr",
+ target_arch = "arm",
+ )))]
+ assert_eq_size!(RawMode, linux_raw_sys::general::__kernel_mode_t);
+
+ #[cfg(linux_kernel)]
+ #[cfg(any(
+ target_arch = "x86",
+ target_arch = "sparc",
+ target_arch = "avr",
+ target_arch = "arm",
+ ))]
+ assert_eq_size!(u16, linux_raw_sys::general::__kernel_mode_t);
+
+ let some_stat: Stat = unsafe { core::mem::zeroed() };
+
+ // Ensure that seconds fields are 64-bit on non-y2038-bug platforms, and
+ // on Linux where we use statx.
+ #[cfg(any(linux_kernel, not(fix_y2038)))]
+ {
+ assert_eq!(some_stat.st_atime, 0_i64);
+ assert_eq!(some_stat.st_mtime, 0_i64);
+ assert_eq!(some_stat.st_ctime, 0_i64);
+ }
+
+ // Ensure that file offsets are 64-bit.
+ assert_eq!(some_stat.st_size, 0_i64);
+
+ // Check that various fields match expected types.
+ assert_eq!(some_stat.st_mode, 0 as RawMode);
+ assert_eq!(some_stat.st_dev, 0 as Dev);
+ assert_eq!(some_stat.st_rdev, 0 as Dev);
+ assert_eq!(some_stat.st_uid, 0 as crate::ugid::RawUid);
+ assert_eq!(some_stat.st_gid, 0 as crate::ugid::RawGid);
+
+ // `Stat` should match `c::stat` or `c::stat64` unless we need y2038
+ // fixes and are using a different layout.
+ #[cfg(not(any(
+ all(libc, linux_kernel, target_pointer_width = "32"),
+ all(
+ linux_raw,
+ any(
+ target_pointer_width = "32",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+ )
+ )
+ )))]
+ {
+ // Check that `Stat` matches `c::stat`.
+ #[cfg(not(all(
+ libc,
+ any(
+ all(linux_kernel, target_pointer_width = "64"),
+ target_os = "hurd",
+ target_os = "emscripten",
+ target_os = "l4re",
+ )
+ )))]
+ {
+ check_renamed_type!(Stat, stat);
+ check_renamed_struct_field!(Stat, stat, st_dev);
+ check_renamed_struct_field!(Stat, stat, st_ino);
+ check_renamed_struct_field!(Stat, stat, st_nlink);
+ check_renamed_struct_field!(Stat, stat, st_mode);
+ check_renamed_struct_field!(Stat, stat, st_uid);
+ check_renamed_struct_field!(Stat, stat, st_gid);
+ #[cfg(all(
+ linux_raw,
+ not(any(
+ target_arch = "aarch64",
+ target_arch = "powerpc64",
+ target_arch = "riscv64",
+ target_arch = "s390x"
+ ))
+ ))]
+ check_renamed_struct_field!(Stat, stat, __pad0);
+ check_renamed_struct_field!(Stat, stat, st_rdev);
+ #[cfg(all(linux_raw, not(any(target_arch = "powerpc64", target_arch = "x86_64"))))]
+ check_renamed_struct_field!(Stat, stat, __pad1);
+ check_renamed_struct_field!(Stat, stat, st_size);
+ check_renamed_struct_field!(Stat, stat, st_blksize);
+ #[cfg(all(
+ linux_raw,
+ not(any(
+ target_arch = "powerpc64",
+ target_arch = "s390x",
+ target_arch = "x86_64"
+ ))
+ ))]
+ check_renamed_struct_field!(Stat, stat, __pad2);
+ check_renamed_struct_field!(Stat, stat, st_blocks);
+ check_renamed_struct_field!(Stat, stat, st_atime);
+ #[cfg(not(target_os = "netbsd"))]
+ check_renamed_struct_field!(Stat, stat, st_atime_nsec);
+ #[cfg(target_os = "netbsd")]
+ check_renamed_struct_renamed_field!(Stat, stat, st_atime_nsec, st_atimensec);
+ check_renamed_struct_field!(Stat, stat, st_mtime);
+ #[cfg(not(target_os = "netbsd"))]
+ check_renamed_struct_field!(Stat, stat, st_mtime_nsec);
+ #[cfg(target_os = "netbsd")]
+ check_renamed_struct_renamed_field!(Stat, stat, st_mtime_nsec, st_mtimensec);
+ check_renamed_struct_field!(Stat, stat, st_ctime);
+ #[cfg(not(target_os = "netbsd"))]
+ check_renamed_struct_field!(Stat, stat, st_ctime_nsec);
+ #[cfg(target_os = "netbsd")]
+ check_renamed_struct_renamed_field!(Stat, stat, st_ctime_nsec, st_ctimensec);
+ #[cfg(all(
+ linux_raw,
+ not(any(
+ target_arch = "aarch64",
+ target_arch = "powerpc64",
+ target_arch = "riscv64"
+ ))
+ ))]
+ check_renamed_struct_field!(Stat, stat, __unused);
+ #[cfg(all(linux_raw, not(any(target_arch = "s390x", target_arch = "x86_64"))))]
+ check_renamed_struct_field!(Stat, stat, __unused4);
+ #[cfg(all(linux_raw, not(any(target_arch = "s390x", target_arch = "x86_64"))))]
+ check_renamed_struct_field!(Stat, stat, __unused5);
+ #[cfg(all(
+ linux_raw,
+ not(any(
+ target_arch = "aarch64",
+ target_arch = "riscv64",
+ target_arch = "s390x",
+ target_arch = "x86_64"
+ ))
+ ))]
+ check_renamed_struct_field!(Stat, stat, __unused6);
+ }
+
+ // Check that `Stat` matches `c::stat64`.
+ #[cfg(all(
+ libc,
+ any(
+ all(linux_kernel, target_pointer_width = "64"),
+ target_os = "hurd",
+ target_os = "emscripten",
+ target_os = "l4re",
+ )
+ ))]
+ {
+ check_renamed_type!(Stat, stat64);
+ check_renamed_struct_field!(Stat, stat64, st_dev);
+ check_renamed_struct_field!(Stat, stat64, st_ino);
+ check_renamed_struct_field!(Stat, stat64, st_nlink);
+ check_renamed_struct_field!(Stat, stat64, st_mode);
+ check_renamed_struct_field!(Stat, stat64, st_uid);
+ check_renamed_struct_field!(Stat, stat64, st_gid);
+ #[cfg(all(
+ linux_raw,
+ not(any(
+ target_arch = "aarch64",
+ target_arch = "powerpc64",
+ target_arch = "riscv64",
+ target_arch = "s390x"
+ ))
+ ))]
+ check_renamed_struct_field!(Stat, stat64, __pad0);
+ check_renamed_struct_field!(Stat, stat64, st_rdev);
+ #[cfg(all(linux_raw, not(any(target_arch = "powerpc64", target_arch = "x86_64"))))]
+ check_renamed_struct_field!(Stat, stat64, __pad1);
+ check_renamed_struct_field!(Stat, stat64, st_size);
+ check_renamed_struct_field!(Stat, stat64, st_blksize);
+ #[cfg(all(
+ linux_raw,
+ not(any(
+ target_arch = "powerpc64",
+ target_arch = "s390x",
+ target_arch = "x86_64"
+ ))
+ ))]
+ check_renamed_struct_field!(Stat, stat64, __pad2);
+ check_renamed_struct_field!(Stat, stat64, st_blocks);
+ check_renamed_struct_field!(Stat, stat64, st_atime);
+ check_renamed_struct_field!(Stat, stat64, st_atime_nsec);
+ check_renamed_struct_field!(Stat, stat64, st_mtime);
+ check_renamed_struct_field!(Stat, stat64, st_mtime_nsec);
+ check_renamed_struct_field!(Stat, stat64, st_ctime);
+ check_renamed_struct_field!(Stat, stat64, st_ctime_nsec);
+ #[cfg(all(
+ linux_raw,
+ not(any(
+ target_arch = "aarch64",
+ target_arch = "powerpc64",
+ target_arch = "riscv64"
+ ))
+ ))]
+ check_renamed_struct_field!(Stat, stat64, __unused);
+ #[cfg(all(linux_raw, not(any(target_arch = "s390x", target_arch = "x86_64"))))]
+ check_renamed_struct_field!(Stat, stat64, __unused4);
+ #[cfg(all(linux_raw, not(any(target_arch = "s390x", target_arch = "x86_64"))))]
+ check_renamed_struct_field!(Stat, stat64, __unused5);
+ #[cfg(all(
+ linux_raw,
+ not(any(
+ target_arch = "aarch64",
+ target_arch = "riscv64",
+ target_arch = "s390x",
+ target_arch = "x86_64"
+ ))
+ ))]
+ check_renamed_struct_field!(Stat, stat64, __unused6);
+ }
+ }
+
+ #[cfg(not(any(
+ solarish,
+ target_os = "cygwin",
+ target_os = "haiku",
+ target_os = "nto",
+ target_os = "redox",
+ target_os = "wasi",
+ )))]
+ {
+ check_renamed_type!(Fsid, fsid_t);
+ #[cfg(not(libc))] // libc hides the `val` field
+ check_renamed_struct_field!(Fsid, fsid_t, val);
+ }
+
+ #[cfg(linux_like)]
+ {
+ check_renamed_type!(StatFs, statfs64);
+ check_renamed_struct_field!(StatFs, statfs64, f_type);
+ check_renamed_struct_field!(StatFs, statfs64, f_bsize);
+ check_renamed_struct_field!(StatFs, statfs64, f_blocks);
+ check_renamed_struct_field!(StatFs, statfs64, f_bfree);
+ check_renamed_struct_field!(StatFs, statfs64, f_bavail);
+ check_renamed_struct_field!(StatFs, statfs64, f_files);
+ check_renamed_struct_field!(StatFs, statfs64, f_ffree);
+ check_renamed_struct_field!(StatFs, statfs64, f_fsid);
+ check_renamed_struct_field!(StatFs, statfs64, f_namelen);
+ check_renamed_struct_field!(StatFs, statfs64, f_frsize);
+ check_renamed_struct_field!(StatFs, statfs64, f_flags);
+ #[cfg(linux_raw)]
+ check_renamed_struct_field!(StatFs, statfs64, f_spare);
+ }
+
+ // Rust's libc crate lacks statx for Non-glibc targets.
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ {
+ check_renamed_type!(StatxTimestamp, statx_timestamp);
+ check_renamed_struct_field!(StatxTimestamp, statx_timestamp, tv_sec);
+ check_renamed_struct_field!(StatxTimestamp, statx_timestamp, tv_nsec);
+ #[cfg(linux_raw)]
+ check_renamed_struct_field!(StatxTimestamp, statx_timestamp, __reserved);
+
+ check_renamed_type!(Statx, statx);
+ check_renamed_struct_field!(Statx, statx, stx_mask);
+ check_renamed_struct_field!(Statx, statx, stx_blksize);
+ check_renamed_struct_field!(Statx, statx, stx_attributes);
+ check_renamed_struct_field!(Statx, statx, stx_nlink);
+ check_renamed_struct_field!(Statx, statx, stx_uid);
+ check_renamed_struct_field!(Statx, statx, stx_gid);
+ check_renamed_struct_field!(Statx, statx, stx_mode);
+ #[cfg(linux_raw)]
+ check_renamed_struct_field!(Statx, statx, __spare0);
+ check_renamed_struct_field!(Statx, statx, stx_ino);
+ check_renamed_struct_field!(Statx, statx, stx_size);
+ check_renamed_struct_field!(Statx, statx, stx_blocks);
+ check_renamed_struct_field!(Statx, statx, stx_attributes_mask);
+ check_renamed_struct_field!(Statx, statx, stx_atime);
+ check_renamed_struct_field!(Statx, statx, stx_btime);
+ check_renamed_struct_field!(Statx, statx, stx_ctime);
+ check_renamed_struct_field!(Statx, statx, stx_mtime);
+ check_renamed_struct_field!(Statx, statx, stx_rdev_major);
+ check_renamed_struct_field!(Statx, statx, stx_rdev_minor);
+ check_renamed_struct_field!(Statx, statx, stx_dev_major);
+ check_renamed_struct_field!(Statx, statx, stx_dev_minor);
+ check_renamed_struct_field!(Statx, statx, stx_mnt_id);
+ check_renamed_struct_field!(Statx, statx, stx_dio_mem_align);
+ check_renamed_struct_field!(Statx, statx, stx_dio_offset_align);
+ #[cfg(not(libc))] // not in libc yet
+ check_renamed_struct_field!(Statx, statx, stx_subvol);
+ #[cfg(not(libc))] // not in libc yet
+ check_renamed_struct_field!(Statx, statx, stx_atomic_write_unit_min);
+ #[cfg(not(libc))] // not in libc yet
+ check_renamed_struct_field!(Statx, statx, stx_atomic_write_unit_max);
+ #[cfg(not(libc))] // not in libc yet
+ check_renamed_struct_field!(Statx, statx, stx_atomic_write_segments_max);
+ #[cfg(linux_raw)]
+ check_renamed_struct_field!(Statx, statx, __spare1);
+ #[cfg(linux_raw)]
+ check_renamed_struct_field!(Statx, statx, __spare3);
+ }
+ }
+}
diff --git a/vendor/rustix/src/fs/copy_file_range.rs b/vendor/rustix/src/fs/copy_file_range.rs
new file mode 100644
index 00000000..b927d572
--- /dev/null
+++ b/vendor/rustix/src/fs/copy_file_range.rs
@@ -0,0 +1,20 @@
+use crate::{backend, io};
+use backend::fd::AsFd;
+
+/// `copy_file_range(fd_in, off_in, fd_out, off_out, len, 0)`—Copies data
+/// from one file to another.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/copy_file_range.2.html
+#[inline]
+pub fn copy_file_range<InFd: AsFd, OutFd: AsFd>(
+ fd_in: InFd,
+ off_in: Option<&mut u64>,
+ fd_out: OutFd,
+ off_out: Option<&mut u64>,
+ len: usize,
+) -> io::Result<usize> {
+ backend::fs::syscalls::copy_file_range(fd_in.as_fd(), off_in, fd_out.as_fd(), off_out, len)
+}
diff --git a/vendor/rustix/src/fs/dir.rs b/vendor/rustix/src/fs/dir.rs
new file mode 100644
index 00000000..b3e1e3b9
--- /dev/null
+++ b/vendor/rustix/src/fs/dir.rs
@@ -0,0 +1,5 @@
+//! `Dir` and `DirEntry`.
+
+use crate::backend;
+
+pub use backend::fs::dir::{Dir, DirEntry};
diff --git a/vendor/rustix/src/fs/fadvise.rs b/vendor/rustix/src/fs/fadvise.rs
new file mode 100644
index 00000000..93d8e081
--- /dev/null
+++ b/vendor/rustix/src/fs/fadvise.rs
@@ -0,0 +1,28 @@
+use crate::{backend, io};
+use backend::fd::AsFd;
+use backend::fs::types::Advice;
+use core::num::NonZeroU64;
+
+/// `posix_fadvise(fd, offset, len, advice)`—Declares an expected access
+/// pattern for a file.
+///
+/// If `len` is `None`, the advice extends to the end of the file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [FreeBSD]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_fadvise.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/posix_fadvise.2.html
+/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=posix_fadvise&sektion=2
+#[inline]
+#[doc(alias = "posix_fadvise")]
+pub fn fadvise<Fd: AsFd>(
+ fd: Fd,
+ offset: u64,
+ len: Option<NonZeroU64>,
+ advice: Advice,
+) -> io::Result<()> {
+ backend::fs::syscalls::fadvise(fd.as_fd(), offset, len, advice)
+}
diff --git a/vendor/rustix/src/fs/fcntl.rs b/vendor/rustix/src/fs/fcntl.rs
new file mode 100644
index 00000000..ba5368c8
--- /dev/null
+++ b/vendor/rustix/src/fs/fcntl.rs
@@ -0,0 +1,107 @@
+//! The Unix `fcntl` function is effectively lots of different functions hidden
+//! behind a single dynamic dispatch interface. In order to provide a type-safe
+//! API, rustix makes them all separate functions so that they can have
+//! dedicated static type signatures.
+
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "espidf",
+ target_os = "fuchsia",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+use crate::fs::FlockOperation;
+use crate::{backend, io};
+use backend::fd::AsFd;
+use backend::fs::types::OFlags;
+
+/// `fcntl(fd, F_GETFL)`—Returns a file descriptor's access mode and status.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fcntl.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[inline]
+#[doc(alias = "F_GETFL")]
+pub fn fcntl_getfl<Fd: AsFd>(fd: Fd) -> io::Result<OFlags> {
+ backend::fs::syscalls::fcntl_getfl(fd.as_fd())
+}
+
+/// `fcntl(fd, F_SETFL, flags)`—Sets a file descriptor's status.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fcntl.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[inline]
+#[doc(alias = "F_SETFL")]
+pub fn fcntl_setfl<Fd: AsFd>(fd: Fd, flags: OFlags) -> io::Result<()> {
+ backend::fs::syscalls::fcntl_setfl(fd.as_fd(), flags)
+}
+
+/// `fcntl(fd, F_GET_SEALS)`—Return the seals for `fd`'s inode.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))]
+#[inline]
+#[doc(alias = "F_GET_SEALS")]
+pub fn fcntl_get_seals<Fd: AsFd>(fd: Fd) -> io::Result<SealFlags> {
+ backend::fs::syscalls::fcntl_get_seals(fd.as_fd())
+}
+
+#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))]
+use backend::fs::types::SealFlags;
+
+/// `fcntl(fd, F_ADD_SEALS)`—Add seals to `fd`'s inode.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))]
+#[inline]
+#[doc(alias = "F_ADD_SEALS")]
+pub fn fcntl_add_seals<Fd: AsFd>(fd: Fd, seals: SealFlags) -> io::Result<()> {
+ backend::fs::syscalls::fcntl_add_seals(fd.as_fd(), seals)
+}
+
+/// `fcntl(fd, F_SETLK)`—Acquire or release an `fcntl`-style lock.
+///
+/// This function doesn't currently have an offset or len; it currently always
+/// sets the `l_len` field to 0, which is a special case that means the entire
+/// file should be locked.
+///
+/// Unlike `flock`-style locks, `fcntl`-style locks are process-associated,
+/// meaning that they don't guard against being acquired by two threads in the
+/// same process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fcntl.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "espidf",
+ target_os = "fuchsia",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+#[inline]
+#[doc(alias = "F_SETLK")]
+#[doc(alias = "F_SETLKW")]
+pub fn fcntl_lock<Fd: AsFd>(fd: Fd, operation: FlockOperation) -> io::Result<()> {
+ backend::fs::syscalls::fcntl_lock(fd.as_fd(), operation)
+}
diff --git a/vendor/rustix/src/fs/fcntl_apple.rs b/vendor/rustix/src/fs/fcntl_apple.rs
new file mode 100644
index 00000000..a32e46d7
--- /dev/null
+++ b/vendor/rustix/src/fs/fcntl_apple.rs
@@ -0,0 +1,66 @@
+use crate::{backend, io};
+use backend::fd::AsFd;
+
+/// `fcntl(fd, F_RDADVISE, radvisory { offset, len })`
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+#[doc(alias = "F_RDADVISE")]
+#[inline]
+pub fn fcntl_rdadvise<Fd: AsFd>(fd: Fd, offset: u64, len: u64) -> io::Result<()> {
+ backend::fs::syscalls::fcntl_rdadvise(fd.as_fd(), offset, len)
+}
+
+/// `fcntl(fd, F_FULLFSYNC)`
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+#[doc(alias = "F_FULLSYNC")]
+#[inline]
+pub fn fcntl_fullfsync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ backend::fs::syscalls::fcntl_fullfsync(fd.as_fd())
+}
+
+/// `fcntl(fd, F_NOCACHE, value)`—Turn data caching off or on for a file
+/// descriptor.
+///
+/// See [this mailing list post] for additional information about the meanings
+/// of `F_NOCACHE` and `F_GLOBAL_NOCACHE`.
+///
+/// [this mailing list post]: https://lists.apple.com/archives/filesystem-dev/2007/Sep/msg00010.html
+///
+/// See also [`fcntl_global_nocache`].
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+#[doc(alias = "F_NOCACHE")]
+#[inline]
+pub fn fcntl_nocache<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> {
+ backend::fs::syscalls::fcntl_nocache(fd.as_fd(), value)
+}
+
+/// `fcntl(fd, F_GLOBAL_NOCACHE, value)`—Turn data caching off or on for all
+/// file descriptors.
+///
+/// See [this mailing list post] for additional information about the meanings
+/// of `F_NOCACHE` and `F_GLOBAL_NOCACHE`.
+///
+/// [this mailing list post]: https://lists.apple.com/archives/filesystem-dev/2007/Sep/msg00010.html
+///
+/// See also [`fcntl_nocache`].
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+#[doc(alias = "F_GLOBAL_NOCACHE")]
+#[inline]
+pub fn fcntl_global_nocache<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> {
+ backend::fs::syscalls::fcntl_global_nocache(fd.as_fd(), value)
+}
diff --git a/vendor/rustix/src/fs/fcopyfile.rs b/vendor/rustix/src/fs/fcopyfile.rs
new file mode 100644
index 00000000..e8f26ffd
--- /dev/null
+++ b/vendor/rustix/src/fs/fcopyfile.rs
@@ -0,0 +1,88 @@
+use crate::fs::CopyfileFlags;
+use crate::{backend, io};
+use backend::fd::AsFd;
+use backend::fs::types::copyfile_state_t;
+
+/// `fcopyfile(from, to, state, flags)`
+///
+/// # Safety
+///
+/// The `state` operand must be allocated with `copyfile_state_alloc` and not
+/// yet freed with `copyfile_state_free`.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub unsafe fn fcopyfile<FromFd: AsFd, ToFd: AsFd>(
+ from: FromFd,
+ to: ToFd,
+ state: copyfile_state_t,
+ flags: CopyfileFlags,
+) -> io::Result<()> {
+ backend::fs::syscalls::fcopyfile(from.as_fd(), to.as_fd(), state, flags)
+}
+
+/// `copyfile_state_alloc()`
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub fn copyfile_state_alloc() -> io::Result<copyfile_state_t> {
+ backend::fs::syscalls::copyfile_state_alloc()
+}
+
+/// `copyfile_state_free(state)`
+///
+/// # Safety
+///
+/// The `state` operand must be allocated with `copyfile_state_alloc` and not
+/// yet freed with `copyfile_state_free`.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub unsafe fn copyfile_state_free(state: copyfile_state_t) -> io::Result<()> {
+ backend::fs::syscalls::copyfile_state_free(state)
+}
+
+/// `copyfile_state_get(state, COPYFILE_STATE_COPIED)`
+///
+/// # Safety
+///
+/// The `state` operand must be allocated with `copyfile_state_alloc` and not
+/// yet freed with `copyfile_state_free`.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub unsafe fn copyfile_state_get_copied(state: copyfile_state_t) -> io::Result<u64> {
+ backend::fs::syscalls::copyfile_state_get_copied(state)
+}
+
+/// `copyfile_state_get(state, flags, dst)`
+///
+/// # Safety
+///
+/// The `state` operand must be allocated with `copyfile_state_alloc` and not
+/// yet freed with `copyfile_state_free`.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub unsafe fn copyfile_state_get(
+ state: copyfile_state_t,
+ flag: u32,
+ dst: *mut core::ffi::c_void,
+) -> io::Result<()> {
+ backend::fs::syscalls::copyfile_state_get(state, flag, dst)
+}
diff --git a/vendor/rustix/src/fs/fd.rs b/vendor/rustix/src/fs/fd.rs
new file mode 100644
index 00000000..7ce1b3a4
--- /dev/null
+++ b/vendor/rustix/src/fs/fd.rs
@@ -0,0 +1,331 @@
+//! Functions which operate on file descriptors.
+
+#[cfg(not(target_os = "wasi"))]
+use crate::fs::Mode;
+#[cfg(not(target_os = "wasi"))]
+use crate::fs::{Gid, Uid};
+use crate::fs::{SeekFrom, Timespec};
+use crate::{backend, io};
+use backend::fd::AsFd;
+#[cfg(not(any(
+ netbsdlike,
+ target_os = "dragonfly",
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "nto",
+ target_os = "redox",
+ target_os = "vita",
+)))]
+use backend::fs::types::FallocateFlags;
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "solaris",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+use backend::fs::types::FlockOperation;
+#[cfg(linux_kernel)]
+use backend::fs::types::FsWord;
+use backend::fs::types::Stat;
+#[cfg(not(any(
+ solarish,
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "netbsd",
+ target_os = "nto",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi",
+)))]
+use backend::fs::types::StatFs;
+#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
+use backend::fs::types::StatVfs;
+
+/// Timestamps used by [`utimensat`] and [`futimens`].
+///
+/// [`utimensat`]: crate::fs::utimensat
+/// [`futimens`]: crate::fs::futimens
+// This is `repr(C)` and specifically laid out to match the representation used
+// by `utimensat` and `futimens`, which expect 2-element arrays of timestamps.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct Timestamps {
+ /// The timestamp of the last access to a filesystem object.
+ pub last_access: Timespec,
+
+ /// The timestamp of the last modification of a filesystem object.
+ pub last_modification: Timespec,
+}
+
+/// The filesystem magic number for procfs.
+///
+/// See [the `fstatfs` manual page] for more information.
+///
+/// [the `fstatfs` manual page]: https://man7.org/linux/man-pages/man2/fstatfs.2.html#DESCRIPTION
+#[cfg(linux_kernel)]
+pub const PROC_SUPER_MAGIC: FsWord = backend::c::PROC_SUPER_MAGIC as FsWord;
+
+/// The filesystem magic number for NFS.
+///
+/// See [the `fstatfs` manual page] for more information.
+///
+/// [the `fstatfs` manual page]: https://man7.org/linux/man-pages/man2/fstatfs.2.html#DESCRIPTION
+#[cfg(linux_kernel)]
+pub const NFS_SUPER_MAGIC: FsWord = backend::c::NFS_SUPER_MAGIC as FsWord;
+
+/// `lseek(fd, offset, whence)`—Repositions a file descriptor within a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/lseek.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/lseek.2.html
+#[inline]
+#[doc(alias = "lseek")]
+pub fn seek<Fd: AsFd>(fd: Fd, pos: SeekFrom) -> io::Result<u64> {
+ backend::fs::syscalls::seek(fd.as_fd(), pos)
+}
+
+/// `lseek(fd, 0, SEEK_CUR)`—Returns the current position within a file.
+///
+/// Return the current position of the file descriptor. This is a subset of
+/// the functionality of `seek`, but this interface makes it easier for users
+/// to declare their intent not to mutate any state.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/lseek.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/lseek.2.html
+#[inline]
+#[doc(alias = "lseek")]
+pub fn tell<Fd: AsFd>(fd: Fd) -> io::Result<u64> {
+ backend::fs::syscalls::tell(fd.as_fd())
+}
+
+/// `fchmod(fd, mode)`—Sets open file or directory permissions.
+///
+/// This implementation does not support [`OFlags::PATH`] file descriptors,
+/// even on platforms where the host libc emulates it.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fchmod.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchmod.2.html
+/// [`OFlags::PATH`]: crate::fs::OFlags::PATH
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn fchmod<Fd: AsFd>(fd: Fd, mode: Mode) -> io::Result<()> {
+ backend::fs::syscalls::fchmod(fd.as_fd(), mode)
+}
+
+/// `fchown(fd, owner, group)`—Sets open file or directory ownership.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fchown.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchown.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn fchown<Fd: AsFd>(fd: Fd, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
+ backend::fs::syscalls::fchown(fd.as_fd(), owner, group)
+}
+
+/// `fstat(fd)`—Queries metadata for an open file or directory.
+///
+/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to
+/// interpret the `st_mode` field.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fstat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fstat.2.html
+/// [`Mode::from_raw_mode`]: Mode::from_raw_mode
+/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode
+#[inline]
+pub fn fstat<Fd: AsFd>(fd: Fd) -> io::Result<Stat> {
+ backend::fs::syscalls::fstat(fd.as_fd())
+}
+
+/// `fstatfs(fd)`—Queries filesystem statistics for an open file or directory.
+///
+/// Compared to [`fstatvfs`], this function often provides more information,
+/// though it's less portable.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fstatfs.2.html
+#[cfg(not(any(
+ solarish,
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "netbsd",
+ target_os = "nto",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi",
+)))]
+#[inline]
+pub fn fstatfs<Fd: AsFd>(fd: Fd) -> io::Result<StatFs> {
+ backend::fs::syscalls::fstatfs(fd.as_fd())
+}
+
+/// `fstatvfs(fd)`—Queries filesystem statistics for an open file or
+/// directory, POSIX version.
+///
+/// Compared to [`fstatfs`], this function often provides less information,
+/// but it is more portable. But even so, filesystems are very diverse and not
+/// all the fields are meaningful for every filesystem. And `f_fsid` doesn't
+/// seem to have a clear meaning anywhere.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fstatvfs.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fstatvfs.2.html
+#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub fn fstatvfs<Fd: AsFd>(fd: Fd) -> io::Result<StatVfs> {
+ backend::fs::syscalls::fstatvfs(fd.as_fd())
+}
+
+/// `futimens(fd, times)`—Sets timestamps for an open file or directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/futimens.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/utimensat.2.html
+#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
+#[inline]
+pub fn futimens<Fd: AsFd>(fd: Fd, times: &Timestamps) -> io::Result<()> {
+ backend::fs::syscalls::futimens(fd.as_fd(), times)
+}
+
+/// `fallocate(fd, mode, offset, len)`—Adjusts file allocation.
+///
+/// This is a more general form of `posix_fallocate`, adding a `mode` argument
+/// which modifies the behavior. On platforms which only support
+/// `posix_fallocate` and not the more general form, no `FallocateFlags` values
+/// are defined so it will always be empty.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux `fallocate`]
+/// - [Linux `posix_fallocate`]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_fallocate.html
+/// [Linux `fallocate`]: https://man7.org/linux/man-pages/man2/fallocate.2.html
+/// [Linux `posix_fallocate`]: https://man7.org/linux/man-pages/man3/posix_fallocate.3.html
+#[cfg(not(any(
+ netbsdlike,
+ target_os = "dragonfly",
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "nto",
+ target_os = "redox",
+ target_os = "vita",
+)))] // not implemented in libc for NetBSD yet
+#[inline]
+#[doc(alias = "posix_fallocate")]
+pub fn fallocate<Fd: AsFd>(fd: Fd, mode: FallocateFlags, offset: u64, len: u64) -> io::Result<()> {
+ backend::fs::syscalls::fallocate(fd.as_fd(), mode, offset, len)
+}
+
+/// `fsync(fd)`—Ensures that file data and metadata is written to the
+/// underlying storage device.
+///
+/// On iOS and macOS this isn't sufficient to ensure that data has reached
+/// persistent storage; use [`fcntl_fullfsync`] to ensure that.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fsync.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fsync.2.html
+/// [`fcntl_fullfsync`]: https://docs.rs/rustix/*/x86_64-apple-darwin/rustix/fs/fn.fcntl_fullfsync.html
+#[inline]
+pub fn fsync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ backend::fs::syscalls::fsync(fd.as_fd())
+}
+
+/// `fdatasync(fd)`—Ensures that file data is written to the underlying
+/// storage device.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/fdatasync.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fdatasync.2.html
+#[cfg(not(any(
+ apple,
+ target_os = "dragonfly",
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita",
+)))]
+#[inline]
+pub fn fdatasync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ backend::fs::syscalls::fdatasync(fd.as_fd())
+}
+
+/// `ftruncate(fd, length)`—Sets the length of a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/ftruncate.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/ftruncate.2.html
+#[inline]
+pub fn ftruncate<Fd: AsFd>(fd: Fd, length: u64) -> io::Result<()> {
+ backend::fs::syscalls::ftruncate(fd.as_fd(), length)
+}
+
+/// `flock(fd, operation)`—Acquire or release an advisory lock on an open file.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/flock.2.html
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "solaris",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+#[inline]
+pub fn flock<Fd: AsFd>(fd: Fd, operation: FlockOperation) -> io::Result<()> {
+ backend::fs::syscalls::flock(fd.as_fd(), operation)
+}
+
+/// `syncfs(fd)`—Flush cached filesystem data.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/syncfs.2.html
+#[cfg(linux_kernel)]
+#[inline]
+pub fn syncfs<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ backend::fs::syscalls::syncfs(fd.as_fd())
+}
diff --git a/vendor/rustix/src/fs/getpath.rs b/vendor/rustix/src/fs/getpath.rs
new file mode 100644
index 00000000..8e14ff2f
--- /dev/null
+++ b/vendor/rustix/src/fs/getpath.rs
@@ -0,0 +1,14 @@
+use crate::ffi::CString;
+use crate::{backend, io};
+use backend::fd::AsFd;
+
+/// `fcntl(fd, F_GETPATH)`
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+#[inline]
+pub fn getpath<Fd: AsFd>(fd: Fd) -> io::Result<CString> {
+ backend::fs::syscalls::getpath(fd.as_fd())
+}
diff --git a/vendor/rustix/src/fs/id.rs b/vendor/rustix/src/fs/id.rs
new file mode 100644
index 00000000..1fc2ef81
--- /dev/null
+++ b/vendor/rustix/src/fs/id.rs
@@ -0,0 +1 @@
+pub use crate::ugid::{Gid, Uid};
diff --git a/vendor/rustix/src/fs/inotify.rs b/vendor/rustix/src/fs/inotify.rs
new file mode 100644
index 00000000..ad03dfa6
--- /dev/null
+++ b/vendor/rustix/src/fs/inotify.rs
@@ -0,0 +1,219 @@
+//! inotify support for working with inotify objects.
+//!
+//! # Examples
+//!
+//! ```
+//! use rustix::fs::inotify;
+//! use rustix::io;
+//! use std::mem::MaybeUninit;
+//!
+//! # fn test() -> io::Result<()> {
+//! // Create an inotify object. In this example, we use `NONBLOCK` so that the
+//! // reader fails with `WOULDBLOCK` when no events are ready. Otherwise it
+//! // will block until at least one event is ready.
+//! let inotify = inotify::init(inotify::CreateFlags::NONBLOCK)?;
+//!
+//! // Add a directory to watch.
+//! inotify::add_watch(
+//! &inotify,
+//! "/path/to/some/directory/to/watch",
+//! inotify::WatchFlags::ALL_EVENTS,
+//! )?;
+//!
+//! // Generate some events in the watched directory…
+//!
+//! // Loop over pending events.
+//! let mut buf = [MaybeUninit::uninit(); 512];
+//! let mut iter = inotify::Reader::new(inotify, &mut buf);
+//! loop {
+//! let entry = match iter.next() {
+//! // Stop iterating if there are no more events for now.
+//! Err(io::Errno::WOULDBLOCK) => break,
+//! Err(e) => return Err(e),
+//! Ok(entry) => entry,
+//! };
+//!
+//! // Use `entry`…
+//! }
+//!
+//! # Ok(())
+//! # }
+
+#![allow(unused_qualifications)]
+
+use super::inotify;
+pub use crate::backend::fs::inotify::{CreateFlags, ReadFlags, WatchFlags};
+use crate::backend::fs::syscalls;
+use crate::fd::{AsFd, OwnedFd};
+use crate::ffi::CStr;
+use crate::io;
+use crate::io::{read, Errno};
+use core::mem::{align_of, size_of, MaybeUninit};
+use linux_raw_sys::general::inotify_event;
+
+/// `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")]
+#[inline]
+pub fn init(flags: inotify::CreateFlags) -> io::Result<OwnedFd> {
+ syscalls::inotify_init1(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.
+#[doc(alias = "inotify_add_watch")]
+#[inline]
+pub fn add_watch<P: crate::path::Arg, Fd: AsFd>(
+ inot: Fd,
+ path: P,
+ flags: inotify::WatchFlags,
+) -> io::Result<i32> {
+ path.into_with_c_str(|path| syscalls::inotify_add_watch(inot.as_fd(), path, flags))
+}
+
+/// `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")]
+#[inline]
+pub fn remove_watch<Fd: AsFd>(inot: Fd, wd: i32) -> io::Result<()> {
+ syscalls::inotify_rm_watch(inot.as_fd(), wd)
+}
+
+/// An inotify event iterator implemented with the read syscall.
+///
+/// See the [`RawDir`] API for more details and usage examples as this API is
+/// based on it.
+///
+/// [`RawDir`]: crate::fs::raw_dir::RawDir
+pub struct Reader<'buf, Fd: AsFd> {
+ fd: Fd,
+ buf: &'buf mut [MaybeUninit<u8>],
+ initialized: usize,
+ offset: usize,
+}
+
+impl<'buf, Fd: AsFd> Reader<'buf, Fd> {
+ /// Create a new iterator from the given file descriptor and buffer.
+ pub fn new(fd: Fd, buf: &'buf mut [MaybeUninit<u8>]) -> Self {
+ Self {
+ fd,
+ buf: {
+ let offset = buf.as_ptr().align_offset(align_of::<inotify_event>());
+ if offset < buf.len() {
+ &mut buf[offset..]
+ } else {
+ &mut []
+ }
+ },
+ initialized: 0,
+ offset: 0,
+ }
+ }
+}
+
+/// An inotify event.
+#[doc(alias = "inotify_event")]
+#[derive(Debug)]
+pub struct Event<'a> {
+ wd: i32,
+ events: ReadFlags,
+ cookie: u32,
+ file_name: Option<&'a CStr>,
+}
+
+impl<'a> Event<'a> {
+ /// Returns the watch for which this event occurs.
+ #[inline]
+ pub fn wd(&self) -> i32 {
+ self.wd
+ }
+
+ /// Returns a description of the events.
+ #[inline]
+ #[doc(alias = "mask")]
+ pub fn events(&self) -> ReadFlags {
+ self.events
+ }
+
+ /// Returns the unique cookie associating related events.
+ #[inline]
+ pub fn cookie(&self) -> u32 {
+ self.cookie
+ }
+
+ /// Returns the file name of this event, if any.
+ #[inline]
+ pub fn file_name(&self) -> Option<&CStr> {
+ self.file_name
+ }
+}
+
+impl<'buf, Fd: AsFd> Reader<'buf, Fd> {
+ /// Read the next inotify event.
+ ///
+ /// This is similar to [`Iterator::next`] except that it doesn't return an
+ /// `Option`, because the stream doesn't have an ending. It always returns
+ /// events or errors.
+ ///
+ /// If there are no events in the buffer and none ready to be read:
+ /// - If the file descriptor was opened with
+ /// [`inotify::CreateFlags::NONBLOCK`], this will fail with
+ /// [`Errno::AGAIN`].
+ /// - Otherwise this will block until at least one event is ready or an
+ /// error occurs.
+ #[allow(unsafe_code)]
+ #[allow(clippy::should_implement_trait)]
+ pub fn next(&mut self) -> io::Result<Event<'_>> {
+ if self.is_buffer_empty() {
+ match read(self.fd.as_fd(), &mut *self.buf).map(|(init, _)| init.len()) {
+ Ok(0) => return Err(Errno::INVAL),
+ Ok(bytes_read) => {
+ self.initialized = bytes_read;
+ self.offset = 0;
+ }
+ Err(e) => return Err(e),
+ }
+ }
+
+ let ptr = self.buf[self.offset..].as_ptr();
+
+ // SAFETY:
+ // - This data is initialized by the check above.
+ // - Assumption: the kernel will not give us partial structs.
+ // - Assumption: the kernel uses proper alignment between structs.
+ // - The starting pointer is aligned (performed in `Reader::new`).
+ let event = unsafe { &*ptr.cast::<inotify_event>() };
+
+ self.offset += size_of::<inotify_event>() + usize::try_from(event.len).unwrap();
+
+ Ok(Event {
+ wd: event.wd,
+ events: ReadFlags::from_bits_retain(event.mask),
+ cookie: event.cookie,
+ file_name: if event.len > 0 {
+ // SAFETY: The kernel guarantees a NUL-terminated string.
+ Some(unsafe { CStr::from_ptr(event.name.as_ptr().cast()) })
+ } else {
+ None
+ },
+ })
+ }
+
+ /// Returns true if the internal buffer is empty and will be refilled when
+ /// calling [`next`]. This is useful to avoid further blocking reads.
+ ///
+ /// [`next`]: Self::next
+ pub fn is_buffer_empty(&self) -> bool {
+ self.offset >= self.initialized
+ }
+}
diff --git a/vendor/rustix/src/fs/ioctl.rs b/vendor/rustix/src/fs/ioctl.rs
new file mode 100644
index 00000000..c126fdd1
--- /dev/null
+++ b/vendor/rustix/src/fs/ioctl.rs
@@ -0,0 +1,169 @@
+//! Filesystem-oriented `ioctl` functions.
+
+#![allow(unsafe_code)]
+
+#[cfg(linux_kernel)]
+use {
+ crate::backend::c,
+ crate::fd::AsFd,
+ crate::{backend, ffi, io, ioctl},
+};
+
+use bitflags::bitflags;
+
+#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))]
+use crate::fd::{AsRawFd as _, BorrowedFd};
+
+/// `ioctl(fd, BLKSSZGET)`—Returns the logical block size of a block device.
+///
+/// This is mentioned in the [Linux `openat` manual page].
+///
+/// [Linux `openat` manual page]: https://man7.org/linux/man-pages/man2/openat.2.html
+#[cfg(linux_kernel)]
+#[inline]
+#[doc(alias = "BLKSSZGET")]
+pub fn ioctl_blksszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
+ // SAFETY: `BLZSSZGET` is a getter opcode that gets a `u32`.
+ unsafe {
+ let ctl = ioctl::Getter::<{ c::BLKSSZGET }, c::c_uint>::new();
+ ioctl::ioctl(fd, ctl)
+ }
+}
+
+/// `ioctl(fd, BLKPBSZGET)`—Returns the physical block size of a block device.
+#[cfg(linux_kernel)]
+#[inline]
+#[doc(alias = "BLKPBSZGET")]
+pub fn ioctl_blkpbszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
+ // SAFETY: `BLKPBSZGET` is a getter opcode that gets a `u32`.
+ unsafe {
+ let ctl = ioctl::Getter::<{ c::BLKPBSZGET }, c::c_uint>::new();
+ ioctl::ioctl(fd, ctl)
+ }
+}
+
+/// `ioctl(fd, FICLONE, src_fd)`—Share data between open files.
+///
+/// This ioctl is not available on SPARC platforms.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_ficlone.2.html
+#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))]
+#[inline]
+#[doc(alias = "FICLONE")]
+pub fn ioctl_ficlone<Fd: AsFd, SrcFd: AsFd>(fd: Fd, src_fd: SrcFd) -> io::Result<()> {
+ unsafe { ioctl::ioctl(fd, Ficlone(src_fd.as_fd())) }
+}
+
+/// `ioctl(fd, EXT4_IOC_RESIZE_FS, blocks)`—Resize ext4 filesystem on fd.
+#[cfg(linux_kernel)]
+#[inline]
+#[doc(alias = "EXT4_IOC_RESIZE_FS")]
+pub fn ext4_ioc_resize_fs<Fd: AsFd>(fd: Fd, blocks: u64) -> io::Result<()> {
+ // SAFETY: `EXT4_IOC_RESIZE_FS` is a pointer setter opcode.
+ unsafe {
+ let ctl = ioctl::Setter::<{ backend::fs::EXT4_IOC_RESIZE_FS }, u64>::new(blocks);
+ ioctl::ioctl(fd, ctl)
+ }
+}
+
+#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))]
+struct Ficlone<'a>(BorrowedFd<'a>);
+
+#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))]
+unsafe impl ioctl::Ioctl for Ficlone<'_> {
+ type Output = ();
+
+ const IS_MUTATING: bool = false;
+
+ fn opcode(&self) -> ioctl::Opcode {
+ c::FICLONE as ioctl::Opcode
+ }
+
+ fn as_ptr(&mut self) -> *mut c::c_void {
+ self.0.as_raw_fd() as *mut c::c_void
+ }
+
+ unsafe fn output_from_ptr(
+ _: ioctl::IoctlOutput,
+ _: *mut c::c_void,
+ ) -> io::Result<Self::Output> {
+ Ok(())
+ }
+}
+
+#[cfg(linux_kernel)]
+bitflags! {
+ /// `FS_*` constants for use with [`ioctl_getflags`].
+ ///
+ /// [`ioctl_getflags`]: crate::fs::ioctl::ioctl_getflags
+ #[repr(transparent)]
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct IFlags: ffi::c_uint {
+ /// `FS_APPEND_FL`
+ const APPEND = linux_raw_sys::general::FS_APPEND_FL;
+ /// `FS_COMPR_FL`
+ const COMPRESSED = linux_raw_sys::general::FS_COMPR_FL;
+ /// `FS_DIRSYNC_FL`
+ const DIRSYNC = linux_raw_sys::general::FS_DIRSYNC_FL;
+ /// `FS_IMMUTABLE_FL`
+ const IMMUTABLE = linux_raw_sys::general::FS_IMMUTABLE_FL;
+ /// `FS_JOURNAL_DATA_FL`
+ const JOURNALING = linux_raw_sys::general::FS_JOURNAL_DATA_FL;
+ /// `FS_NOATIME_FL`
+ const NOATIME = linux_raw_sys::general::FS_NOATIME_FL;
+ /// `FS_NOCOW_FL`
+ const NOCOW = linux_raw_sys::general::FS_NOCOW_FL;
+ /// `FS_NODUMP_FL`
+ const NODUMP = linux_raw_sys::general::FS_NODUMP_FL;
+ /// `FS_NOTAIL_FL`
+ const NOTAIL = linux_raw_sys::general::FS_NOTAIL_FL;
+ /// `FS_PROJINHERIT_FL`
+ const PROJECT_INHERIT = linux_raw_sys::general::FS_PROJINHERIT_FL;
+ /// `FS_SECRM_FL`
+ const SECURE_REMOVAL = linux_raw_sys::general::FS_SECRM_FL;
+ /// `FS_SYNC_FL`
+ const SYNC = linux_raw_sys::general::FS_SYNC_FL;
+ /// `FS_TOPDIR_FL`
+ const TOPDIR = linux_raw_sys::general::FS_TOPDIR_FL;
+ /// `FS_UNRM_FL`
+ const UNRM = linux_raw_sys::general::FS_UNRM_FL;
+ }
+}
+
+/// `ioctl(fd, FS_IOC_GETFLAGS)`—Returns the [inode flags] attributes
+///
+/// [inode flags]: https://man7.org/linux/man-pages/man2/ioctl_iflags.2.html
+#[cfg(linux_kernel)]
+#[inline]
+#[doc(alias = "FS_IOC_GETFLAGS")]
+pub fn ioctl_getflags<Fd: AsFd>(fd: Fd) -> io::Result<IFlags> {
+ unsafe {
+ #[cfg(target_pointer_width = "32")]
+ let ctl = ioctl::Getter::<{ c::FS_IOC32_GETFLAGS }, u32>::new();
+ #[cfg(target_pointer_width = "64")]
+ let ctl = ioctl::Getter::<{ c::FS_IOC_GETFLAGS }, u32>::new();
+
+ ioctl::ioctl(fd, ctl).map(IFlags::from_bits_retain)
+ }
+}
+
+/// `ioctl(fd, FS_IOC_SETFLAGS)`—Modify the [inode flags] attributes
+///
+/// [inode flags]: https://man7.org/linux/man-pages/man2/ioctl_iflags.2.html
+#[cfg(linux_kernel)]
+#[inline]
+#[doc(alias = "FS_IOC_SETFLAGS")]
+pub fn ioctl_setflags<Fd: AsFd>(fd: Fd, flags: IFlags) -> io::Result<()> {
+ unsafe {
+ #[cfg(target_pointer_width = "32")]
+ let ctl = ioctl::Setter::<{ c::FS_IOC32_SETFLAGS }, u32>::new(flags.bits());
+
+ #[cfg(target_pointer_width = "64")]
+ let ctl = ioctl::Setter::<{ c::FS_IOC_SETFLAGS }, u32>::new(flags.bits());
+
+ ioctl::ioctl(fd, ctl)
+ }
+}
diff --git a/vendor/rustix/src/fs/makedev.rs b/vendor/rustix/src/fs/makedev.rs
new file mode 100644
index 00000000..e6cf5c0e
--- /dev/null
+++ b/vendor/rustix/src/fs/makedev.rs
@@ -0,0 +1,35 @@
+use crate::backend;
+use crate::fs::Dev;
+
+/// `makedev(maj, min)`—Compute a device ID from a given major and minor ID.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/makedev.3.html
+#[inline]
+pub fn makedev(maj: u32, min: u32) -> Dev {
+ backend::fs::makedev::makedev(maj, min)
+}
+
+/// `minor(dev)`—Compute the minor ID of a given device ID.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/minor.3.html
+#[inline]
+pub fn minor(dev: Dev) -> u32 {
+ backend::fs::makedev::minor(dev)
+}
+
+/// `major(dev)`—Compute the major ID of a given device ID.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/major.3.html
+#[inline]
+pub fn major(dev: Dev) -> u32 {
+ backend::fs::makedev::major(dev)
+}
diff --git a/vendor/rustix/src/fs/memfd_create.rs b/vendor/rustix/src/fs/memfd_create.rs
new file mode 100644
index 00000000..6e49771f
--- /dev/null
+++ b/vendor/rustix/src/fs/memfd_create.rs
@@ -0,0 +1,22 @@
+use crate::fd::OwnedFd;
+use crate::{backend, io, path};
+use backend::fs::types::MemfdFlags;
+
+/// `memfd_create(name, flags)`—Create an anonymous file.
+///
+/// For a higher-level API to this functionality, see the [memfd] crate.
+///
+/// [memfd]: https://crates.io/crates/memfd
+///
+/// # References
+/// - [Linux]
+/// - [glibc]
+/// - [FreeBSD]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
+/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Memory_002dmapped-I_002fO.html#index-memfd_005fcreate
+/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?memfd_create
+#[inline]
+pub fn memfd_create<P: path::Arg>(name: P, flags: MemfdFlags) -> io::Result<OwnedFd> {
+ name.into_with_c_str(|name| backend::fs::syscalls::memfd_create(name, flags))
+}
diff --git a/vendor/rustix/src/fs/mod.rs b/vendor/rustix/src/fs/mod.rs
new file mode 100644
index 00000000..505925f7
--- /dev/null
+++ b/vendor/rustix/src/fs/mod.rs
@@ -0,0 +1,141 @@
+//! Filesystem operations.
+
+mod abs;
+#[cfg(not(target_os = "redox"))]
+mod at;
+mod constants;
+#[cfg(linux_kernel)]
+mod copy_file_range;
+#[cfg(all(feature = "alloc", not(any(target_os = "espidf", target_os = "redox"))))]
+mod dir;
+#[cfg(not(any(
+ apple,
+ netbsdlike,
+ target_os = "dragonfly",
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "vita",
+)))]
+mod fadvise;
+pub(crate) mod fcntl;
+#[cfg(apple)]
+mod fcntl_apple;
+#[cfg(apple)]
+mod fcopyfile;
+pub(crate) mod fd;
+#[cfg(all(apple, feature = "alloc"))]
+mod getpath;
+#[cfg(not(target_os = "wasi"))] // WASI doesn't have get[gpu]id.
+mod id;
+#[cfg(linux_kernel)]
+pub mod inotify;
+#[cfg(linux_kernel)]
+mod ioctl;
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+mod makedev;
+#[cfg(any(linux_kernel, target_os = "freebsd"))]
+mod memfd_create;
+#[cfg(linux_kernel)]
+mod openat2;
+#[cfg(linux_kernel)]
+mod raw_dir;
+mod seek_from;
+#[cfg(target_os = "linux")]
+mod sendfile;
+#[cfg(not(any(target_os = "espidf", target_os = "redox")))]
+mod special;
+#[cfg(linux_kernel)]
+mod statx;
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+mod sync;
+#[cfg(any(apple, linux_kernel, target_os = "hurd"))]
+mod xattr;
+
+pub use abs::*;
+#[cfg(not(target_os = "redox"))]
+pub use at::*;
+pub use constants::*;
+#[cfg(linux_kernel)]
+pub use copy_file_range::copy_file_range;
+#[cfg(all(feature = "alloc", not(any(target_os = "espidf", target_os = "redox"))))]
+pub use dir::{Dir, DirEntry};
+#[cfg(not(any(
+ apple,
+ netbsdlike,
+ target_os = "dragonfly",
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "vita",
+)))]
+pub use fadvise::fadvise;
+pub use fcntl::*;
+#[cfg(apple)]
+pub use fcntl_apple::*;
+#[cfg(apple)]
+pub use fcopyfile::*;
+pub use fd::*;
+#[cfg(all(apple, feature = "alloc"))]
+pub use getpath::getpath;
+#[cfg(not(target_os = "wasi"))]
+pub use id::*;
+#[cfg(linux_kernel)]
+pub use ioctl::*;
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+pub use makedev::*;
+#[cfg(any(linux_kernel, target_os = "freebsd"))]
+pub use memfd_create::memfd_create;
+#[cfg(linux_kernel)]
+pub use openat2::openat2;
+#[cfg(linux_kernel)]
+pub use raw_dir::{RawDir, RawDirEntry};
+pub use seek_from::SeekFrom;
+#[cfg(target_os = "linux")]
+pub use sendfile::sendfile;
+#[cfg(not(any(target_os = "espidf", target_os = "redox")))]
+pub use special::*;
+#[cfg(linux_kernel)]
+pub use statx::*;
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
+pub use sync::sync;
+#[cfg(any(apple, linux_kernel, target_os = "hurd"))]
+pub use xattr::*;
+
+/// Re-export types common to POSIX-ish platforms.
+#[cfg(feature = "std")]
+#[cfg(unix)]
+pub use std::os::unix::fs::{DirEntryExt, FileExt, FileTypeExt, MetadataExt, OpenOptionsExt};
+#[cfg(feature = "std")]
+#[cfg(all(wasi_ext, target_os = "wasi"))]
+pub use std::os::wasi::fs::{DirEntryExt, FileExt, FileTypeExt, MetadataExt, OpenOptionsExt};
diff --git a/vendor/rustix/src/fs/openat2.rs b/vendor/rustix/src/fs/openat2.rs
new file mode 100644
index 00000000..0a0e1d16
--- /dev/null
+++ b/vendor/rustix/src/fs/openat2.rs
@@ -0,0 +1,24 @@
+use crate::fd::OwnedFd;
+use crate::{backend, io, path};
+use backend::fd::AsFd;
+use backend::fs::types::{Mode, OFlags, ResolveFlags};
+
+/// `openat2(dirfd, path, OpenHow { oflags, mode, resolve }, sizeof(OpenHow))`—
+/// Opens a file with more options.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/openat2.2.html
+#[inline]
+pub fn openat2<Fd: AsFd, P: path::Arg>(
+ dirfd: Fd,
+ path: P,
+ oflags: OFlags,
+ mode: Mode,
+ resolve: ResolveFlags,
+) -> io::Result<OwnedFd> {
+ path.into_with_c_str(|path| {
+ backend::fs::syscalls::openat2(dirfd.as_fd(), path, oflags, mode, resolve)
+ })
+}
diff --git a/vendor/rustix/src/fs/raw_dir.rs b/vendor/rustix/src/fs/raw_dir.rs
new file mode 100644
index 00000000..7fec6fd7
--- /dev/null
+++ b/vendor/rustix/src/fs/raw_dir.rs
@@ -0,0 +1,236 @@
+//! `RawDir` and `RawDirEntry`.
+
+use crate::backend::fs::syscalls::getdents_uninit;
+use crate::fd::AsFd;
+use crate::ffi::CStr;
+use crate::fs::FileType;
+use crate::io;
+use core::fmt;
+use core::mem::{align_of, MaybeUninit};
+use linux_raw_sys::general::linux_dirent64;
+
+/// A directory iterator implemented with getdents.
+///
+/// Note: This implementation does not handle growing the buffer. If this
+/// functionality is necessary, you'll need to drop the current iterator,
+/// resize the buffer, and then re-create the iterator. The iterator is
+/// guaranteed to continue where it left off provided the file descriptor isn't
+/// changed. See the example in [`RawDir::new`].
+pub struct RawDir<'buf, Fd: AsFd> {
+ fd: Fd,
+ buf: &'buf mut [MaybeUninit<u8>],
+ initialized: usize,
+ offset: usize,
+}
+
+impl<'buf, Fd: AsFd> RawDir<'buf, Fd> {
+ /// Create a new iterator from the given file descriptor and buffer.
+ ///
+ /// Note: the buffer size may be trimmed to accommodate alignment
+ /// requirements.
+ ///
+ /// # Examples
+ ///
+ /// ## Simple but non-portable
+ ///
+ /// These examples are non-portable, because file systems may not have a
+ /// maximum file name length. If you can make assumptions that bound
+ /// this length, then these examples may suffice.
+ ///
+ /// Using the heap:
+ ///
+ /// ```
+ /// # use std::mem::MaybeUninit;
+ /// # use rustix::fs::{CWD, Mode, OFlags, openat, RawDir};
+ /// # use rustix::cstr;
+ ///
+ /// let fd = openat(
+ /// CWD,
+ /// cstr!("."),
+ /// OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC,
+ /// Mode::empty(),
+ /// )
+ /// .unwrap();
+ ///
+ /// let mut buf = Vec::with_capacity(8192);
+ /// let mut iter = RawDir::new(fd, buf.spare_capacity_mut());
+ /// while let Some(entry) = iter.next() {
+ /// let entry = entry.unwrap();
+ /// dbg!(&entry);
+ /// }
+ /// ```
+ ///
+ /// Using the stack:
+ ///
+ /// ```
+ /// # use std::mem::MaybeUninit;
+ /// # use rustix::fs::{CWD, Mode, OFlags, openat, RawDir};
+ /// # use rustix::cstr;
+ ///
+ /// let fd = openat(
+ /// CWD,
+ /// cstr!("."),
+ /// OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC,
+ /// Mode::empty(),
+ /// )
+ /// .unwrap();
+ ///
+ /// let mut buf = [MaybeUninit::uninit(); 2048];
+ /// let mut iter = RawDir::new(fd, &mut buf);
+ /// while let Some(entry) = iter.next() {
+ /// let entry = entry.unwrap();
+ /// dbg!(&entry);
+ /// }
+ /// ```
+ ///
+ /// ## Portable
+ ///
+ /// Heap allocated growing buffer for supporting directory entries with
+ /// arbitrarily large file names:
+ ///
+ /// ```ignore
+ /// # // The `ignore` above can be removed when we can depend on Rust 1.65.
+ /// # use std::mem::MaybeUninit;
+ /// # use rustix::fs::{CWD, Mode, OFlags, openat, RawDir};
+ /// # use rustix::io::Errno;
+ /// # use rustix::cstr;
+ ///
+ /// let fd = openat(
+ /// CWD,
+ /// cstr!("."),
+ /// OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC,
+ /// Mode::empty(),
+ /// )
+ /// .unwrap();
+ ///
+ /// let mut buf = Vec::with_capacity(8192);
+ /// 'read: loop {
+ /// 'resize: {
+ /// let mut iter = RawDir::new(&fd, buf.spare_capacity_mut());
+ /// while let Some(entry) = iter.next() {
+ /// let entry = match entry {
+ /// Err(Errno::INVAL) => break 'resize,
+ /// r => r.unwrap(),
+ /// };
+ /// dbg!(&entry);
+ /// }
+ /// break 'read;
+ /// }
+ ///
+ /// let new_capacity = buf.capacity() * 2;
+ /// buf.reserve(new_capacity);
+ /// }
+ /// ```
+ pub fn new(fd: Fd, buf: &'buf mut [MaybeUninit<u8>]) -> Self {
+ Self {
+ fd,
+ buf: {
+ let offset = buf.as_ptr().align_offset(align_of::<linux_dirent64>());
+ if offset < buf.len() {
+ &mut buf[offset..]
+ } else {
+ &mut []
+ }
+ },
+ initialized: 0,
+ offset: 0,
+ }
+ }
+}
+
+/// A raw directory entry, similar to [`std::fs::DirEntry`].
+///
+/// Unlike the std version, this may represent the `.` or `..` entries.
+pub struct RawDirEntry<'a> {
+ file_name: &'a CStr,
+ file_type: u8,
+ inode_number: u64,
+ next_entry_cookie: i64,
+}
+
+impl<'a> fmt::Debug for RawDirEntry<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut f = f.debug_struct("RawDirEntry");
+ f.field("file_name", &self.file_name());
+ f.field("file_type", &self.file_type());
+ f.field("ino", &self.ino());
+ f.field("next_entry_cookie", &self.next_entry_cookie());
+ f.finish()
+ }
+}
+
+impl<'a> RawDirEntry<'a> {
+ /// Returns the file name of this directory entry.
+ #[inline]
+ pub fn file_name(&self) -> &CStr {
+ self.file_name
+ }
+
+ /// Returns the type of this directory entry.
+ #[inline]
+ pub fn file_type(&self) -> FileType {
+ FileType::from_dirent_d_type(self.file_type)
+ }
+
+ /// Returns the inode number of this directory entry.
+ #[inline]
+ #[doc(alias = "inode_number")]
+ pub fn ino(&self) -> u64 {
+ self.inode_number
+ }
+
+ /// Returns the seek cookie to the next directory entry.
+ #[inline]
+ #[doc(alias = "off")]
+ pub fn next_entry_cookie(&self) -> u64 {
+ self.next_entry_cookie as u64
+ }
+}
+
+impl<'buf, Fd: AsFd> RawDir<'buf, Fd> {
+ /// Identical to [`Iterator::next`] except that [`Iterator::Item`] borrows
+ /// from self.
+ ///
+ /// Note: this interface will be broken to implement a stdlib iterator API
+ /// with GAT support once one becomes available.
+ #[allow(unsafe_code)]
+ #[allow(clippy::should_implement_trait)]
+ pub fn next(&mut self) -> Option<io::Result<RawDirEntry<'_>>> {
+ if self.is_buffer_empty() {
+ match getdents_uninit(self.fd.as_fd(), self.buf) {
+ Ok(0) => return None,
+ Ok(bytes_read) => {
+ self.initialized = bytes_read;
+ self.offset = 0;
+ }
+ Err(e) => return Some(Err(e)),
+ }
+ }
+
+ let dirent_ptr = self.buf[self.offset..].as_ptr();
+ // SAFETY:
+ // - This data is initialized by the check above.
+ // - Assumption: the kernel will not give us partial structs.
+ // - Assumption: the kernel uses proper alignment between structs.
+ // - The starting pointer is aligned (performed in `RawDir::new`).
+ let dirent = unsafe { &*dirent_ptr.cast::<linux_dirent64>() };
+
+ self.offset += usize::from(dirent.d_reclen);
+
+ Some(Ok(RawDirEntry {
+ file_type: dirent.d_type,
+ inode_number: dirent.d_ino.into(),
+ next_entry_cookie: dirent.d_off.into(),
+ // SAFETY: The kernel guarantees a NUL-terminated string.
+ file_name: unsafe { CStr::from_ptr(dirent.d_name.as_ptr().cast()) },
+ }))
+ }
+
+ /// Returns true if the internal buffer is empty and will be refilled when
+ /// calling [`next`].
+ ///
+ /// [`next`]: Self::next
+ pub fn is_buffer_empty(&self) -> bool {
+ self.offset >= self.initialized
+ }
+}
diff --git a/vendor/rustix/src/fs/seek_from.rs b/vendor/rustix/src/fs/seek_from.rs
new file mode 100644
index 00000000..bc0907ca
--- /dev/null
+++ b/vendor/rustix/src/fs/seek_from.rs
@@ -0,0 +1,53 @@
+//! The following is derived from Rust's
+//! library/std/src/io/mod.rs at revision
+//! dca3f1b786efd27be3b325ed1e01e247aa589c3b.
+
+/// Enumeration of possible methods to seek within an I/O object.
+///
+/// It is used by the [`seek`] function.
+///
+/// This is similar to [`std::io::SeekFrom`], however it adds platform-specific
+/// seek options.
+///
+/// [`seek`]: crate::fs::seek
+#[derive(Copy, PartialEq, Eq, Clone, Debug)]
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub enum SeekFrom {
+ /// Sets the offset to the provided number of bytes.
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ Start(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] u64),
+
+ /// Sets the offset to the size of this object plus the specified number of
+ /// bytes.
+ ///
+ /// It is possible to seek beyond the end of an object, but it's an error
+ /// to seek before byte 0.
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ End(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64),
+
+ /// Sets the offset to the current position plus the specified number of
+ /// bytes.
+ ///
+ /// It is possible to seek beyond the end of an object, but it's an error
+ /// to seek before byte 0.
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ Current(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64),
+
+ /// Sets the offset to the current position plus the specified number of
+ /// bytes, plus the distance to the next byte which is not in a hole.
+ ///
+ /// If the offset is in a hole at the end of the file, the seek will fail
+ /// with [`Errno::NXIO`].
+ ///
+ /// [`Errno::NXIO`]: crate::io::Errno::NXIO
+ #[cfg(any(apple, freebsdlike, linux_kernel, solarish))]
+ Data(u64),
+
+ /// Sets the offset to the current position plus the specified number of
+ /// bytes, plus the distance to the next byte which is in a hole.
+ ///
+ /// If there is no hole past the offset, it will be set to the end of the
+ /// file i.e. there is an implicit hole at the end of any file.
+ #[cfg(any(apple, freebsdlike, linux_kernel, solarish))]
+ Hole(u64),
+}
diff --git a/vendor/rustix/src/fs/sendfile.rs b/vendor/rustix/src/fs/sendfile.rs
new file mode 100644
index 00000000..db3d6022
--- /dev/null
+++ b/vendor/rustix/src/fs/sendfile.rs
@@ -0,0 +1,20 @@
+use crate::{backend, io};
+use backend::fd::AsFd;
+
+/// `sendfile(out_fd, in_fd, offset, count)`—Transfer data between file
+/// descriptors.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/sendfile.2.html
+#[cfg(linux_kernel)]
+#[inline]
+pub fn sendfile<OutFd: AsFd, InFd: AsFd>(
+ out_fd: OutFd,
+ in_fd: InFd,
+ offset: Option<&mut u64>,
+ count: usize,
+) -> io::Result<usize> {
+ backend::fs::syscalls::sendfile(out_fd.as_fd(), in_fd.as_fd(), offset, count)
+}
diff --git a/vendor/rustix/src/fs/special.rs b/vendor/rustix/src/fs/special.rs
new file mode 100644
index 00000000..276a775f
--- /dev/null
+++ b/vendor/rustix/src/fs/special.rs
@@ -0,0 +1,80 @@
+//! The `CWD` and `ABS` constants, representing the current working directory
+//! and absolute-only paths, respectively.
+//!
+//! # Safety
+//!
+//! This file uses `AT_FDCWD`, which is a raw file descriptor, but which is
+//! always valid, and `-EBADF`, which is an undocumented by commonly used
+//! convention of passing a value which will always fail if the accompanying
+//! path isn't absolute.
+
+#![allow(unsafe_code)]
+
+use crate::backend;
+use backend::c;
+use backend::fd::{BorrowedFd, RawFd};
+
+/// `AT_FDCWD`—A handle representing the current working directory.
+///
+/// This is a file descriptor which refers to the process current directory
+/// which can be used as the directory argument in `*at` functions such as
+/// [`openat`].
+///
+/// # References
+/// - [POSIX]
+///
+/// [`openat`]: crate::fs::openat
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fcntl.h.html
+// SAFETY: `AT_FDCWD` is a reserved value that is never dynamically
+// allocated, so it'll remain valid for the duration of `'static`.
+#[cfg(not(target_os = "horizon"))]
+#[doc(alias = "AT_FDCWD")]
+pub const CWD: BorrowedFd<'static> =
+ unsafe { BorrowedFd::<'static>::borrow_raw(c::AT_FDCWD as RawFd) };
+
+/// `-EBADF`—A handle that requires paths to be absolute.
+///
+/// This is a file descriptor which refers to no directory, which can be used
+/// as the directory argument in `*at` functions such as [`openat`], which
+/// causes them to fail with [`BADF`] if the accompanying path is not absolute.
+///
+/// This corresponds to the undocumented by commonly used convention of
+/// passing `-EBADF` as the `dirfd` argument, which is ignored if the path is
+/// absolute, and evokes an `EBADF` error otherwise.
+///
+/// [`openat`]: crate::fs::openat
+/// [`BADF`]: crate::io::Errno::BADF
+// SAFETY: This `-EBADF` convention is commonly used, such as in lxc, so OS's
+// aren't going to break it.
+pub const ABS: BorrowedFd<'static> =
+ unsafe { BorrowedFd::<'static>::borrow_raw(c::EBADF.wrapping_neg() as RawFd) };
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::fd::AsRawFd as _;
+
+ #[test]
+ fn test_cwd() {
+ assert!(CWD.as_raw_fd() != -1);
+ assert!(CWD.as_raw_fd() != c::STDIN_FILENO);
+ assert!(CWD.as_raw_fd() != c::STDOUT_FILENO);
+ assert!(CWD.as_raw_fd() != c::STDERR_FILENO);
+ #[cfg(linux_kernel)]
+ #[cfg(feature = "io_uring")]
+ assert!(CWD.as_raw_fd() != crate::io_uring::IORING_REGISTER_FILES_SKIP.as_raw_fd());
+ }
+
+ #[test]
+ fn test_abs() {
+ assert!(ABS.as_raw_fd() < 0);
+ assert!(ABS.as_raw_fd() != -1);
+ assert!(ABS.as_raw_fd() != c::AT_FDCWD);
+ assert!(ABS.as_raw_fd() != c::STDIN_FILENO);
+ assert!(ABS.as_raw_fd() != c::STDOUT_FILENO);
+ assert!(ABS.as_raw_fd() != c::STDERR_FILENO);
+ #[cfg(linux_kernel)]
+ #[cfg(feature = "io_uring")]
+ assert!(ABS.as_raw_fd() != crate::io_uring::IORING_REGISTER_FILES_SKIP.as_raw_fd());
+ }
+}
diff --git a/vendor/rustix/src/fs/statx.rs b/vendor/rustix/src/fs/statx.rs
new file mode 100644
index 00000000..f1d995ec
--- /dev/null
+++ b/vendor/rustix/src/fs/statx.rs
@@ -0,0 +1,275 @@
+//! Linux `statx`.
+
+use crate::fd::AsFd;
+use crate::fs::AtFlags;
+use crate::{backend, io, path};
+use backend::c;
+use bitflags::bitflags;
+
+#[cfg(feature = "linux_4_11")]
+use backend::fs::syscalls::statx as _statx;
+#[cfg(not(feature = "linux_4_11"))]
+use compat::statx as _statx;
+
+/// `struct statx` for use with [`statx`].
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+#[allow(missing_docs)]
+#[non_exhaustive]
+pub struct Statx {
+ pub stx_mask: u32,
+ pub stx_blksize: u32,
+ pub stx_attributes: StatxAttributes,
+ pub stx_nlink: u32,
+ pub stx_uid: u32,
+ pub stx_gid: u32,
+ pub stx_mode: u16,
+ pub(crate) __spare0: [u16; 1],
+ pub stx_ino: u64,
+ pub stx_size: u64,
+ pub stx_blocks: u64,
+ pub stx_attributes_mask: StatxAttributes,
+ 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,
+ pub stx_dio_mem_align: u32,
+ pub stx_dio_offset_align: u32,
+ pub stx_subvol: u64,
+ pub stx_atomic_write_unit_min: u32,
+ pub stx_atomic_write_unit_max: u32,
+ pub stx_atomic_write_segments_max: u32,
+ pub(crate) __spare1: [u32; 1],
+ pub(crate) __spare3: [u64; 9],
+}
+
+/// `struct statx_timestamp` for use with [`Statx`].
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+#[non_exhaustive]
+pub struct StatxTimestamp {
+ /// Seconds.
+ pub tv_sec: i64,
+
+ /// Nanoseconds. Must be less than 1_000_000_000.
+ pub tv_nsec: u32,
+
+ pub(crate) __reserved: i32,
+}
+
+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;
+ }
+}
+
+bitflags! {
+ /// `STATX_ATTR_*` flags for use with [`Statx`].
+ #[repr(transparent)]
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct StatxAttributes: u64 {
+ /// `STATX_ATTR_COMPRESSED`
+ const COMPRESSED = c::STATX_ATTR_COMPRESSED as u64;
+
+ /// `STATX_ATTR_IMMUTABLE`
+ const IMMUTABLE = c::STATX_ATTR_IMMUTABLE as u64;
+
+ /// `STATX_ATTR_APPEND`
+ const APPEND = c::STATX_ATTR_APPEND as u64;
+
+ /// `STATX_ATTR_NODUMP`
+ const NODUMP = c::STATX_ATTR_NODUMP as u64;
+
+ /// `STATX_ATTR_ENCRYPTED`
+ const ENCRYPTED = c::STATX_ATTR_ENCRYPTED as u64;
+
+ /// `STATX_ATTR_AUTOMOUNT`
+ const AUTOMOUNT = c::STATX_ATTR_AUTOMOUNT as u64;
+
+ /// `STATX_ATTR_MOUNT_ROOT`
+ const MOUNT_ROOT = c::STATX_ATTR_MOUNT_ROOT as u64;
+
+ /// `STATX_ATTR_VERITY`
+ const VERITY = c::STATX_ATTR_VERITY as u64;
+
+ /// `STATX_ATTR_DAX`
+ const DAX = c::STATX_ATTR_DAX as u64;
+
+ /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
+ const _ = !0;
+ }
+}
+
+/// `statx(dirfd, path, flags, mask, statxbuf)`—Extended `stat`.
+///
+/// This function returns [`io::Errno::NOSYS`] if `statx` is not available on
+/// the platform, such as Linux before 4.11. This also includes older Docker
+/// versions where the actual syscall fails with different error codes; rustix
+/// handles this and translates them into `NOSYS`.
+///
+/// # References
+/// - [Linux]
+///
+/// # Examples
+///
+/// ```
+/// # use std::path::Path;
+/// # use std::io;
+/// # use rustix::fs::{AtFlags, StatxFlags};
+/// # use rustix::fd::BorrowedFd;
+/// /// Try to determine if the provided path is a mount root. Will return
+/// /// `Ok(None)` if the kernel is not new enough to support `statx` or
+/// /// [`StatxAttributes::MOUNT_ROOT`].
+/// fn is_mountpoint(root: BorrowedFd<'_>, path: &Path) -> io::Result<Option<bool>> {
+/// use rustix::fs::{AtFlags, StatxAttributes, StatxFlags};
+///
+/// match rustix::fs::statx(
+/// root,
+/// path,
+/// AtFlags::NO_AUTOMOUNT | AtFlags::SYMLINK_NOFOLLOW,
+/// StatxFlags::empty(),
+/// ) {
+/// Ok(r) => {
+/// let present = r.stx_attributes_mask.contains(StatxAttributes::MOUNT_ROOT);
+/// Ok(present.then(|| r.stx_attributes.contains(StatxAttributes::MOUNT_ROOT)))
+/// }
+/// Err(rustix::io::Errno::NOSYS) => Ok(None),
+/// Err(e) => Err(e.into()),
+/// }
+/// }
+/// ```
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/statx.2.html
+#[inline]
+pub fn statx<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ flags: AtFlags,
+ mask: StatxFlags,
+) -> io::Result<Statx> {
+ path.into_with_c_str(|path| _statx(dirfd.as_fd(), path, flags, mask))
+}
+
+#[cfg(not(feature = "linux_4_11"))]
+mod compat {
+ use crate::fd::BorrowedFd;
+ use crate::ffi::CStr;
+ use crate::fs::{AtFlags, Statx, StatxFlags};
+ use crate::{backend, io};
+ use core::sync::atomic::{AtomicU8, Ordering};
+
+ // Linux kernel prior to 4.11 and old versions of Docker don't support
+ // `statx`. We store the availability in a global to avoid unnecessary
+ // syscalls.
+ //
+ // 0: Unknown
+ // 1: Not available
+ // 2: Available
+ static STATX_STATE: AtomicU8 = AtomicU8::new(0);
+
+ #[inline]
+ pub fn statx(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ flags: AtFlags,
+ mask: StatxFlags,
+ ) -> io::Result<Statx> {
+ match STATX_STATE.load(Ordering::Relaxed) {
+ 0 => statx_init(dirfd, path, flags, mask),
+ 1 => Err(io::Errno::NOSYS),
+ _ => backend::fs::syscalls::statx(dirfd, path, flags, mask),
+ }
+ }
+
+ /// The first `statx` call. We don't know if `statx` is available yet.
+ fn statx_init(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ flags: AtFlags,
+ mask: StatxFlags,
+ ) -> io::Result<Statx> {
+ match backend::fs::syscalls::statx(dirfd, path, flags, mask) {
+ Err(err) => statx_error(err),
+ result => {
+ STATX_STATE.store(2, Ordering::Relaxed);
+ result
+ }
+ }
+ }
+
+ /// The first `statx` call failed. We can get a variety of error codes
+ /// from seccomp configs or faulty FUSE drivers, so we don't trust
+ /// `ENOSYS` or `EPERM` to tell us whether statx is available.
+ #[cold]
+ fn statx_error(err: io::Errno) -> io::Result<Statx> {
+ if backend::fs::syscalls::is_statx_available() {
+ // Statx is available. Record this, and fail with the error
+ // code of the initial `statx` call.
+ STATX_STATE.store(2, Ordering::Relaxed);
+ Err(err)
+ } else {
+ // Statx is not available. Record this, and fail with `NOSYS`.
+ STATX_STATE.store(1, Ordering::Relaxed);
+ Err(io::Errno::NOSYS)
+ }
+ }
+}
diff --git a/vendor/rustix/src/fs/sync.rs b/vendor/rustix/src/fs/sync.rs
new file mode 100644
index 00000000..cb5f0704
--- /dev/null
+++ b/vendor/rustix/src/fs/sync.rs
@@ -0,0 +1,14 @@
+use crate::backend;
+
+/// `sync`—Flush cached filesystem data for all filesystems.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/sync.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/sync.2.html
+#[inline]
+pub fn sync() {
+ backend::fs::syscalls::sync();
+}
diff --git a/vendor/rustix/src/fs/xattr.rs b/vendor/rustix/src/fs/xattr.rs
new file mode 100644
index 00000000..ea0eaea1
--- /dev/null
+++ b/vendor/rustix/src/fs/xattr.rs
@@ -0,0 +1,256 @@
+//! Extended attribute functions.
+
+#![allow(unsafe_code)]
+
+use crate::buffer::Buffer;
+use crate::{backend, ffi, io, path};
+use backend::c;
+use backend::fd::AsFd;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `XATTR_*` constants for use with [`setxattr`], and other `*setxattr`
+ /// functions.
+ #[repr(transparent)]
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct XattrFlags: ffi::c_uint {
+ /// `XATTR_CREATE`
+ const CREATE = c::XATTR_CREATE as c::c_uint;
+
+ /// `XATTR_REPLACE`
+ const REPLACE = c::XATTR_REPLACE as c::c_uint;
+
+ /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
+ const _ = !0;
+ }
+}
+
+/// `getxattr(path, name, value)`—Get extended filesystem attributes.
+///
+/// For a higher-level API to xattr functionality, see the [xattr] crate.
+///
+/// [xattr]: https://crates.io/crates/xattr
+///
+/// # References
+/// - [Linux]
+/// - [Apple]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/getxattr.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getxattr.2.html
+#[inline]
+pub fn getxattr<P: path::Arg, Name: path::Arg, Buf: Buffer<u8>>(
+ path: P,
+ name: Name,
+ mut value: Buf,
+) -> io::Result<Buf::Output> {
+ path.into_with_c_str(|path| {
+ name.into_with_c_str(|name| {
+ // SAFETY: `getxattr` behaves.
+ let len = unsafe { backend::fs::syscalls::getxattr(path, name, value.parts_mut())? };
+ // SAFETY: `getxattr` behaves.
+ unsafe { Ok(value.assume_init(len)) }
+ })
+ })
+}
+
+/// `lgetxattr(path, name, value.as_ptr(), value.len())`—Get extended
+/// filesystem attributes, without following symlinks in the last path
+/// component.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/lgetxattr.2.html
+#[inline]
+pub fn lgetxattr<P: path::Arg, Name: path::Arg, Buf: Buffer<u8>>(
+ path: P,
+ name: Name,
+ mut value: Buf,
+) -> io::Result<Buf::Output> {
+ path.into_with_c_str(|path| {
+ name.into_with_c_str(|name| {
+ // SAFETY: `lgetxattr` behaves.
+ let len = unsafe { backend::fs::syscalls::lgetxattr(path, name, value.parts_mut())? };
+ // SAFETY: `lgetxattr` behaves.
+ unsafe { Ok(value.assume_init(len)) }
+ })
+ })
+}
+
+/// `fgetxattr(fd, name, value.as_ptr(), value.len())`—Get extended
+/// filesystem attributes on an open file descriptor.
+///
+/// # References
+/// - [Linux]
+/// - [Apple]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fgetxattr.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fgetxattr.2.html
+#[inline]
+pub fn fgetxattr<Fd: AsFd, Name: path::Arg, Buf: Buffer<u8>>(
+ fd: Fd,
+ name: Name,
+ mut value: Buf,
+) -> io::Result<Buf::Output> {
+ name.into_with_c_str(|name| {
+ // SAFETY: `fgetxattr` behaves.
+ let len = unsafe { backend::fs::syscalls::fgetxattr(fd.as_fd(), name, value.parts_mut())? };
+ // SAFETY: `fgetxattr` behaves.
+ unsafe { Ok(value.assume_init(len)) }
+ })
+}
+
+/// `setxattr(path, name, value.as_ptr(), value.len(), flags)`—Set extended
+/// filesystem attributes.
+///
+/// # References
+/// - [Linux]
+/// - [Apple]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/setxattr.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setxattr.2.html
+#[inline]
+pub fn setxattr<P: path::Arg, Name: path::Arg>(
+ path: P,
+ name: Name,
+ value: &[u8],
+ flags: XattrFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| {
+ name.into_with_c_str(|name| backend::fs::syscalls::setxattr(path, name, value, flags))
+ })
+}
+
+/// `setxattr(path, name, value.as_ptr(), value.len(), flags)`—Set extended
+/// filesystem attributes, without following symlinks in the last path
+/// component.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/lsetxattr.2.html
+#[inline]
+pub fn lsetxattr<P: path::Arg, Name: path::Arg>(
+ path: P,
+ name: Name,
+ value: &[u8],
+ flags: XattrFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| {
+ name.into_with_c_str(|name| backend::fs::syscalls::lsetxattr(path, name, value, flags))
+ })
+}
+
+/// `fsetxattr(fd, name, value.as_ptr(), value.len(), flags)`—Set extended
+/// filesystem attributes on an open file descriptor.
+///
+/// # References
+/// - [Linux]
+/// - [Apple]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fsetxattr.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fsetxattr.2.html
+#[inline]
+pub fn fsetxattr<Fd: AsFd, Name: path::Arg>(
+ fd: Fd,
+ name: Name,
+ value: &[u8],
+ flags: XattrFlags,
+) -> io::Result<()> {
+ name.into_with_c_str(|name| backend::fs::syscalls::fsetxattr(fd.as_fd(), name, value, flags))
+}
+
+/// `listxattr(path, list.as_ptr(), list.len())`—List extended filesystem
+/// attributes.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/listxattr.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/listxattr.2.html
+#[inline]
+pub fn listxattr<P: path::Arg, Buf: Buffer<u8>>(path: P, mut list: Buf) -> io::Result<Buf::Output> {
+ path.into_with_c_str(|path| {
+ // SAFETY: `listxattr` behaves.
+ let len = unsafe { backend::fs::syscalls::listxattr(path, list.parts_mut())? };
+ // SAFETY: `listxattr` behaves.
+ unsafe { Ok(list.assume_init(len)) }
+ })
+}
+
+/// `llistxattr(path, list.as_ptr(), list.len())`—List extended filesystem
+/// attributes, without following symlinks in the last path component.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/llistxattr.2.html
+#[inline]
+pub fn llistxattr<P: path::Arg, Buf: Buffer<u8>>(
+ path: P,
+ mut list: Buf,
+) -> io::Result<Buf::Output> {
+ path.into_with_c_str(|path| {
+ // SAFETY: `flistxattr` behaves.
+ let len = unsafe { backend::fs::syscalls::llistxattr(path, list.parts_mut())? };
+ // SAFETY: `flistxattr` behaves.
+ unsafe { Ok(list.assume_init(len)) }
+ })
+}
+
+/// `flistxattr(fd, list.as_ptr(), list.len())`—List extended filesystem
+/// attributes on an open file descriptor.
+///
+/// # References
+/// - [Linux]
+/// - [Apple]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/flistxattr.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/flistxattr.2.html
+#[inline]
+pub fn flistxattr<Fd: AsFd, Buf: Buffer<u8>>(fd: Fd, mut list: Buf) -> io::Result<Buf::Output> {
+ // SAFETY: `flistxattr` behaves.
+ let len = unsafe { backend::fs::syscalls::flistxattr(fd.as_fd(), list.parts_mut())? };
+ // SAFETY: `flistxattr` behaves.
+ unsafe { Ok(list.assume_init(len)) }
+}
+
+/// `removexattr(path, name)`—Remove an extended filesystem attribute.
+///
+/// # References
+/// - [Linux]
+/// - [Apple]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/removexattr.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/removexattr.2.html
+pub fn removexattr<P: path::Arg, Name: path::Arg>(path: P, name: Name) -> io::Result<()> {
+ path.into_with_c_str(|path| {
+ name.into_with_c_str(|name| backend::fs::syscalls::removexattr(path, name))
+ })
+}
+
+/// `lremovexattr(path, name)`—Remove an extended filesystem attribute,
+/// without following symlinks in the last path component.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/lremovexattr.2.html
+pub fn lremovexattr<P: path::Arg, Name: path::Arg>(path: P, name: Name) -> io::Result<()> {
+ path.into_with_c_str(|path| {
+ name.into_with_c_str(|name| backend::fs::syscalls::lremovexattr(path, name))
+ })
+}
+
+/// `fremovexattr(fd, name)`—Remove an extended filesystem attribute on an
+/// open file descriptor.
+///
+/// # References
+/// - [Linux]
+/// - [Apple]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fremovexattr.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fremovexattr.2.html
+pub fn fremovexattr<Fd: AsFd, Name: path::Arg>(fd: Fd, name: Name) -> io::Result<()> {
+ name.into_with_c_str(|name| backend::fs::syscalls::fremovexattr(fd.as_fd(), name))
+}