Vendor dependencies
Let's see how I like this workflow.
This commit is contained in:
parent
34d1830413
commit
9c435dc440
7500 changed files with 1665121 additions and 99 deletions
41
vendor/rustix/src/io/close.rs
vendored
Normal file
41
vendor/rustix/src/io/close.rs
vendored
Normal 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
80
vendor/rustix/src/io/dup.rs
vendored
Normal 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
85
vendor/rustix/src/io/errno.rs
vendored
Normal 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
16
vendor/rustix/src/io/eventfd.rs
vendored
Normal 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
85
vendor/rustix/src/io/fcntl.rs
vendored
Normal 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
17
vendor/rustix/src/io/fd/mod.rs
vendored
Normal 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
252
vendor/rustix/src/io/fd/owned.rs
vendored
Normal 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
159
vendor/rustix/src/io/fd/raw.rs
vendored
Normal 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
99
vendor/rustix/src/io/ioctl.rs
vendored
Normal 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
20
vendor/rustix/src/io/is_read_write.rs
vendored
Normal 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
97
vendor/rustix/src/io/mod.rs
vendored
Normal 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
130
vendor/rustix/src/io/pipe.rs
vendored
Normal 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
20
vendor/rustix/src/io/poll.rs
vendored
Normal 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
464
vendor/rustix/src/io/procfs.rs
vendored
Normal 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
170
vendor/rustix/src/io/read_write.rs
vendored
Normal 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
30
vendor/rustix/src/io/seek_from.rs
vendored
Normal 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
254
vendor/rustix/src/io/stdio.rs
vendored
Normal 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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue