Vendor dependencies

Let's see how I like this workflow.
This commit is contained in:
John Doty 2022-12-19 08:27:18 -08:00
parent 34d1830413
commit 9c435dc440
7500 changed files with 1665121 additions and 99 deletions

41
vendor/rustix/src/io/close.rs vendored Normal file
View file

@ -0,0 +1,41 @@
//! The unsafe `close` for raw file descriptors.
//!
//! # Safety
//!
//! Operating on raw file descriptors is unsafe.
#![allow(unsafe_code)]
use crate::backend;
use backend::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) {
backend::io::syscalls::close(raw_fd)
}

80
vendor/rustix/src/io/dup.rs vendored Normal file
View file

@ -0,0 +1,80 @@
//! Functions which duplicate file descriptors.
use crate::fd::OwnedFd;
use crate::{backend, io};
use backend::fd::AsFd;
#[cfg(not(target_os = "wasi"))]
pub use backend::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::io::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> {
backend::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::io::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<()> {
backend::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(any(target_os = "aix", target_os = "wasi")))]
#[inline]
pub fn dup3<Fd: AsFd>(fd: Fd, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()> {
backend::io::syscalls::dup3(fd.as_fd(), new, flags)
}

85
vendor/rustix/src/io/errno.rs vendored Normal file
View file

@ -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::backend;
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 backend::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,
}
}
}

16
vendor/rustix/src/io/eventfd.rs vendored Normal file
View file

@ -0,0 +1,16 @@
use crate::fd::OwnedFd;
use crate::{backend, io};
pub use backend::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> {
backend::io::syscalls::eventfd(initval, flags)
}

85
vendor/rustix/src/io/fcntl.rs vendored Normal file
View file

@ -0,0 +1,85 @@
//! 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.
//!
//! `fcntl` functions which are not specific to files or directories live
//! in the [`io`] module instead.
//!
//! [`io`]: crate::io
use crate::{backend, io};
use backend::fd::{AsFd, OwnedFd, RawFd};
pub use backend::io::types::FdFlags;
/// `fcntl(fd, F_GETFD)`—Returns a file descriptor's flags.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
#[inline]
#[doc(alias = "F_GETFD")]
pub fn fcntl_getfd<Fd: AsFd>(fd: Fd) -> io::Result<FdFlags> {
backend::io::syscalls::fcntl_getfd(fd.as_fd())
}
/// `fcntl(fd, F_SETFD, flags)`—Sets a file descriptor's flags.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
#[inline]
#[doc(alias = "F_SETFD")]
pub fn fcntl_setfd<Fd: AsFd>(fd: Fd, flags: FdFlags) -> io::Result<()> {
backend::io::syscalls::fcntl_setfd(fd.as_fd(), flags)
}
/// `fcntl(fd, F_DUPFD_CLOEXEC)`—Creates a new `OwnedFd` instance, with value
/// at least `min`, that has `O_CLOEXEC` set and that shares the same
/// underlying [file description] as `fd`.
///
/// POSIX guarantees that `F_DUPFD_CLOEXEC` will use the lowest unused file
/// descriptor which is at least `min`, 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]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
#[cfg(not(any(target_os = "wasi", target_os = "espidf")))]
#[inline]
#[doc(alias = "F_DUPFD_CLOEXEC")]
pub fn fcntl_dupfd_cloexec<Fd: AsFd>(fd: Fd, min: RawFd) -> io::Result<OwnedFd> {
backend::io::syscalls::fcntl_dupfd_cloexec(fd.as_fd(), min)
}
/// `fcntl(fd, F_DUPFD)`—Creates a new `OwnedFd` instance, with value at least
/// `min`, that shares the same underlying [file description] as `fd`.
///
/// POSIX guarantees that `F_DUPFD` will use the lowest unused file descriptor
/// which is at least `min`, 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]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
#[cfg(target_os = "espidf")]
#[inline]
#[doc(alias = "F_DUPFD")]
pub fn fcntl_dupfd<Fd: AsFd>(fd: Fd, min: RawFd) -> io::Result<OwnedFd> {
backend::io::syscalls::fcntl_dupfd(fd.as_fd(), min)
}

