summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/io
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/io')
-rw-r--r--vendor/rustix/src/io/close.rs41
-rw-r--r--vendor/rustix/src/io/dup.rs80
-rw-r--r--vendor/rustix/src/io/errno.rs85
-rw-r--r--vendor/rustix/src/io/eventfd.rs16
-rw-r--r--vendor/rustix/src/io/fd/mod.rs17
-rw-r--r--vendor/rustix/src/io/fd/owned.rs252
-rw-r--r--vendor/rustix/src/io/fd/raw.rs159
-rw-r--r--vendor/rustix/src/io/ioctl.rs99
-rw-r--r--vendor/rustix/src/io/is_read_write.rs16
-rw-r--r--vendor/rustix/src/io/mod.rs74
-rw-r--r--vendor/rustix/src/io/owned_fd.rs272
-rw-r--r--vendor/rustix/src/io/pipe.rs53
-rw-r--r--vendor/rustix/src/io/poll.rs20
-rw-r--r--vendor/rustix/src/io/procfs.rs482
-rw-r--r--vendor/rustix/src/io/read_write.rs170
-rw-r--r--vendor/rustix/src/io/seek_from.rs30
-rw-r--r--vendor/rustix/src/io/stdio.rs194
17 files changed, 2060 insertions, 0 deletions
diff --git a/vendor/rustix/src/io/close.rs b/vendor/rustix/src/io/close.rs
new file mode 100644
index 000000000..2116f53bd
--- /dev/null
+++ b/vendor/rustix/src/io/close.rs
@@ -0,0 +1,41 @@
+//! The unsafe `close` for raw file descriptors.
+//!
+//! # Safety
+//!
+//! Operating on raw file descriptors is unsafe.
+#![allow(unsafe_code)]
+
+use crate::imp;
+use imp::fd::RawFd;
+
+/// `close(raw_fd)`—Closes a `RawFd` directly.
+///
+/// Most users won't need to use this, as `OwnedFd` automatically closes its
+/// file descriptor on `Drop`.
+///
+/// This function does not return a `Result`, as it is the [responsibility] of
+/// filesystem designers to not return errors from `close`. Users who chose to
+/// use NFS or similar filesystems should take care to monitor for problems
+/// externally.
+///
+/// [responsibility]: https://lwn.net/Articles/576518/
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/close.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/close.2.html#//apple_ref/doc/man/2/close
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket
+///
+/// # Safety
+///
+/// This function takes a `RawFd`, which must be valid before the call, and is
+/// not valid after the call.
+#[inline]
+pub unsafe fn close(raw_fd: RawFd) {
+ imp::io::syscalls::close(raw_fd)
+}
diff --git a/vendor/rustix/src/io/dup.rs b/vendor/rustix/src/io/dup.rs
new file mode 100644
index 000000000..ffa0401f2
--- /dev/null
+++ b/vendor/rustix/src/io/dup.rs
@@ -0,0 +1,80 @@
+//! Functions which duplicate file descriptors.
+
+use crate::imp;
+use crate::io::{self, OwnedFd};
+use imp::fd::AsFd;
+
+#[cfg(not(target_os = "wasi"))]
+pub use imp::io::types::DupFlags;
+
+/// `dup(fd)`—Creates a new `OwnedFd` instance that shares the same
+/// underlying [file description] as `fd`.
+///
+/// This function does not set the `O_CLOEXEC` flag. To do a `dup` that does
+/// set `O_CLOEXEC`, use [`fcntl_dupfd_cloexec`].
+///
+/// POSIX guarantees that `dup` 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.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
+/// [`fcntl_dupfd_cloexec`]: crate::fs::fcntl_dupfd_cloexec
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/dup.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/dup.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn dup<Fd: AsFd>(fd: Fd) -> io::Result<OwnedFd> {
+ imp::io::syscalls::dup(fd.as_fd())
+}
+
+/// `dup2(fd, new)`—Changes the [file description] of a file descriptor.
+///
+/// `dup2` conceptually closes `new` and then sets the file description for
+/// `new` to be the same as the one for `fd`. This is a very unusual operation,
+/// and should only be used on file descriptors where you know how `new` will
+/// be subsequently used.
+///
+/// This function does not set the `O_CLOEXEC` flag. To do a `dup2` that does
+/// set `O_CLOEXEC`, use [`dup3`] with [`DupFlags::CLOEXEC`] on platforms which
+/// support it, or [`fcntl_dupfd_cloexec`]
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
+/// [`fcntl_dupfd_cloexec`]: crate::fs::fcntl_dupfd_cloexec
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/dup2.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/dup2.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn dup2<Fd: AsFd>(fd: Fd, new: &mut OwnedFd) -> io::Result<()> {
+ imp::io::syscalls::dup2(fd.as_fd(), new)
+}
+
+/// `dup3(fd, new, flags)`—Changes the [file description] of a file
+/// descriptor, with flags.
+///
+/// `dup3` is the same as [`dup2`] but adds an additional flags operand, and it
+/// fails in the case that `fd` and `new` have the same file descriptor value.
+/// This additional difference is the reason this function isn't named
+/// `dup2_with`.
+///
+/// # References
+/// - [Linux]
+///
+/// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
+/// [Linux]: https://man7.org/linux/man-pages/man2/dup3.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn dup3<Fd: AsFd>(fd: Fd, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()> {
+ imp::io::syscalls::dup3(fd.as_fd(), new, flags)
+}
diff --git a/vendor/rustix/src/io/errno.rs b/vendor/rustix/src/io/errno.rs
new file mode 100644
index 000000000..84ced6a37
--- /dev/null
+++ b/vendor/rustix/src/io/errno.rs
@@ -0,0 +1,85 @@
+//! The `Errno` type, which is a minimal wrapper around an error code.
+//!
+//! We define the error constants as individual `const`s instead of an
+//! enum because we may not know about all of the host's error values
+//! and we don't want unrecognized values to create UB.
+
+use crate::imp;
+use core::{fmt, result};
+#[cfg(feature = "std")]
+use std::error;
+
+/// A specialized [`Result`] type for `rustix` APIs.
+///
+/// [`Result`]: core::result::Result
+pub type Result<T> = result::Result<T, Errno>;
+
+/// `errno`—An error code.
+///
+/// The error type for `rustix` APIs. This is similar to `std::io::Error`, but
+/// only holds an OS error code, and no extra error value.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/errno.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/errno.3.html
+pub use imp::io::errno::Errno;
+
+impl Errno {
+ /// Shorthand for `std::io::Error::from(self).kind()`.
+ #[cfg(feature = "std")]
+ #[inline]
+ pub fn kind(self) -> std::io::ErrorKind {
+ std::io::Error::from(self).kind()
+ }
+}
+
+impl fmt::Display for Errno {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ #[cfg(feature = "std")]
+ {
+ std::io::Error::from(*self).fmt(fmt)
+ }
+ #[cfg(not(feature = "std"))]
+ {
+ write!(fmt, "os error {}", self.raw_os_error())
+ }
+ }
+}
+
+impl fmt::Debug for Errno {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ #[cfg(feature = "std")]
+ {
+ std::io::Error::from(*self).fmt(fmt)
+ }
+ #[cfg(not(feature = "std"))]
+ {
+ write!(fmt, "os error {}", self.raw_os_error())
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl error::Error for Errno {}
+
+#[cfg(feature = "std")]
+impl From<Errno> for std::io::Error {
+ #[inline]
+ fn from(err: Errno) -> Self {
+ Self::from_raw_os_error(err.raw_os_error() as _)
+ }
+}
+
+/// Call `f` until it either succeeds or fails other than [`Errno::INTR`].
+#[inline]
+pub fn retry_on_intr<T, F: FnMut() -> Result<T>>(mut f: F) -> Result<T> {
+ loop {
+ match f() {
+ Err(Errno::INTR) => (),
+ result => return result,
+ }
+ }
+}
diff --git a/vendor/rustix/src/io/eventfd.rs b/vendor/rustix/src/io/eventfd.rs
new file mode 100644
index 000000000..53e9d11f0
--- /dev/null
+++ b/vendor/rustix/src/io/eventfd.rs
@@ -0,0 +1,16 @@
+use crate::imp;
+use crate::io::{self, OwnedFd};
+
+pub use imp::io::types::EventfdFlags;
+
+/// `eventfd(initval, flags)`—Creates a file descriptor for event
+/// notification.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/eventfd.2.html
+#[inline]
+pub fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
+ imp::io::syscalls::eventfd(initval, flags)
+}
diff --git a/vendor/rustix/src/io/fd/mod.rs b/vendor/rustix/src/io/fd/mod.rs
new file mode 100644
index 000000000..0978b5421
--- /dev/null
+++ b/vendor/rustix/src/io/fd/mod.rs
@@ -0,0 +1,17 @@
+//! The following is derived from Rust's
+//! library/std/src/os/fd/mod.rs at revision
+//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9.
+//!
+//! Owned and borrowed Unix-like file descriptors.
+
+#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+#![deny(unsafe_op_in_unsafe_fn)]
+
+// `RawFd`, `AsRawFd`, etc.
+mod raw;
+
+// `OwnedFd`, `AsFd`, etc.
+mod owned;
+
+pub use owned::*;
+pub use raw::*;
diff --git a/vendor/rustix/src/io/fd/owned.rs b/vendor/rustix/src/io/fd/owned.rs
new file mode 100644
index 000000000..d99b6a0f9
--- /dev/null
+++ b/vendor/rustix/src/io/fd/owned.rs
@@ -0,0 +1,252 @@
+//! The following is derived from Rust's
+//! library/std/src/os/fd/owned.rs at revision
+//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9.
+//!
+//! Owned and borrowed Unix-like file descriptors.
+
+#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![allow(unsafe_code)]
+
+use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+use crate::io::close;
+use core::fmt;
+use core::marker::PhantomData;
+use core::mem::forget;
+
+/// A borrowed file descriptor.
+///
+/// This has a lifetime parameter to tie it to the lifetime of something that
+/// owns the file descriptor.
+///
+/// This uses `repr(transparent)` and has the representation of a host file
+/// descriptor, so it can be used in FFI in places where a file descriptor is
+/// passed as an argument, it is not captured or consumed, and it never has the
+/// value `-1`.
+///
+/// This type's `.to_owned()` implementation returns another `BorrowedFd`
+/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file
+/// descriptor, which is then borrowed under the same lifetime.
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))]
+// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
+// 32-bit c_int. Below is -2, in two's complement, but that only works out
+// because c_int is 32 bits.
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)]
+pub struct BorrowedFd<'fd> {
+ fd: RawFd,
+ _phantom: PhantomData<&'fd OwnedFd>,
+}
+
+/// An owned file descriptor.
+///
+/// This closes the file descriptor on drop.
+///
+/// This uses `repr(transparent)` and has the representation of a host file
+/// descriptor, so it can be used in FFI in places where a file descriptor is
+/// passed as a consumed argument or returned as an owned value, and it never
+/// has the value `-1`.
+#[repr(transparent)]
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))]
+// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
+// 32-bit c_int. Below is -2, in two's complement, but that only works out
+// because c_int is 32 bits.
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)]
+pub struct OwnedFd {
+ fd: RawFd,
+}
+
+impl BorrowedFd<'_> {
+ /// Return a `BorrowedFd` holding the given raw file descriptor.
+ ///
+ /// # Safety
+ ///
+ /// The resource pointed to by `fd` must remain open for the duration of
+ /// the returned `BorrowedFd`, and it must not have the value `-1`.
+ #[inline]
+ #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+ pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
+ assert!(fd != u32::MAX as RawFd);
+ // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
+ #[allow(unused_unsafe)]
+ unsafe {
+ Self {
+ fd,
+ _phantom: PhantomData,
+ }
+ }
+ }
+}
+
+impl OwnedFd {
+ /// Creates a new `OwnedFd` instance that shares the same underlying file handle
+ /// as the existing `OwnedFd` instance.
+ #[cfg(not(target_arch = "wasm32"))]
+ pub fn try_clone(&self) -> crate::io::Result<Self> {
+ // We want to atomically duplicate this file descriptor and set the
+ // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
+ // is a POSIX flag that was added to Linux in 2.6.24.
+ #[cfg(not(target_os = "espidf"))]
+ let fd = crate::fs::fcntl_dupfd_cloexec(self, 0)?;
+
+ // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics
+ // will never be supported, as this is a bare metal framework with
+ // no capabilities for multi-process execution. While F_DUPFD is also
+ // not supported yet, it might be (currently it returns ENOSYS).
+ #[cfg(target_os = "espidf")]
+ let fd = crate::fs::fcntl_dupfd(self)?;
+
+ Ok(fd.into())
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ pub fn try_clone(&self) -> crate::io::Result<Self> {
+ Err(crate::io::const_io_error!(
+ crate::io::ErrorKind::Unsupported,
+ "operation not supported on WASI yet",
+ ))
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl AsRawFd for BorrowedFd<'_> {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ self.fd
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl AsRawFd for OwnedFd {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ self.fd
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl IntoRawFd for OwnedFd {
+ #[inline]
+ fn into_raw_fd(self) -> RawFd {
+ let fd = self.fd;
+ forget(self);
+ fd
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl FromRawFd for OwnedFd {
+ /// Constructs a new instance of `Self` from the given raw file descriptor.
+ ///
+ /// # Safety
+ ///
+ /// The resource pointed to by `fd` must be open and suitable for assuming
+ /// ownership. The resource must not require any cleanup other than `close`.
+ #[inline]
+ unsafe fn from_raw_fd(fd: RawFd) -> Self {
+ assert_ne!(fd, u32::MAX as RawFd);
+ // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
+ #[allow(unused_unsafe)]
+ unsafe {
+ Self { fd }
+ }
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl Drop for OwnedFd {
+ #[inline]
+ fn drop(&mut self) {
+ unsafe {
+ // Errors are ignored when closing a file descriptor. The reason
+ // for this is that if an error occurs we don't actually know if
+ // the file descriptor was closed or not, and if we retried (for
+ // something like EINTR), we might close another valid file
+ // descriptor opened after we closed ours.
+ let _ = close(self.fd as _);
+ }
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl fmt::Debug for BorrowedFd<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("BorrowedFd").field("fd", &self.fd).finish()
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl fmt::Debug for OwnedFd {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("OwnedFd").field("fd", &self.fd).finish()
+ }
+}
+
+/// A trait to borrow the file descriptor from an underlying object.
+///
+/// This is only available on unix platforms and must be imported in order to
+/// call the method. Windows platforms have a corresponding `AsHandle` and
+/// `AsSocket` set of traits.
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+pub trait AsFd {
+ /// Borrows the file descriptor.
+ ///
+ /// # Example
+ ///
+ /// ```rust,no_run
+ /// # #![feature(io_safety)]
+ /// use std::fs::File;
+ /// # use std::io;
+ /// # #[cfg(target_os = "wasi")]
+ /// # use std::os::wasi::io::{AsFd, BorrowedFd};
+ /// # #[cfg(unix)]
+ /// # use std::os::unix::io::{AsFd, BorrowedFd};
+ ///
+ /// let mut f = File::open("foo.txt")?;
+ /// # #[cfg(any(unix, target_os = "wasi"))]
+ /// let borrowed_fd: BorrowedFd<'_> = f.as_fd();
+ /// # Ok::<(), io::Error>(())
+ /// ```
+ #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+ fn as_fd(&self) -> BorrowedFd<'_>;
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl<T: AsFd> AsFd for &T {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ T::as_fd(self)
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl<T: AsFd> AsFd for &mut T {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ T::as_fd(self)
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl AsFd for BorrowedFd<'_> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ *self
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl AsFd for OwnedFd {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ // Safety: `OwnedFd` and `BorrowedFd` have the same validity
+ // invariants, and the `BorrowedFd` is bounded by the lifetime
+ // of `&self`.
+ unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
+ }
+}
diff --git a/vendor/rustix/src/io/fd/raw.rs b/vendor/rustix/src/io/fd/raw.rs
new file mode 100644
index 000000000..44322d9fe
--- /dev/null
+++ b/vendor/rustix/src/io/fd/raw.rs
@@ -0,0 +1,159 @@
+//! The following is derived from Rust's
+//! library/std/src/os/fd/raw.rs at revision
+//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9.
+//!
+//! Raw Unix-like file descriptors.
+
+#![cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+#![allow(unsafe_code)]
+
+use crate::imp::c;
+
+/// Raw file descriptors.
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub type RawFd = c::c_int;
+
+/// A trait to extract the raw file descriptor from an underlying object.
+///
+/// This is only available on unix and WASI platforms and must be imported in
+/// order to call the method. Windows platforms have a corresponding
+/// `AsRawHandle` and `AsRawSocket` set of traits.
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub trait AsRawFd {
+ /// Extracts the raw file descriptor.
+ ///
+ /// This function is typically used to **borrow** an owned file descriptor.
+ /// When used in this way, this method does **not** pass ownership of the
+ /// raw file descriptor to the caller, and the file descriptor is only
+ /// guaranteed to be valid while the original object has not yet been
+ /// destroyed.
+ ///
+ /// However, borrowing is not strictly required. See [`AsFd::as_fd`]
+ /// for an API which strictly borrows a file descriptor.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// # use std::io;
+ /// #[cfg(unix)]
+ /// use std::os::unix::io::{AsRawFd, RawFd};
+ /// #[cfg(target_os = "wasi")]
+ /// use std::os::wasi::io::{AsRawFd, RawFd};
+ ///
+ /// let mut f = File::open("foo.txt")?;
+ /// // `raw_fd` is only valid as long as `f` exists.
+ /// #[cfg(any(unix, target_os = "wasi"))]
+ /// let raw_fd: RawFd = f.as_raw_fd();
+ /// # Ok::<(), io::Error>(())
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ fn as_raw_fd(&self) -> RawFd;
+}
+
+/// A trait to express the ability to construct an object from a raw file
+/// descriptor.
+#[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))]
+pub trait FromRawFd {
+ /// Constructs a new instance of `Self` from the given raw file
+ /// descriptor.
+ ///
+ /// This function is typically used to **consume ownership** of the
+ /// specified file descriptor. When used in this way, the returned object
+ /// will take responsibility for closing it when the object goes out of
+ /// scope.
+ ///
+ /// However, consuming ownership is not strictly required. Use a
+ /// [`From<OwnedFd>::from`] implementation for an API which strictly
+ /// consumes ownership.
+ ///
+ /// # Safety
+ ///
+ /// The `fd` passed in must be a valid an open file descriptor.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// # use std::io;
+ /// #[cfg(unix)]
+ /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
+ /// #[cfg(target_os = "wasi")]
+ /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd};
+ ///
+ /// let f = File::open("foo.txt")?;
+ /// # #[cfg(any(unix, target_os = "wasi"))]
+ /// let raw_fd: RawFd = f.into_raw_fd();
+ /// // SAFETY: no other functions should call `from_raw_fd`, so there
+ /// // is only one owner for the file descriptor.
+ /// # #[cfg(any(unix, target_os = "wasi"))]
+ /// let f = unsafe { File::from_raw_fd(raw_fd) };
+ /// # Ok::<(), io::Error>(())
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))]
+ unsafe fn from_raw_fd(fd: RawFd) -> Self;
+}
+
+/// A trait to express the ability to consume an object and acquire ownership of
+/// its raw file descriptor.
+#[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))]
+pub trait IntoRawFd {
+ /// Consumes this object, returning the raw underlying file descriptor.
+ ///
+ /// This function is typically used to **transfer ownership** of the underlying
+ /// file descriptor to the caller. When used in this way, callers are then the unique
+ /// owners of the file descriptor and must close it once it's no longer needed.
+ ///
+ /// However, transferring ownership is not strictly required. Use a
+ /// [`Into<OwnedFd>::into`] implementation for an API which strictly
+ /// transfers ownership.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// # use std::io;
+ /// #[cfg(unix)]
+ /// use std::os::unix::io::{IntoRawFd, RawFd};
+ /// #[cfg(target_os = "wasi")]
+ /// use std::os::wasi::io::{IntoRawFd, RawFd};
+ ///
+ /// let f = File::open("foo.txt")?;
+ /// #[cfg(any(unix, target_os = "wasi"))]
+ /// let raw_fd: RawFd = f.into_raw_fd();
+ /// # Ok::<(), io::Error>(())
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))]
+ fn into_raw_fd(self) -> RawFd;
+}
+
+#[cfg_attr(
+ staged_api,
+ stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")
+)]
+impl AsRawFd for RawFd {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ *self
+ }
+}
+#[cfg_attr(
+ staged_api,
+ stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")
+)]
+impl IntoRawFd for RawFd {
+ #[inline]
+ fn into_raw_fd(self) -> RawFd {
+ self
+ }
+}
+#[cfg_attr(
+ staged_api,
+ stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")
+)]
+impl FromRawFd for RawFd {
+ #[inline]
+ unsafe fn from_raw_fd(fd: RawFd) -> RawFd {
+ fd
+ }
+}
diff --git a/vendor/rustix/src/io/ioctl.rs b/vendor/rustix/src/io/ioctl.rs
new file mode 100644
index 000000000..be47e7958
--- /dev/null
+++ b/vendor/rustix/src/io/ioctl.rs
@@ -0,0 +1,99 @@
+//! The Unix `ioctl` 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.
+
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+/// `ioctl(fd, TIOCEXCL)`—Enables exclusive mode on a terminal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+#[inline]
+#[doc(alias = "TIOCEXCL")]
+pub fn ioctl_tiocexcl<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::io::syscalls::ioctl_tiocexcl(fd.as_fd())
+}
+
+/// `ioctl(fd, TIOCNXCL)`—Disables exclusive mode on a terminal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+#[inline]
+#[doc(alias = "TIOCNXCL")]
+pub fn ioctl_tiocnxcl<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::io::syscalls::ioctl_tiocnxcl(fd.as_fd())
+}
+
+/// `ioctl(fd, FIOCLEX)`—Set the close-on-exec flag.
+///
+/// Also known as `fcntl(fd, F_SETFD, FD_CLOEXEC)`.
+///
+/// # References
+/// - [Linux]
+/// - [Winsock2]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ioctlsocket
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[inline]
+#[doc(alias = "FIOCLEX")]
+#[doc(alias = "FD_CLOEXEC")]
+pub fn ioctl_fioclex<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::io::syscalls::ioctl_fioclex(fd.as_fd())
+}
+
+/// `ioctl(fd, FIONBIO, &value)`—Enables or disables non-blocking mode.
+///
+/// # References
+/// - [Linux]
+/// - [Winsock2]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes
+#[inline]
+#[doc(alias = "FIONBIO")]
+pub fn ioctl_fionbio<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> {
+ imp::io::syscalls::ioctl_fionbio(fd.as_fd(), value)
+}
+
+/// `ioctl(fd, FIONREAD)`—Returns the number of bytes ready to be read.
+///
+/// The result of this function gets silently coerced into a C `int`
+/// by the OS, so it may contain a wrapped value.
+///
+/// # References
+/// - [Linux]
+/// - [Winsock2]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_tty.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes
+#[cfg(not(target_os = "redox"))]
+#[inline]
+#[doc(alias = "FIONREAD")]
+pub fn ioctl_fionread<Fd: AsFd>(fd: Fd) -> io::Result<u64> {
+ imp::io::syscalls::ioctl_fionread(fd.as_fd())
+}
+
+/// `ioctl(fd, BLKSSZGET)`—Returns the logical block size of a block device.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[doc(alias = "BLKSSZGET")]
+pub fn ioctl_blksszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
+ imp::io::syscalls::ioctl_blksszget(fd.as_fd())
+}
+
+/// `ioctl(fd, BLKPBSZGET)`—Returns the physical block size of a block device.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[doc(alias = "BLKPBSZGET")]
+pub fn ioctl_blkpbszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
+ imp::io::syscalls::ioctl_blkpbszget(fd.as_fd())
+}
diff --git a/vendor/rustix/src/io/is_read_write.rs b/vendor/rustix/src/io/is_read_write.rs
new file mode 100644
index 000000000..c6f189090
--- /dev/null
+++ b/vendor/rustix/src/io/is_read_write.rs
@@ -0,0 +1,16 @@
+//! The [`is_read_write`] function.
+
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+/// Returns a pair of booleans indicating whether the file descriptor is
+/// readable and/or writable, respectively.
+///
+/// Unlike [`is_file_read_write`], this correctly detects whether sockets
+/// have been shutdown, partially or completely.
+///
+/// [`is_file_read_write`]: crate::fs::is_file_read_write
+#[inline]
+pub fn is_read_write<Fd: AsFd>(fd: Fd) -> io::Result<(bool, bool)> {
+ imp::io::syscalls::is_read_write(fd.as_fd())
+}
diff --git a/vendor/rustix/src/io/mod.rs b/vendor/rustix/src/io/mod.rs
new file mode 100644
index 000000000..5cd5e2ec9
--- /dev/null
+++ b/vendor/rustix/src/io/mod.rs
@@ -0,0 +1,74 @@
+//! I/O operations.
+
+mod close;
+#[cfg(not(windows))]
+mod dup;
+mod errno;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod eventfd;
+#[cfg(not(feature = "std"))]
+pub(crate) mod fd;
+mod ioctl;
+#[cfg(not(any(windows, target_os = "redox")))]
+#[cfg(feature = "net")]
+mod is_read_write;
+mod owned_fd;
+#[cfg(not(any(windows, target_os = "wasi")))]
+mod pipe;
+mod poll;
+#[cfg(all(feature = "procfs", any(target_os = "android", target_os = "linux")))]
+mod procfs;
+#[cfg(not(windows))]
+mod read_write;
+#[cfg(not(feature = "std"))]
+mod seek_from;
+#[cfg(not(windows))]
+mod stdio;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use crate::imp::io::epoll;
+pub use close::close;
+#[cfg(not(any(windows, target_os = "wasi")))]
+pub use dup::{dup, dup2, dup3, DupFlags};
+pub use errno::{retry_on_intr, Errno, Result};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use eventfd::{eventfd, EventfdFlags};
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub use ioctl::ioctl_fioclex;
+pub use ioctl::ioctl_fionbio;
+#[cfg(not(target_os = "redox"))]
+pub use ioctl::ioctl_fionread;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use ioctl::{ioctl_blkpbszget, ioctl_blksszget};
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+pub use ioctl::{ioctl_tiocexcl, ioctl_tiocnxcl};
+#[cfg(not(any(windows, target_os = "redox")))]
+#[cfg(feature = "net")]
+pub use is_read_write::is_read_write;
+pub use owned_fd::OwnedFd;
+#[cfg(not(any(windows, target_os = "wasi")))]
+pub use pipe::pipe;
+#[cfg(not(any(
+ windows,
+ target_os = "illumos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub use pipe::PIPE_BUF;
+#[cfg(not(any(windows, target_os = "ios", target_os = "macos", target_os = "wasi")))]
+pub use pipe::{pipe_with, PipeFlags};
+pub use poll::{poll, PollFd, PollFlags};
+#[cfg(all(feature = "procfs", any(target_os = "android", target_os = "linux")))]
+pub use procfs::{proc_self_fd, proc_self_fdinfo_fd, proc_self_maps, proc_self_pagemap};
+#[cfg(not(windows))]
+pub use read_write::{pread, pwrite, read, readv, write, writev, IoSlice, IoSliceMut};
+#[cfg(not(any(windows, target_os = "redox")))]
+pub use read_write::{preadv, pwritev};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use read_write::{preadv2, pwritev2, ReadWriteFlags};
+#[cfg(not(feature = "std"))]
+pub use seek_from::SeekFrom;
+#[cfg(feature = "std")]
+pub use std::io::SeekFrom;
+#[cfg(not(windows))]
+pub use stdio::{stderr, stdin, stdout, take_stderr, take_stdin, take_stdout};
diff --git a/vendor/rustix/src/io/owned_fd.rs b/vendor/rustix/src/io/owned_fd.rs
new file mode 100644
index 000000000..63c6145b0
--- /dev/null
+++ b/vendor/rustix/src/io/owned_fd.rs
@@ -0,0 +1,272 @@
+//! A wrapper around [`io_lifetimes::OwnedFd`].
+//!
+//! rustix needs to wrap io-lifetimes' `OwnedFd` type so that it can call its
+//! own [`close`] function when the `OwnedFd` is dropped.
+//!
+//! [`close`]: crate::io::close
+//!
+//! # Safety
+//!
+//! We wrap an `OwnedFd` in a `ManuallyDrop` so that we can extract the
+//! file descriptor and close it ourselves.
+#![allow(unsafe_code)]
+
+use crate::imp::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
+#[cfg(all(not(io_lifetimes_use_std), feature = "std"))]
+use crate::imp::fd::{FromFd, IntoFd};
+use crate::io::close;
+use core::fmt;
+use core::mem::{forget, ManuallyDrop};
+
+/// A wrapper around [`io_lifetimes::OwnedFd`] which closes the file descriptor
+/// using rustix's own [`close`] rather than libc's `close`.
+///
+/// [`close`]: crate::io::close
+#[repr(transparent)]
+pub struct OwnedFd {
+ inner: ManuallyDrop<crate::imp::fd::OwnedFd>,
+}
+
+impl OwnedFd {
+ /// Creates a new `OwnedFd` instance that shares the same underlying file
+ /// handle as the existing `OwnedFd` instance.
+ #[cfg(all(unix, not(target_os = "wasi")))]
+ pub fn try_clone(&self) -> crate::io::Result<Self> {
+ // We want to atomically duplicate this file descriptor and set the
+ // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
+ // is a POSIX flag that was added to Linux in 2.6.24.
+ #[cfg(not(target_os = "espidf"))]
+ let fd = crate::fs::fcntl_dupfd_cloexec(self, 0)?;
+
+ // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics
+ // will never be supported, as this is a bare metal framework with
+ // no capabilities for multi-process execution. While F_DUPFD is also
+ // not supported yet, it might be (currently it returns ENOSYS).
+ #[cfg(target_os = "espidf")]
+ let fd = crate::fs::fcntl_dupfd(self)?;
+
+ Ok(fd)
+ }
+
+ /// Creates a new `OwnedFd` instance that shares the same underlying file
+ /// handle as the existing `OwnedFd` instance.
+ #[cfg(target_os = "wasi")]
+ pub fn try_clone(&self) -> std::io::Result<Self> {
+ Err(std::io::Error::new(
+ std::io::ErrorKind::Unsupported,
+ "operation not supported on WASI yet",
+ ))
+ }
+
+ /// Creates a new `OwnedFd` instance that shares the same underlying file
+ /// handle as the existing `OwnedFd` instance.
+ #[cfg(target_os = "windows")]
+ pub fn try_clone(&self) -> std::io::Result<Self> {
+ use windows_sys::Win32::Networking::WinSock::{
+ WSADuplicateSocketW, WSAGetLastError, WSASocketW, INVALID_SOCKET, SOCKET_ERROR,
+ WSAEINVAL, WSAEPROTOTYPE, WSAPROTOCOL_INFOW, WSA_FLAG_NO_HANDLE_INHERIT,
+ WSA_FLAG_OVERLAPPED,
+ };
+ use windows_sys::Win32::System::Threading::GetCurrentProcessId;
+
+ let mut info = unsafe { std::mem::zeroed::<WSAPROTOCOL_INFOW>() };
+ let result =
+ unsafe { WSADuplicateSocketW(self.as_raw_fd() as _, GetCurrentProcessId(), &mut info) };
+ match result {
+ SOCKET_ERROR => return Err(std::io::Error::last_os_error()),
+ 0 => (),
+ _ => panic!(),
+ }
+ let socket = unsafe {
+ WSASocketW(
+ info.iAddressFamily,
+ info.iSocketType,
+ info.iProtocol,
+ &mut info,
+ 0,
+ WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT,
+ )
+ };
+
+ if socket != INVALID_SOCKET {
+ unsafe { Ok(Self::from_raw_fd(socket as _)) }
+ } else {
+ let error = unsafe { WSAGetLastError() };
+
+ if error != WSAEPROTOTYPE && error != WSAEINVAL {
+ return Err(std::io::Error::from_raw_os_error(error));
+ }
+
+ let socket = unsafe {
+ WSASocketW(
+ info.iAddressFamily,
+ info.iSocketType,
+ info.iProtocol,
+ &mut info,
+ 0,
+ WSA_FLAG_OVERLAPPED,
+ )
+ };
+
+ if socket == INVALID_SOCKET {
+ return Err(std::io::Error::last_os_error());
+ }
+
+ unsafe {
+ let socket = Self::from_raw_fd(socket as _);
+ socket.set_no_inherit()?;
+ Ok(socket)
+ }
+ }
+ }
+
+ #[cfg(windows)]
+ #[cfg(not(target_vendor = "uwp"))]
+ fn set_no_inherit(&self) -> std::io::Result<()> {
+ use windows_sys::Win32::Foundation::{SetHandleInformation, HANDLE, HANDLE_FLAG_INHERIT};
+ match unsafe { SetHandleInformation(self.as_raw_fd() as HANDLE, HANDLE_FLAG_INHERIT, 0) } {
+ 0 => return Err(std::io::Error::last_os_error()),
+ _ => Ok(()),
+ }
+ }
+
+ #[cfg(windows)]
+ #[cfg(target_vendor = "uwp")]
+ fn set_no_inherit(&self) -> std::io::Result<()> {
+ Err(std::io::Error::new(
+ std::io::ErrorKind::Unsupported,
+ "Unavailable on UWP",
+ ))
+ }
+}
+
+#[cfg(not(windows))]
+impl AsFd for OwnedFd {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.inner.as_fd()
+ }
+}
+
+#[cfg(windows)]
+impl io_lifetimes::AsSocket for OwnedFd {
+ #[inline]
+ fn as_socket(&self) -> BorrowedFd<'_> {
+ self.inner.as_socket()
+ }
+}
+
+#[cfg(any(io_lifetimes_use_std, not(feature = "std")))]
+impl From<OwnedFd> for crate::imp::fd::OwnedFd {
+ #[inline]
+ fn from(owned_fd: OwnedFd) -> Self {
+ let raw_fd = owned_fd.inner.as_fd().as_raw_fd();
+ forget(owned_fd);
+
+ // Safety: We use `as_fd().as_raw_fd()` to extract the raw file
+ // descriptor from `self.inner`, and then `forget` `self` so
+ // that they remain valid until the new `OwnedFd` acquires them.
+ unsafe { crate::imp::fd::OwnedFd::from_raw_fd(raw_fd) }
+ }
+}
+
+#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))]
+impl IntoFd for OwnedFd {
+ #[inline]
+ fn into_fd(self) -> crate::imp::fd::OwnedFd {
+ let raw_fd = self.inner.as_fd().as_raw_fd();
+ forget(self);
+
+ // Safety: We use `as_fd().as_raw_fd()` to extract the raw file
+ // descriptor from `self.inner`, and then `forget` `self` so
+ // that they remain valid until the new `OwnedFd` acquires them.
+ unsafe { crate::imp::fd::OwnedFd::from_raw_fd(raw_fd) }
+ }
+}
+
+#[cfg(any(io_lifetimes_use_std, not(feature = "std")))]
+impl From<crate::imp::fd::OwnedFd> for OwnedFd {
+ #[inline]
+ fn from(owned_fd: crate::imp::fd::OwnedFd) -> Self {
+ Self {
+ inner: ManuallyDrop::new(owned_fd),
+ }
+ }
+}
+
+#[cfg(all(not(io_lifetimes_use_std), feature = "std"))]
+impl FromFd for OwnedFd {
+ #[inline]
+ fn from_fd(owned_fd: crate::imp::fd::OwnedFd) -> Self {
+ Self {
+ inner: ManuallyDrop::new(owned_fd),
+ }
+ }
+}
+
+#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))]
+impl From<crate::imp::fd::OwnedFd> for OwnedFd {
+ #[inline]
+ fn from(fd: crate::imp::fd::OwnedFd) -> Self {
+ Self {
+ inner: ManuallyDrop::new(fd),
+ }
+ }
+}
+
+#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))]
+impl From<OwnedFd> for crate::imp::fd::OwnedFd {
+ #[inline]
+ fn from(fd: OwnedFd) -> Self {
+ let raw_fd = fd.inner.as_fd().as_raw_fd();
+ forget(fd);
+
+ // Safety: We use `as_fd().as_raw_fd()` to extract the raw file
+ // descriptor from `self.inner`, and then `forget` `self` so
+ // that they remain valid until the new `OwnedFd` acquires them.
+ unsafe { Self::from_raw_fd(raw_fd) }
+ }
+}
+
+impl AsRawFd for OwnedFd {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ self.inner.as_raw_fd()
+ }
+}
+
+impl IntoRawFd for OwnedFd {
+ #[inline]
+ fn into_raw_fd(self) -> RawFd {
+ let raw_fd = self.inner.as_fd().as_raw_fd();
+ forget(self);
+ raw_fd
+ }
+}
+
+impl FromRawFd for OwnedFd {
+ #[inline]
+ unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
+ Self {
+ inner: ManuallyDrop::new(crate::imp::fd::OwnedFd::from_raw_fd(raw_fd)),
+ }
+ }
+}
+
+impl Drop for OwnedFd {
+ #[inline]
+ fn drop(&mut self) {
+ // Safety: We use `as_fd().as_raw_fd()` to extract the raw file
+ // descriptor from `self.inner`. `self.inner` is wrapped with
+ // `ManuallyDrop` so dropping it doesn't invalid them.
+ unsafe {
+ close(self.as_fd().as_raw_fd());
+ }
+ }
+}
+
+impl fmt::Debug for OwnedFd {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.inner.fmt(f)
+ }
+}
diff --git a/vendor/rustix/src/io/pipe.rs b/vendor/rustix/src/io/pipe.rs
new file mode 100644
index 000000000..2878d10b1
--- /dev/null
+++ b/vendor/rustix/src/io/pipe.rs
@@ -0,0 +1,53 @@
+use crate::imp;
+use crate::io::{self, OwnedFd};
+
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::io::types::PipeFlags;
+
+/// `PIPE_BUF`—The maximum length at which writes to a pipe are atomic.
+///
+/// # References
+/// - [Linux]
+/// - [POSIX]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man7/pipe.7.html
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
+#[cfg(not(any(
+ windows,
+ target_os = "illumos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub const PIPE_BUF: usize = imp::io::types::PIPE_BUF;
+
+/// `pipe()`—Creates a pipe.
+///
+/// This function creates a pipe and returns two file descriptors, for the
+/// reading and writing ends of the pipe, respectively.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/pipe.2.html
+#[inline]
+pub fn pipe() -> io::Result<(OwnedFd, OwnedFd)> {
+ imp::io::syscalls::pipe()
+}
+
+/// `pipe2(flags)`—Creates a pipe, with flags.
+///
+/// This function creates a pipe and returns two file descriptors, for the
+/// reading and writing ends of the pipe, respectively.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/pipe2.2.html
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+#[inline]
+#[doc(alias = "pipe2")]
+pub fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> {
+ imp::io::syscalls::pipe_with(flags)
+}
diff --git a/vendor/rustix/src/io/poll.rs b/vendor/rustix/src/io/poll.rs
new file mode 100644
index 000000000..efa25045c
--- /dev/null
+++ b/vendor/rustix/src/io/poll.rs
@@ -0,0 +1,20 @@
+use crate::{imp, io};
+
+pub use imp::io::poll_fd::{PollFd, PollFlags};
+
+/// `poll(self.fds, timeout)`
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/poll.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/poll.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsapoll
+#[inline]
+pub fn poll(fds: &mut [PollFd<'_>], timeout: i32) -> io::Result<usize> {
+ imp::io::syscalls::poll(fds, timeout)
+}
diff --git a/vendor/rustix/src/io/procfs.rs b/vendor/rustix/src/io/procfs.rs
new file mode 100644
index 000000000..a947a4e06
--- /dev/null
+++ b/vendor/rustix/src/io/procfs.rs
@@ -0,0 +1,482 @@
+//! Utilities for working with `/proc`, where Linux's `procfs` is typically
+//! mounted. `/proc` serves as an adjunct to Linux's main syscall surface area,
+//! providing additional features with an awkward interface.
+//!
+//! This module does a considerable amount of work to determine whether `/proc`
+//! is mounted, with actual `procfs`, and without any additional mount points
+//! on top of the paths we open.
+//!
+//! Why all the effort to detect bind mount points? People are doing all kinds
+//! of things with Linux containers these days, with many different privilege
+//! schemes, and we want to avoid making any unnecessary assumptions. Rustix
+//! and its users will sometimes use procfs *implicitly* (when Linux gives them
+//! no better options), in ways that aren't obvious from their public APIs.
+//! These filesystem accesses might not be visible to someone auditing the main
+//! code of an application for places which may be influenced by the filesystem
+//! namespace. So with the checking here, they may fail, but they won't be able
+//! to succeed with bogus results.
+
+use crate::fd::{AsFd, BorrowedFd};
+use crate::ffi::CStr;
+use crate::fs::{
+ cwd, fstat, fstatfs, major, openat, renameat, Dir, FileType, Mode, OFlags, Stat,
+ PROC_SUPER_MAGIC,
+};
+use crate::io::{self, OwnedFd};
+use crate::path::DecInt;
+use crate::process::{getgid, getpid, getuid, Gid, RawGid, RawUid, Uid};
+#[cfg(feature = "rustc-dep-of-std")]
+use core::lazy::OnceCell;
+#[cfg(not(feature = "rustc-dep-of-std"))]
+use once_cell::sync::OnceCell;
+
+/// Linux's procfs always uses inode 1 for its root directory.
+const PROC_ROOT_INO: u64 = 1;
+
+// Identify an entry within "/proc", to determine which anomalies to check for.
+#[derive(Copy, Clone, Debug)]
+enum Kind {
+ Proc,
+ Pid,
+ Fd,
+ File,
+}
+
+/// Check a subdirectory of "/proc" for anomalies.
+fn check_proc_entry(
+ kind: Kind,
+ entry: BorrowedFd<'_>,
+ proc_stat: Option<&Stat>,
+ uid: RawUid,
+ gid: RawGid,
+) -> io::Result<Stat> {
+ let entry_stat = fstat(entry)?;
+ check_proc_entry_with_stat(kind, entry, entry_stat, proc_stat, uid, gid)
+}
+
+/// Check a subdirectory of "/proc" for anomalies, using the provided `Stat`.
+fn check_proc_entry_with_stat(
+ kind: Kind,
+ entry: BorrowedFd<'_>,
+ entry_stat: Stat,
+ proc_stat: Option<&Stat>,
+ uid: RawUid,
+ gid: RawGid,
+) -> io::Result<Stat> {
+ // Check the filesystem magic.
+ check_procfs(entry)?;
+
+ match kind {
+ Kind::Proc => check_proc_root(entry, &entry_stat)?,
+ Kind::Pid | Kind::Fd => check_proc_subdir(entry, &entry_stat, proc_stat)?,
+ Kind::File => check_proc_file(&entry_stat, proc_stat)?,
+ }
+
+ // Check the ownership of the directory. We can't do that for the toplevel
+ // "/proc" though, because in e.g. a user namespace scenario, root outside
+ // the container may be mapped to another uid like `nobody`.
+ if !matches!(kind, Kind::Proc) && (entry_stat.st_uid, entry_stat.st_gid) != (uid, gid) {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ // "/proc" directories are typically mounted r-xr-xr-x.
+ // "/proc/self/fd" is r-x------. Allow them to have fewer permissions, but
+ // not more.
+ let expected_mode = if let Kind::Fd = kind { 0o500 } else { 0o555 };
+ if entry_stat.st_mode & 0o777 & !expected_mode != 0 {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ match kind {
+ Kind::Fd => {
+ // Check that the "/proc/self/fd" directory doesn't have any extraneous
+ // links into it (which might include unexpected subdirectories).
+ if entry_stat.st_nlink != 2 {
+ return Err(io::Errno::NOTSUP);
+ }
+ }
+ Kind::Pid | Kind::Proc => {
+ // Check that the "/proc" and "/proc/self" directories aren't empty.
+ if entry_stat.st_nlink <= 2 {
+ return Err(io::Errno::NOTSUP);
+ }
+ }
+ Kind::File => {
+ // Check that files in procfs don't have extraneous hard links to
+ // them (which might indicate hard links to other things).
+ if entry_stat.st_nlink != 1 {
+ return Err(io::Errno::NOTSUP);
+ }
+ }
+ }
+
+ Ok(entry_stat)
+}
+
+fn check_proc_root(entry: BorrowedFd<'_>, stat: &Stat) -> io::Result<()> {
+ // We use `O_DIRECTORY` for proc directories, so open should fail if we
+ // don't get a directory when we expect one.
+ assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory);
+
+ // Check the root inode number.
+ if stat.st_ino != PROC_ROOT_INO {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ // Proc is a non-device filesystem, so check for major number 0.
+ // <https://www.kernel.org/doc/Documentation/admin-guide/devices.txt>
+ if major(stat.st_dev) != 0 {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ // Check that "/proc" is a mountpoint.
+ if !is_mountpoint(entry) {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ Ok(())
+}
+
+fn check_proc_subdir(
+ entry: BorrowedFd<'_>,
+ stat: &Stat,
+ proc_stat: Option<&Stat>,
+) -> io::Result<()> {
+ // We use `O_DIRECTORY` for proc directories, so open should fail if we
+ // don't get a directory when we expect one.
+ assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory);
+
+ check_proc_nonroot(stat, proc_stat)?;
+
+ // Check that subdirectories of "/proc" are not mount points.
+ if is_mountpoint(entry) {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ Ok(())
+}
+
+fn check_proc_file(stat: &Stat, proc_stat: Option<&Stat>) -> io::Result<()> {
+ // Check that we have a regular file.
+ if FileType::from_raw_mode(stat.st_mode) != FileType::RegularFile {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ check_proc_nonroot(stat, proc_stat)?;
+
+ Ok(())
+}
+
+fn check_proc_nonroot(stat: &Stat, proc_stat: Option<&Stat>) -> io::Result<()> {
+ // Check that we haven't been linked back to the root of "/proc".
+ if stat.st_ino == PROC_ROOT_INO {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ // Check that we're still in procfs.
+ if stat.st_dev != proc_stat.unwrap().st_dev {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ Ok(())
+}
+
+/// Check that `file` is opened on a `procfs` filesystem.
+fn check_procfs(file: BorrowedFd<'_>) -> io::Result<()> {
+ let statfs = fstatfs(file)?;
+ let f_type = statfs.f_type;
+ if f_type != PROC_SUPER_MAGIC {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ Ok(())
+}
+
+/// Check whether the given directory handle is a mount point. We use a
+/// `renameat` call that would otherwise fail, but which fails with `EXDEV`
+/// first if it would cross a mount point.
+fn is_mountpoint(file: BorrowedFd<'_>) -> bool {
+ let err = renameat(file, cstr!("../."), file, cstr!(".")).unwrap_err();
+ match err {
+ io::Errno::XDEV => true, // the rename failed due to crossing a mount point
+ io::Errno::BUSY => false, // the rename failed normally
+ _ => panic!("Unexpected error from `renameat`: {:?}", err),
+ }
+}
+
+/// Open a directory in `/proc`, mapping all errors to `io::Errno::NOTSUP`.
+fn proc_opendirat<P: crate::path::Arg, Fd: AsFd>(dirfd: Fd, path: P) -> io::Result<OwnedFd> {
+ // We could add `PATH`|`NOATIME` here but Linux 2.6.32 doesn't support it.
+ let oflags = OFlags::NOFOLLOW | OFlags::DIRECTORY | OFlags::CLOEXEC | OFlags::NOCTTY;
+ openat(dirfd, path, oflags, Mode::empty()).map_err(|_err| io::Errno::NOTSUP)
+}
+
+/// Returns a handle to Linux's `/proc` directory.
+///
+/// This ensures that `/proc` is procfs, that nothing is mounted on top of it,
+/// and that it looks normal. It also returns the `Stat` of `/proc`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+fn proc() -> io::Result<(BorrowedFd<'static>, &'static Stat)> {
+ static PROC: StaticFd = StaticFd::new();
+
+ // `OnceBox` is "racey" in that the initialization function may run
+ // multiple times. We're ok with that, since the initialization function
+ // has no side effects.
+ PROC.get_or_try_init(|| {
+ // Open "/proc".
+ let proc = proc_opendirat(cwd(), cstr!("/proc"))?;
+ let proc_stat = check_proc_entry(
+ Kind::Proc,
+ proc.as_fd(),
+ None,
+ Uid::ROOT.as_raw(),
+ Gid::ROOT.as_raw(),
+ )
+ .map_err(|_err| io::Errno::NOTSUP)?;
+
+ Ok(new_static_fd(proc, proc_stat))
+ })
+ .map(|(fd, stat)| (fd.as_fd(), stat))
+}
+
+/// Returns a handle to Linux's `/proc/self` directory.
+///
+/// This ensures that `/proc/self` is procfs, that nothing is mounted on top of
+/// it, and that it looks normal. It also returns the `Stat` of `/proc/self`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+fn proc_self() -> io::Result<(BorrowedFd<'static>, &'static Stat)> {
+ static PROC_SELF: StaticFd = StaticFd::new();
+
+ // The init function here may run multiple times; see above.
+ PROC_SELF
+ .get_or_try_init(|| {
+ let (proc, proc_stat) = proc()?;
+
+ let (uid, gid, pid) = (getuid(), getgid(), getpid());
+
+ // Open "/proc/self". Use our pid to compute the name rather than literally
+ // using "self", as "self" is a symlink.
+ let proc_self = proc_opendirat(proc, DecInt::new(pid.as_raw_nonzero().get()))?;
+ let proc_self_stat = check_proc_entry(
+ Kind::Pid,
+ proc_self.as_fd(),
+ Some(proc_stat),
+ uid.as_raw(),
+ gid.as_raw(),
+ )
+ .map_err(|_err| io::Errno::NOTSUP)?;
+
+ Ok(new_static_fd(proc_self, proc_self_stat))
+ })
+ .map(|(owned, stat)| (owned.as_fd(), stat))
+}
+
+/// Returns a handle to Linux's `/proc/self/fd` directory.
+///
+/// This ensures that `/proc/self/fd` is `procfs`, that nothing is mounted on
+/// top of it, and that it looks normal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub fn proc_self_fd() -> io::Result<BorrowedFd<'static>> {
+ static PROC_SELF_FD: StaticFd = StaticFd::new();
+
+ // The init function here may run multiple times; see above.
+ PROC_SELF_FD
+ .get_or_try_init(|| {
+ let (_, proc_stat) = proc()?;
+
+ let (proc_self, proc_self_stat) = proc_self()?;
+
+ // Open "/proc/self/fd".
+ let proc_self_fd = proc_opendirat(proc_self, cstr!("fd"))?;
+ let proc_self_fd_stat = check_proc_entry(
+ Kind::Fd,
+ proc_self_fd.as_fd(),
+ Some(proc_stat),
+ proc_self_stat.st_uid,
+ proc_self_stat.st_gid,
+ )
+ .map_err(|_err| io::Errno::NOTSUP)?;
+
+ Ok(new_static_fd(proc_self_fd, proc_self_fd_stat))
+ })
+ .map(|(owned, _stat)| owned.as_fd())
+}
+
+type StaticFd = OnceCell<(OwnedFd, Stat)>;
+
+#[inline]
+fn new_static_fd(fd: OwnedFd, stat: Stat) -> (OwnedFd, Stat) {
+ (fd, stat)
+}
+
+/// Returns a handle to Linux's `/proc/self/fdinfo` directory.
+///
+/// This ensures that `/proc/self/fdinfo` is `procfs`, that nothing is mounted
+/// on top of it, and that it looks normal. It also returns the `Stat` of
+/// `/proc/self/fd`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+fn proc_self_fdinfo() -> io::Result<(BorrowedFd<'static>, &'static Stat)> {
+ static PROC_SELF_FDINFO: OnceCell<(OwnedFd, Stat)> = OnceCell::new();
+
+ PROC_SELF_FDINFO
+ .get_or_try_init(|| {
+ let (_, proc_stat) = proc()?;
+
+ let (proc_self, proc_self_stat) = proc_self()?;
+
+ // Open "/proc/self/fdinfo".
+ let proc_self_fdinfo = proc_opendirat(proc_self, cstr!("fdinfo"))?;
+ let proc_self_fdinfo_stat = check_proc_entry(
+ Kind::Fd,
+ proc_self_fdinfo.as_fd(),
+ Some(proc_stat),
+ proc_self_stat.st_uid,
+ proc_self_stat.st_gid,
+ )
+ .map_err(|_err| io::Errno::NOTSUP)?;
+
+ Ok((proc_self_fdinfo, proc_self_fdinfo_stat))
+ })
+ .map(|(owned, stat)| (owned.as_fd(), stat))
+}
+
+/// Returns a handle to a Linux `/proc/self/fdinfo/<fd>` file.
+///
+/// This ensures that `/proc/self/fdinfo/<fd>` is `procfs`, that nothing is
+/// mounted on top of it, and that it looks normal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+#[inline]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub fn proc_self_fdinfo_fd<Fd: AsFd>(fd: Fd) -> io::Result<OwnedFd> {
+ _proc_self_fdinfo(fd.as_fd())
+}
+
+fn _proc_self_fdinfo(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
+ let (proc_self_fdinfo, proc_self_fdinfo_stat) = proc_self_fdinfo()?;
+ let fd_str = DecInt::from_fd(fd);
+ open_and_check_file(proc_self_fdinfo, proc_self_fdinfo_stat, fd_str.as_c_str())
+}
+
+/// Returns a handle to a Linux `/proc/self/pagemap` file.
+///
+/// This ensures that `/proc/self/pagemap` is `procfs`, that nothing is
+/// mounted on top of it, and that it looks normal.
+///
+/// # References
+/// - [Linux]
+/// - [Linux pagemap]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+/// [Linux pagemap]: https://www.kernel.org/doc/Documentation/vm/pagemap.txt
+#[inline]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub fn proc_self_pagemap() -> io::Result<OwnedFd> {
+ proc_self_file(cstr!("pagemap"))
+}
+
+/// Returns a handle to a Linux `/proc/self/maps` file.
+///
+/// This ensures that `/proc/self/maps` is `procfs`, that nothing is
+/// mounted on top of it, and that it looks normal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+#[inline]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub fn proc_self_maps() -> io::Result<OwnedFd> {
+ proc_self_file(cstr!("maps"))
+}
+
+/// Open a file under `/proc/self`.
+fn proc_self_file(name: &CStr) -> io::Result<OwnedFd> {
+ let (proc_self, proc_self_stat) = proc_self()?;
+ open_and_check_file(proc_self, proc_self_stat, name)
+}
+
+/// Open a procfs file within in `dir` and check it for bind mounts.
+fn open_and_check_file(dir: BorrowedFd, dir_stat: &Stat, name: &CStr) -> io::Result<OwnedFd> {
+ let (_, proc_stat) = proc()?;
+
+ let oflags =
+ OFlags::RDONLY | OFlags::CLOEXEC | OFlags::NOFOLLOW | OFlags::NOCTTY | OFlags::NOATIME;
+ let file = openat(&dir, name, oflags, Mode::empty()).map_err(|_err| io::Errno::NOTSUP)?;
+ let file_stat = fstat(&file)?;
+
+ // `is_mountpoint` only works on directory mount points, not file mount
+ // points. To detect file mount points, scan the parent directory to see
+ // if we can find a regular file with an inode and name that matches the
+ // file we just opened. If we can't find it, there could be a file bind
+ // mount on top of the file we want.
+ //
+ // As we scan, we also check for ".", to make sure it's the same directory
+ // as our original directory, to detect mount points, since
+ // `Dir::read_from` reopens ".".
+ //
+ // TODO: With Linux 5.8 we might be able to use `statx` and
+ // `STATX_ATTR_MOUNT_ROOT` to detect mountpoints directly instead of doing
+ // this scanning.
+ let dir = Dir::read_from(dir).map_err(|_err| io::Errno::NOTSUP)?;
+
+ // Confirm that we got the same inode.
+ let dot_stat = dir.stat().map_err(|_err| io::Errno::NOTSUP)?;
+ if (dot_stat.st_dev, dot_stat.st_ino) != (dir_stat.st_dev, dir_stat.st_ino) {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ let mut found_file = false;
+ let mut found_dot = false;
+ for entry in dir {
+ let entry = entry.map_err(|_err| io::Errno::NOTSUP)?;
+ if entry.ino() == file_stat.st_ino
+ && entry.file_type() == FileType::RegularFile
+ && entry.file_name() == name
+ {
+ // We found the file. Proceed to check the file handle.
+ let _ = check_proc_entry_with_stat(
+ Kind::File,
+ file.as_fd(),
+ file_stat,
+ Some(proc_stat),
+ dir_stat.st_uid,
+ dir_stat.st_gid,
+ )?;
+
+ found_file = true;
+ } else if entry.ino() == dir_stat.st_ino
+ && entry.file_type() == FileType::Directory
+ && entry.file_name() == cstr!(".")
+ {
+ // We found ".", and it's the right ".".
+ found_dot = true;
+ }
+ }
+
+ if found_file && found_dot {
+ Ok(file)
+ } else {
+ Err(io::Errno::NOTSUP)
+ }
+}
diff --git a/vendor/rustix/src/io/read_write.rs b/vendor/rustix/src/io/read_write.rs
new file mode 100644
index 000000000..abb96e9c1
--- /dev/null
+++ b/vendor/rustix/src/io/read_write.rs
@@ -0,0 +1,170 @@
+//! `read` and `write`, optionally positioned, optionally vectored
+
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+// Declare `IoSlice` and `IoSliceMut`.
+#[cfg(not(windows))]
+#[cfg(not(feature = "std"))]
+pub use imp::io::io_slice::{IoSlice, IoSliceMut};
+#[cfg(not(windows))]
+#[cfg(feature = "std")]
+pub use std::io::{IoSlice, IoSliceMut};
+
+/// `RWF_*` constants for use with [`preadv2`] and [`pwritev2`].
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use imp::io::types::ReadWriteFlags;
+
+/// `read(fd, buf)`—Reads from a stream.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/read.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/read.2.html
+#[inline]
+pub fn read<Fd: AsFd>(fd: Fd, buf: &mut [u8]) -> io::Result<usize> {
+ imp::io::syscalls::read(fd.as_fd(), buf)
+}
+
+/// `write(fd, buf)`—Writes to a stream.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/write.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/write.2.html
+#[inline]
+pub fn write<Fd: AsFd>(fd: Fd, buf: &[u8]) -> io::Result<usize> {
+ imp::io::syscalls::write(fd.as_fd(), buf)
+}
+
+/// `pread(fd, buf, offset)`—Reads from a file at a given position.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/pread.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/pread.2.html
+#[inline]
+pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+ imp::io::syscalls::pread(fd.as_fd(), buf, offset)
+}
+
+/// `pwrite(fd, bufs)`—Writes to a file at a given position.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/pwrite.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/pwrite.2.html
+#[inline]
+pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: u64) -> io::Result<usize> {
+ imp::io::syscalls::pwrite(fd.as_fd(), buf, offset)
+}
+
+/// `readv(fd, bufs)`—Reads from a stream into multiple buffers.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/readv.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/readv.2.html
+#[inline]
+pub fn readv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+ imp::io::syscalls::readv(fd.as_fd(), bufs)
+}
+
+/// `writev(fd, bufs)`—Writes to a stream from multiple buffers.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/writev.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/writev.2.html
+#[inline]
+pub fn writev<Fd: AsFd>(fd: Fd, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+ imp::io::syscalls::writev(fd.as_fd(), bufs)
+}
+
+/// `preadv(fd, bufs, offset)`—Reads from a file at a given position into
+/// multiple buffers.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/preadv.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+pub fn preadv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ imp::io::syscalls::preadv(fd.as_fd(), bufs, offset)
+}
+
+/// `pwritev(fd, bufs, offset)`—Writes to a file at a given position from
+/// multiple buffers.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/pwritev.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+pub fn pwritev<Fd: AsFd>(fd: Fd, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ imp::io::syscalls::pwritev(fd.as_fd(), bufs, offset)
+}
+
+/// `preadv2(fd, bufs, offset, flags)`—Reads data, with several options.
+///
+/// An `offset` of `u64::MAX` means to use and update the current file offset.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/preadv2.2.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub fn preadv2<Fd: AsFd>(
+ fd: Fd,
+ bufs: &mut [IoSliceMut<'_>],
+ offset: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ imp::io::syscalls::preadv2(fd.as_fd(), bufs, offset, flags)
+}
+
+/// `pwritev2(fd, bufs, offset, flags)`—Writes data, with several options.
+///
+/// An `offset` of `u64::MAX` means to use and update the current file offset.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/pwritev2.2.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub fn pwritev2<Fd: AsFd>(
+ fd: Fd,
+ bufs: &[IoSlice<'_>],
+ offset: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ imp::io::syscalls::pwritev2(fd.as_fd(), bufs, offset, flags)
+}
diff --git a/vendor/rustix/src/io/seek_from.rs b/vendor/rustix/src/io/seek_from.rs
new file mode 100644
index 000000000..265369b6b
--- /dev/null
+++ b/vendor/rustix/src/io/seek_from.rs
@@ -0,0 +1,30 @@
+//! 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`] trait.
+#[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),
+}
diff --git a/vendor/rustix/src/io/stdio.rs b/vendor/rustix/src/io/stdio.rs
new file mode 100644
index 000000000..f9d03a701
--- /dev/null
+++ b/vendor/rustix/src/io/stdio.rs
@@ -0,0 +1,194 @@
+//! Functions returning the stdio file descriptors.
+//!
+//! # Safety
+//!
+//! These access the file descriptors by absolute index value, and nothing
+//! prevents them from being closed and reused. They should only be used in
+//! `main` or other situations where one is in control of the process'
+//! stdio streams.
+#![allow(unsafe_code)]
+
+use crate::imp;
+use crate::io::OwnedFd;
+use imp::fd::{BorrowedFd, FromRawFd, RawFd};
+
+/// `STDIN_FILENO`—Standard input, borrowed.
+///
+/// # Safety
+///
+/// This function must be called from code which knows how the process'
+/// standard input is being used. Often, this will be the `main` function or
+/// code that knows its relationship with the `main` function.
+///
+/// The stdin file descriptor can be closed, potentially on other threads, in
+/// which case the file descriptor index value could be dynamically reused for
+/// other purposes, potentially on different threads.
+///
+/// # Other hazards
+///
+/// Stdin could be redirected from arbitrary input sources, and unless one
+/// knows how the process' standard input is being used, one could consume
+/// bytes that are expected to be consumed by other parts of the process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
+#[inline]
+pub unsafe fn stdin() -> BorrowedFd<'static> {
+ BorrowedFd::borrow_raw(imp::io::types::STDIN_FILENO as RawFd)
+}
+
+/// `STDIN_FILENO`—Standard input, owned.
+///
+/// This is similar to [`stdin`], however it returns an `OwnedFd` which closes
+/// standard input when it is dropped.
+///
+/// # Safety
+///
+/// This is unsafe for the same reasons as [`stdin`].
+///
+/// # Other hazards
+///
+/// This has the same hazards as [`stdin`].
+///
+/// And, when the `OwnedFd` is dropped, subsequent newly created file
+/// descriptors may unknowingly reuse the stdin file descriptor number, which
+/// may break common assumptions, so it should typically only be dropped at the
+/// end of a program when no more file descriptors will be created.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
+#[inline]
+pub unsafe fn take_stdin() -> OwnedFd {
+ OwnedFd::from(imp::fd::OwnedFd::from_raw_fd(
+ imp::io::types::STDIN_FILENO as RawFd,
+ ))
+}
+
+/// `STDOUT_FILENO`—Standard output, borrowed.
+///
+/// # Safety
+///
+/// This function must be called from code which knows how the process'
+/// standard output is being used. Often, this will be the `main` function or
+/// code that knows its relationship with the `main` function.
+///
+/// The stdout file descriptor can be closed, potentially on other threads, in
+/// which case the file descriptor index value could be dynamically reused for
+/// other purposes, potentially on different threads.
+///
+/// # Other hazards
+///
+/// Stdout could be redirected to arbitrary output sinks, and unless one
+/// knows how the process' standard output is being used, one could
+/// unexpectedly inject bytes into a stream being written by another part of
+/// the process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
+#[inline]
+pub unsafe fn stdout() -> BorrowedFd<'static> {
+ BorrowedFd::borrow_raw(imp::io::types::STDOUT_FILENO as RawFd)
+}
+
+/// `STDOUT_FILENO`—Standard output, owned.
+///
+/// This is similar to [`stdout`], however it returns an `OwnedFd` which closes
+/// standard output when it is dropped.
+///
+/// # Safety
+///
+/// This is unsafe for the same reasons as [`stdout`].
+///
+/// # Other hazards
+///
+/// This has the same hazards as [`stdout`].
+///
+/// And, when the `OwnedFd` is dropped, subsequent newly created file
+/// descriptors may unknowingly reuse the stdout file descriptor number, which
+/// may break common assumptions, so it should typically only be dropped at the
+/// end of a program when no more file descriptors will be created.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
+#[inline]
+pub unsafe fn take_stdout() -> OwnedFd {
+ OwnedFd::from(imp::fd::OwnedFd::from_raw_fd(
+ imp::io::types::STDOUT_FILENO as RawFd,
+ ))
+}
+
+/// `STDERR_FILENO`—Standard error, borrowed.
+///
+/// # Safety
+///
+/// This function must be called from code which knows how the process'
+/// standard error is being used. Often, this will be the `main` function or
+/// code that knows its relationship with the `main` function.
+///
+/// The stderr file descriptor can be closed, potentially on other threads, in
+/// which case the file descriptor index value could be dynamically reused for
+/// other purposes, potentially on different threads.
+///
+/// # Other hazards
+///
+/// Stderr could be redirected to arbitrary output sinks, and unless one
+/// knows how the process' standard error is being used, one could unexpectedly
+/// inject bytes into a stream being written by another part of the process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
+#[inline]
+pub unsafe fn stderr() -> BorrowedFd<'static> {
+ BorrowedFd::borrow_raw(imp::io::types::STDERR_FILENO as RawFd)
+}
+
+/// `STDERR_FILENO`—Standard error, owned.
+///
+/// This is similar to [`stdout`], however it returns an `OwnedFd` which closes
+/// standard output when it is dropped.
+///
+/// # Safety
+///
+/// This is unsafe for the same reasons as [`stderr`].
+///
+/// # Other hazards
+///
+/// This has the same hazards as [`stderr`].
+///
+/// And, when the `OwnedFd` is dropped, subsequent newly created file
+/// descriptors may unknowingly reuse the stderr file descriptor number, which
+/// may break common assumptions, so it should typically only be dropped at the
+/// end of a program when no more file descriptors will be created.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
+#[inline]
+pub unsafe fn take_stderr() -> OwnedFd {
+ OwnedFd::from(imp::fd::OwnedFd::from_raw_fd(
+ imp::io::types::STDERR_FILENO as RawFd,
+ ))
+}