//! Functions returning the stdio file descriptors. //! //! # Safety //! //! Some of the functions in this module can cause the process' stdio file //! descriptors to be closed, which breaks the assumption made in Rust's std //! that these file descriptors are always open. //! //! And in no-std mode, some of the functions in this module similarly assume //! that the process' stdio file descriptors are open, which we don't take as //! given in no-std mode because we don't have std also making that assumption. //! //! See the individual functions' safety comments for more details. #![allow(unsafe_code)] use crate::backend; use crate::fd::OwnedFd; use backend::c; use backend::fd::{BorrowedFd, FromRawFd as _, RawFd}; #[cfg(not(any(windows, target_os = "wasi")))] use { crate::io, backend::fd::{AsFd, AsRawFd as _}, core::mem::ManuallyDrop, }; /// `STDIN_FILENO`—Standard input, borrowed. /// /// In `std`-using configurations, this is a safe function, because the /// standard library already assumes that the stdin file descriptor is always /// valid. In `no_std` configurations, it is `unsafe`. /// /// # Warning /// /// This function allows reading directly from stdin without coordinating /// with the buffering performed by [`std::io::Stdin`], so it could cause /// corrupted input. /// /// # References /// - [POSIX] /// - [Linux] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdin.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 /// [NetBSD]: https://man.netbsd.org/stdin.4 /// [OpenBSD]: https://man.openbsd.org/stdin.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 /// [illumos]: https://illumos.org/man/4FS/stdin /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdin #[cfg(feature = "std")] #[doc(alias = "STDIN_FILENO")] #[inline] pub const fn stdin() -> BorrowedFd<'static> { // SAFETY: When "std" is enabled, the standard library assumes that the // stdio file descriptors are all valid. unsafe { BorrowedFd::borrow_raw(c::STDIN_FILENO as RawFd) } } /// `STDIN_FILENO`—Standard input, borrowed. /// /// In `std`-using configurations, this is a safe function, because the /// standard library already assumes that the stdin file descriptor is always /// valid. In `no_std` configurations, it is `unsafe`. /// /// # Safety /// /// In `no_std` configurations, the process' stdin file descriptor can be /// closed, potentially on other threads, in which case the file descriptor /// index number (`STDIN_FILENO`) could be dynamically reused for other /// purposes, potentially on different threads. /// /// # Warning /// /// This function allows reading directly from stdin without coordinating /// with the buffering performed by [`std::io::Stdin`], so it could cause /// corrupted input. /// /// # References /// - [POSIX] /// - [Linux] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdin.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 /// [NetBSD]: https://man.netbsd.org/stdin.4 /// [OpenBSD]: https://man.openbsd.org/stdin.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 /// [illumos]: https://illumos.org/man/4FS/stdin /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdin #[cfg(not(feature = "std"))] #[doc(alias = "STDIN_FILENO")] #[inline] pub const unsafe fn stdin() -> BorrowedFd<'static> { BorrowedFd::borrow_raw(c::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 /// /// Safe `std`-using Rust code is permitted to assume that the stdin file /// descriptor is always valid. This function returns an `OwnedFd` which will /// close the stdin file descriptor when dropped. /// /// # Warning /// /// This has the same hazards as [`stdin`]. /// /// # References /// - [POSIX] /// - [Linux] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdin.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 /// [NetBSD]: https://man.netbsd.org/stdin.4 /// [OpenBSD]: https://man.openbsd.org/stdin.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 /// [illumos]: https://illumos.org/man/4FS/stdin /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdin #[doc(alias = "STDIN_FILENO")] #[inline] pub unsafe fn take_stdin() -> OwnedFd { backend::fd::OwnedFd::from_raw_fd(c::STDIN_FILENO as RawFd) } /// `STDOUT_FILENO`—Standard output, borrowed. /// /// In `std`-using configurations, this is a safe function, because the /// standard library already assumes that the stdout file descriptor is always /// valid. In `no_std` configurations, it is `unsafe`. /// /// # Warning /// /// This function allows writing directly to stdout without coordinating /// with the buffering performed by [`std::io::Stdout`], so it could cause /// corrupted output. /// /// # References /// - [POSIX] /// - [Linux] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdout.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 /// [NetBSD]: https://man.netbsd.org/stdout.4 /// [OpenBSD]: https://man.openbsd.org/stdout.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 /// [illumos]: https://illumos.org/man/4FS/stdout /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdout #[cfg(feature = "std")] #[doc(alias = "STDOUT_FILENO")] #[inline] pub const fn stdout() -> BorrowedFd<'static> { // SAFETY: When "std" is enabled, the standard library assumes that the // stdio file descriptors are all valid. unsafe { BorrowedFd::borrow_raw(c::STDOUT_FILENO as RawFd) } } /// `STDOUT_FILENO`—Standard output, borrowed. /// /// In `std`-using configurations, this is a safe function, because the /// standard library already assumes that the stdout file descriptor is always /// valid. In `no_std` configurations, it is `unsafe`. /// /// # Safety /// /// In `no_std` configurations, the process' stdout file descriptor can be /// closed, potentially on other threads, in which case the file descriptor /// index number (`STDOUT_FILENO`) could be dynamically reused for other /// purposes, potentially on different threads. /// /// # Warning /// /// This function allows writing directly to stdout without coordinating /// with the buffering performed by [`std::io::Stdout`], so it could cause /// corrupted output. /// /// # References /// - [POSIX] /// - [Linux] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdout.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 /// [NetBSD]: https://man.netbsd.org/stdout.4 /// [OpenBSD]: https://man.openbsd.org/stdout.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 /// [illumos]: https://illumos.org/man/4FS/stdout /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdout #[cfg(not(feature = "std"))] #[doc(alias = "STDOUT_FILENO")] #[inline] pub const unsafe fn stdout() -> BorrowedFd<'static> { BorrowedFd::borrow_raw(c::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 /// /// Safe `std`-using Rust code is permitted to assume that the stdout file /// descriptor is always valid. This function returns an `OwnedFd` which will /// close the stdout file descriptor when dropped. /// /// # Warning /// /// This has the same hazards as [`stdout`]. /// /// # References /// - [POSIX] /// - [Linux] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdout.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 /// [NetBSD]: https://man.netbsd.org/stdout.4 /// [OpenBSD]: https://man.openbsd.org/stdout.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 /// [illumos]: https://illumos.org/man/4FS/stdout /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdout #[doc(alias = "STDOUT_FILENO")] #[inline] pub unsafe fn take_stdout() -> OwnedFd { backend::fd::OwnedFd::from_raw_fd(c::STDOUT_FILENO as RawFd) } /// `STDERR_FILENO`—Standard error, borrowed. /// /// In `std`-using configurations, this is a safe function, because the /// standard library already assumes that the stderr file descriptor is always /// valid. In `no_std` configurations, it is `unsafe`. /// /// # References /// - [POSIX] /// - [Linux] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stderr.html /// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 /// [NetBSD]: https://man.netbsd.org/stderr.4 /// [OpenBSD]: https://man.openbsd.org/stderr.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 /// [illumos]: https://illumos.org/man/4FS/stderr /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stderr #[cfg(feature = "std")] #[doc(alias = "STDERR_FILENO")] #[inline] pub const fn stderr() -> BorrowedFd<'static> { // SAFETY: When "std" is enabled, the standard library assumes that the // stdio file descriptors are all valid. unsafe { BorrowedFd::borrow_raw(c::STDERR_FILENO as RawFd) } } /// `STDERR_FILENO`—Standard error, borrowed. /// /// In `std`-using configurations, this is a safe function, because the /// standard library already assumes that the stderr file descriptor is always /// valid. In `no_std` configurations, it is `unsafe`. /// /// # Safety /// /// In `no_std` configurations, the process' stderr file descriptor can be /// closed, potentially on other threads, in which case the file descriptor /// index number (`STDERR_FILENO`) could be dynamically reused for other /// purposes, potentially on different threads. /// /// # References /// - [POSIX] /// - [Linux] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stderr.html /// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 /// [NetBSD]: https://man.netbsd.org/stderr.4 /// [OpenBSD]: https://man.openbsd.org/stderr.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 /// [illumos]: https://illumos.org/man/4FS/stderr /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stderr #[cfg(not(feature = "std"))] #[doc(alias = "STDERR_FILENO")] #[inline] pub const unsafe fn stderr() -> BorrowedFd<'static> { BorrowedFd::borrow_raw(c::STDERR_FILENO as RawFd) } /// `STDERR_FILENO`—Standard error, owned. /// /// This is similar to [`stderr`], however it returns an `OwnedFd` which closes /// standard output when it is dropped. /// /// # Safety /// /// Safe std-using Rust code is permitted to assume that the stderr file /// descriptor is always valid. This function returns an `OwnedFd` which will /// close the stderr file descriptor when dropped. /// /// # 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] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stderr.html /// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 /// [NetBSD]: https://man.netbsd.org/stderr.4 /// [OpenBSD]: https://man.openbsd.org/stderr.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 /// [illumos]: https://illumos.org/man/4FS/stderr /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stderr #[doc(alias = "STDERR_FILENO")] #[inline] pub unsafe fn take_stderr() -> OwnedFd { backend::fd::OwnedFd::from_raw_fd(c::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] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdin.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 /// [NetBSD]: https://man.netbsd.org/stdin.4 /// [OpenBSD]: https://man.openbsd.org/stdin.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 /// [illumos]: https://illumos.org/man/4FS/stdin /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdin #[doc(alias = "STDIN_FILENO")] #[inline] pub const fn raw_stdin() -> RawFd { c::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] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stdout.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 /// [NetBSD]: https://man.netbsd.org/stdout.4 /// [OpenBSD]: https://man.openbsd.org/stdout.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 /// [illumos]: https://illumos.org/man/4FS/stdout /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stdout #[doc(alias = "STDOUT_FILENO")] #[inline] pub const fn raw_stdout() -> RawFd { c::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] /// - [FreeBSD] /// - [NetBSD] /// - [OpenBSD] /// - [DragonFly BSD] /// - [illumos] /// - [glibc] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/stderr.html /// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 /// [NetBSD]: https://man.netbsd.org/stderr.4 /// [OpenBSD]: https://man.openbsd.org/stderr.4 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 /// [illumos]: https://illumos.org/man/4FS/stderr /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Standard-Streams.html#index-stderr #[doc(alias = "STDERR_FILENO")] #[inline] pub const fn raw_stderr() -> RawFd { c::STDERR_FILENO as RawFd } /// Utility function to safely `dup2` over stdin (fd 0). #[cfg(not(any(windows, target_os = "wasi")))] #[inline] pub fn dup2_stdin(fd: Fd) -> io::Result<()> { let fd = fd.as_fd(); if fd.as_raw_fd() != c::STDIN_FILENO { // SAFETY: We wrap the returned `OwnedFd` to `ManuallyDrop` so that it // isn't dropped. let mut target = ManuallyDrop::new(unsafe { take_stdin() }); backend::io::syscalls::dup2(fd, &mut target)?; } Ok(()) } /// Utility function to safely `dup2` over stdout (fd 1). #[cfg(not(any(windows, target_os = "wasi")))] #[inline] pub fn dup2_stdout(fd: Fd) -> io::Result<()> { let fd = fd.as_fd(); if fd.as_raw_fd() != c::STDOUT_FILENO { // SAFETY: We wrap the returned `OwnedFd` to `ManuallyDrop` so that it // isn't dropped. let mut target = ManuallyDrop::new(unsafe { take_stdout() }); backend::io::syscalls::dup2(fd, &mut target)?; } Ok(()) } /// Utility function to safely `dup2` over stderr (fd 2). #[cfg(not(any(windows, target_os = "wasi")))] #[inline] pub fn dup2_stderr(fd: Fd) -> io::Result<()> { let fd = fd.as_fd(); if fd.as_raw_fd() != c::STDERR_FILENO { // SAFETY: We wrap the returned `OwnedFd` to `ManuallyDrop` so that it // isn't dropped. let mut target = ManuallyDrop::new(unsafe { take_stderr() }); backend::io::syscalls::dup2(fd, &mut target)?; } Ok(()) }