17
vendor/rustix/src/io/fd/mod.rs vendored Normal file
View file

@ -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::*;

252
vendor/rustix/src/io/fd/owned.rs vendored Normal file
View file

@ -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::io::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::io::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()) }
}
}

159
vendor/rustix/src/io/fd/raw.rs vendored Normal file
View file

@ -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::backend::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
}
}

99
vendor/rustix/src/io/ioctl.rs vendored Normal file
View file

@ -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::{backend, io};
use backend::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 = "haiku", target_os = "redox", target_os = "wasi")))]
#[inline]
#[doc(alias = "TIOCEXCL")]
pub fn ioctl_tiocexcl<Fd: AsFd>(fd: Fd) -> io::Result<()> {
backend::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 = "haiku", target_os = "redox", target_os = "wasi")))]
#[inline]
#[doc(alias = "TIOCNXCL")]
pub fn ioctl_tiocnxcl<Fd: AsFd>(fd: Fd) -> io::Result<()> {
backend::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<()> {
backend::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<()> {
backend::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> {
backend::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> {
backend::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> {
backend::io::syscalls::ioctl_blkpbszget(fd.as_fd())
}

20
vendor/rustix/src/io/is_read_write.rs vendored Normal file
View file

@ -0,0 +1,20 @@
//! The [`is_read_write`] function.
#[cfg(all(feature = "fs", feature = "net"))]
use crate::{backend, io};
#[cfg(all(feature = "fs", feature = "net"))]
use backend::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]
#[cfg(all(feature = "fs", feature = "net"))]
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "fs", feature = "net"))))]
pub fn is_read_write<Fd: AsFd>(fd: Fd) -> io::Result<(bool, bool)> {
backend::io::syscalls::is_read_write(fd.as_fd())
}

97
vendor/rustix/src/io/mod.rs vendored Normal file
View file

@ -0,0 +1,97 @@
//! I/O operations.
mod close;
#[cfg(not(windows))]
mod dup;
mod errno;
#[cfg(any(target_os = "android", target_os = "linux"))]
mod eventfd;
#[cfg(not(windows))]
mod fcntl;
#[cfg(not(feature = "std"))]
pub(crate) mod fd;
mod ioctl;
#[cfg(not(any(windows, target_os = "redox")))]
mod is_read_write;
#[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::backend::io::epoll;
pub use close::close;
#[cfg(not(any(windows, target_os = "aix", 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(not(any(windows, target_os = "wasi")))]
pub use fcntl::fcntl_dupfd_cloexec;
#[cfg(not(windows))]
pub use fcntl::{fcntl_getfd, fcntl_setfd, FdFlags};
#[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 = "haiku", target_os = "redox", target_os = "wasi")))]
pub use ioctl::{ioctl_tiocexcl, ioctl_tiocnxcl};
#[cfg(not(any(windows, target_os = "redox")))]
#[cfg(all(feature = "fs", feature = "net"))]
pub use is_read_write::is_read_write;
#[cfg(not(any(windows, target_os = "wasi")))]
pub use pipe::pipe;
#[cfg(not(any(
windows,
target_os = "haiku",
target_os = "illumos",
target_os = "redox",
target_os = "solaris",
target_os = "wasi",
)))]
pub use pipe::PIPE_BUF;
#[cfg(not(any(
windows,
target_os = "aix",
target_os = "haiku",
target_os = "ios",
target_os = "macos",
target_os = "wasi"
)))]
pub use pipe::{pipe_with, PipeFlags};
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use pipe::{splice, vmsplice, IoSliceRaw, SpliceFlags};
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, proc_self_status,
};
#[cfg(not(windows))]
pub use read_write::{pread, pwrite, read, readv, write, writev, IoSlice, IoSliceMut};
#[cfg(not(any(
windows,
target_os = "haiku",
target_os = "redox",
target_os = "solaris"
)))]
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::{
raw_stderr, raw_stdin, raw_stdout, stderr, stdin, stdout, take_stderr, take_stdin, take_stdout,
};

130
vendor/rustix/src/io/pipe.rs vendored Normal file
View file

@ -0,0 +1,130 @@
#![allow(unsafe_code)]
use crate::fd::OwnedFd;
use crate::{backend, io};
#[cfg(any(target_os = "android", target_os = "linux"))]
use backend::fd::AsFd;
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
pub use backend::io::types::PipeFlags;
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use backend::io::types::{IoSliceRaw, SpliceFlags};
/// `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 = "haiku",
target_os = "illumos",
target_os = "redox",
target_os = "solaris",
target_os = "wasi",
)))]
pub const PIPE_BUF: usize = backend::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)> {
backend::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 = "aix",
target_os = "haiku",
target_os = "ios",
target_os = "macos"
)))]
#[inline]
#[doc(alias = "pipe2")]
pub fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> {
backend::io::syscalls::pipe_with(flags)
}
/// `splice(fd_in, off_in, fd_out, off_out, len, flags)`—Transfer data between a file and a pipe.
///
/// This function transfers up to `len` bytes of data from the file descriptor `fd_in`
/// to the file descriptor `fd_out`, where one of the file descriptors
/// must refer to a pipe.
///
/// `off_*` must be `None` if the corresponding fd refers to a pipe.
/// Otherwise its value points to the starting offset to the file,
/// from which the data is read/written.
/// on success the number of bytes read/written is added to the offset.
///
/// passing `None` causes the read/write to start from the file offset,
/// and the file offset is adjusted appropriately.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/splice.2.html
#[cfg(any(target_os = "android", target_os = "linux"))]
#[inline]
pub fn splice<FdIn: AsFd, FdOut: AsFd>(
fd_in: FdIn,
off_in: Option<&mut u64>,
fd_out: FdOut,
off_out: Option<&mut u64>,
len: usize,
flags: SpliceFlags,
) -> io::Result<usize> {
backend::io::syscalls::splice(fd_in.as_fd(), off_in, fd_out.as_fd(), off_out, len, flags)
}
/// `vmsplice(fd, bufs, flags)`—Transfer data between memory and a pipe.
///
/// If `fd` is the write end of the pipe,
/// the function maps the memory pointer at by `bufs` to the pipe.
///
/// If `fd` is the read end of the pipe,
/// the function writes data from the pipe to said memory.
///
/// # Safety
///
/// If the memory must not be mutated (such as when `bufs` were originally immutable slices),
/// it is up to the caller to ensure that the write end of the pipe is placed in `fd`.
///
/// Additionally if `SpliceFlags::GIFT` is set, the caller must also ensure
/// that the contents of `bufs` in never modified following the call,
/// and that all of the pointers in `bufs` are page aligned,
/// and the lengths are multiples of a page size in bytes.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/vmsplice.2.html
#[cfg(any(target_os = "android", target_os = "linux"))]
#[inline]
pub unsafe fn vmsplice<PipeFd: AsFd>(
fd: PipeFd,
bufs: &[io::IoSliceRaw],
flags: SpliceFlags,
) -> io::Result<usize> {
backend::io::syscalls::vmsplice(fd.as_fd(), bufs, flags)
}

20
vendor/rustix/src/io/poll.rs vendored Normal file
View file

@ -0,0 +1,20 @@
use crate::{backend, io};
pub use backend::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> {
backend::io::syscalls::poll(fds, timeout)
}

464
vendor/rustix/src/io/procfs.rs vendored Normal file
View file

@ -0,0 +1,464 @@
//! 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, OwnedFd};
use crate::ffi::CStr;
use crate::fs::{
cwd, fstat, fstatfs, major, openat, renameat, Dir, FileType, Mode, OFlags, Stat,
PROC_SUPER_MAGIC,
};
use crate::io;
use crate::path::DecInt;
use crate::process::getpid;
#[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>,
) -> io::Result<Stat> {
let entry_stat = fstat(entry)?;
check_proc_entry_with_stat(kind, entry, entry_stat, proc_stat)
}
/// 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>,
) -> 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)?,
}
// "/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.
// Also for `NOATIME` see the comment in `open_and_check_file`.
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).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 pid = 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))
.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))
.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: StaticFd = StaticFd::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))
.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"))
}
/// Returns a handle to a Linux `/proc/self/status` file.
///
/// This ensures that `/proc/self/status` 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_status() -> io::Result<OwnedFd> {
proc_self_file(cstr!("status"))
}
/// 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()?;
// Don't use `NOATIME`, because it [requires us to own the file], and when
// a process sets itself non-dumpable Linux changes the user:group of its
// `/proc/<pid>` files [to root:root].
//
// [requires us to own the file]: https://man7.org/linux/man-pages/man2/openat.2.html
// [to root:root]: https://man7.org/linux/man-pages/man5/proc.5.html
let oflags = OFlags::RDONLY | OFlags::CLOEXEC | OFlags::NOFOLLOW | OFlags::NOCTTY;
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))?;
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)
}
}

170
vendor/rustix/src/io/read_write.rs vendored Normal file
View file

@ -0,0 +1,170 @@
//! `read` and `write`, optionally positioned, optionally vectored
use crate::{backend, io};
use backend::fd::AsFd;
// Declare `IoSlice` and `IoSliceMut`.
#[cfg(not(windows))]
#[cfg(not(feature = "std"))]
pub use backend::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 backend::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> {
backend::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> {
backend::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> {
backend::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> {
backend::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> {
backend::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> {
backend::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(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))]
#[inline]
pub fn preadv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
backend::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(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))]
#[inline]
pub fn pwritev<Fd: AsFd>(fd: Fd, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
backend::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> {
backend::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> {
backend::io::syscalls::pwritev2(fd.as_fd(), bufs, offset, flags)
}

30
vendor/rustix/src/io/seek_from.rs vendored Normal file
View file

@ -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),
}

254
vendor/rustix/src/io/stdio.rs vendored Normal file
View file

@ -0,0 +1,254 @@
//! 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::backend;
use crate::fd::OwnedFd;
use backend::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
#[doc(alias = "STDIN_FILENO")]
#[inline]
pub const unsafe fn stdin() -> BorrowedFd<'static> {
BorrowedFd::borrow_raw(backend::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
#[doc(alias = "STDIN_FILENO")]
#[inline]
pub unsafe fn take_stdin() -> OwnedFd {
backend::fd::OwnedFd::from_raw_fd(backend::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
#[doc(alias = "STDOUT_FILENO")]
#[inline]
pub const unsafe fn stdout() -> BorrowedFd<'static> {
BorrowedFd::borrow_raw(backend::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
#[doc(alias = "STDOUT_FILENO")]
#[inline]
pub unsafe fn take_stdout() -> OwnedFd {
backend::fd::OwnedFd::from_raw_fd(backend::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
#[doc(alias = "STDERR_FILENO")]
#[inline]
pub const unsafe fn stderr() -> BorrowedFd<'static> {
BorrowedFd::borrow_raw(backend::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
#[doc(alias = "STDERR_FILENO")]
#[inline]
pub unsafe fn take_stderr() -> OwnedFd {
backend::fd::OwnedFd::from_raw_fd(backend::io::types::STDERR_FILENO as RawFd)
}
/// `STDIN_FILENO`—Standard input, raw.
///
/// This is similar to [`stdin`], however it returns a `RawFd`.
///
/// # Other hazards
///
/// This has the same hazards as [`stdin`].
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html
/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
#[doc(alias = "STDIN_FILENO")]
#[inline]
pub const fn raw_stdin() -> RawFd {
backend::io::types::STDIN_FILENO as RawFd
}
/// `STDOUT_FILENO`—Standard output, raw.
///
/// This is similar to [`stdout`], however it returns a `RawFd`.
///
/// # Other hazards
///
/// This has the same hazards as [`stdout`].
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html
/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
#[doc(alias = "STDOUT_FILENO")]
#[inline]
pub const fn raw_stdout() -> RawFd {
backend::io::types::STDOUT_FILENO as RawFd
}
/// `STDERR_FILENO`—Standard error, raw.
///
/// This is similar to [`stderr`], however it returns a `RawFd`.
///
/// # Other hazards
///
/// This has the same hazards as [`stderr`].
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html
/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
#[doc(alias = "STDERR_FILENO")]
#[inline]
pub const fn raw_stderr() -> RawFd {
backend::io::types::STDERR_FILENO as RawFd
}