diff options
Diffstat (limited to 'third_party/rust/rustix/src/io')
-rw-r--r-- | third_party/rust/rustix/src/io/close.rs | 55 | ||||
-rw-r--r-- | third_party/rust/rustix/src/io/dup.rs | 124 | ||||
-rw-r--r-- | third_party/rust/rustix/src/io/errno.rs | 72 | ||||
-rw-r--r-- | third_party/rust/rustix/src/io/fcntl.rs | 141 | ||||
-rw-r--r-- | third_party/rust/rustix/src/io/ioctl.rs | 77 | ||||
-rw-r--r-- | third_party/rust/rustix/src/io/is_read_write.rs | 19 | ||||
-rw-r--r-- | third_party/rust/rustix/src/io/mod.rs | 32 | ||||
-rw-r--r-- | third_party/rust/rustix/src/io/read_write.rs | 312 |
8 files changed, 832 insertions, 0 deletions
diff --git a/third_party/rust/rustix/src/io/close.rs b/third_party/rust/rustix/src/io/close.rs new file mode 100644 index 0000000000..474d252f4f --- /dev/null +++ b/third_party/rust/rustix/src/io/close.rs @@ -0,0 +1,55 @@ +//! 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 +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#close-and-shutdownget-outta-my-face +/// [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 +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=close&sektion=2 +/// [NetBSD]: https://man.netbsd.org/close.2 +/// [OpenBSD]: https://man.openbsd.org/close.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=close§ion=2 +/// [illumos]: https://illumos.org/man/2/close +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Opening-and-Closing-Files.html#index-close +/// +/// # 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) +} diff --git a/third_party/rust/rustix/src/io/dup.rs b/third_party/rust/rustix/src/io/dup.rs new file mode 100644 index 0000000000..46fb38ad3c --- /dev/null +++ b/third_party/rust/rustix/src/io/dup.rs @@ -0,0 +1,124 @@ +//! 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] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=dup&sektion=2 +/// [NetBSD]: https://man.netbsd.org/dup.2 +/// [OpenBSD]: https://man.openbsd.org/dup.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=dup§ion=2 +/// [illumos]: https://illumos.org/man/2/dup +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Duplicating-Descriptors.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`] +/// +/// For `dup2` to stdin, stdout, and stderr, see [`stdio::dup2_stdin`], +/// [`stdio::dup2_stdout`], and [`stdio::dup2_stderr`]. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=dup2&sektion=2 +/// [NetBSD]: https://man.netbsd.org/dup2.2 +/// [OpenBSD]: https://man.openbsd.org/dup2.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=dup2§ion=2 +/// [illumos]: https://illumos.org/man/2/dup +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Duplicating-Descriptors.html +/// [`stdio::dup2_stdin`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stdin.html +/// [`stdio::dup2_stdout`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stdout.html +/// [`stdio::dup2_stderr`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stderr.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] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=dup3&sektion=3 +/// [NetBSD]: https://man.netbsd.org/dup3.2 +/// [OpenBSD]: https://man.openbsd.org/dup3.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=dup3§ion=3 +#[cfg(not(any( + target_os = "aix", + target_os = "espidf", + target_os = "nto", + target_os = "vita", + 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) +} diff --git a/third_party/rust/rustix/src/io/errno.rs b/third_party/rust/rustix/src/io/errno.rs new file mode 100644 index 0000000000..2b72de005d --- /dev/null +++ b/third_party/rust/rustix/src/io/errno.rs @@ -0,0 +1,72 @@ +//! 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 undefined behavior. + +use crate::backend; +use core::{fmt, result}; +#[cfg(feature = "std")] +use std::error; + +/// A specialized [`Result`] type for `rustix` APIs. +pub type Result<T> = result::Result<T, Errno>; + +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, + } + } +} diff --git a/third_party/rust/rustix/src/io/fcntl.rs b/third_party/rust/rustix/src/io/fcntl.rs new file mode 100644 index 0000000000..31eb84cef4 --- /dev/null +++ b/third_party/rust/rustix/src/io/fcntl.rs @@ -0,0 +1,141 @@ +//! 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] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html +/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=fcntl&sektion=2 +/// [NetBSD]: https://man.netbsd.org/fcntl.2 +/// [OpenBSD]: https://man.openbsd.org/fcntl.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=fcntl§ion=2 +/// [illumos]: https://illumos.org/man/2/fcntl +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Control-Operations.html#index-fcntl-function +#[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] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html +/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=fcntl&sektion=2 +/// [NetBSD]: https://man.netbsd.org/fcntl.2 +/// [OpenBSD]: https://man.openbsd.org/fcntl.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=fcntl§ion=2 +/// [illumos]: https://illumos.org/man/2/fcntl +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Control-Operations.html#index-fcntl-function +#[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] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html +/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=fcntl&sektion=2 +/// [NetBSD]: https://man.netbsd.org/fcntl.2 +/// [OpenBSD]: https://man.openbsd.org/fcntl.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=fcntl§ion=2 +/// [illumos]: https://illumos.org/man/2/fcntl +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Control-Operations.html#index-fcntl-function +#[cfg(not(any(target_os = "espidf", target_os = "wasi")))] +#[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] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html +/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=fcntl&sektion=2 +/// [NetBSD]: https://man.netbsd.org/fcntl.2 +/// [OpenBSD]: https://man.openbsd.org/fcntl.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=fcntl§ion=2 +/// [illumos]: https://illumos.org/man/2/fcntl +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Control-Operations.html#index-fcntl-function +#[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) +} diff --git a/third_party/rust/rustix/src/io/ioctl.rs b/third_party/rust/rustix/src/io/ioctl.rs new file mode 100644 index 0000000000..99dec067d5 --- /dev/null +++ b/third_party/rust/rustix/src/io/ioctl.rs @@ -0,0 +1,77 @@ +//! 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. +//! +//! Some ioctls, such as those related to filesystems, terminals, and +//! processes, live in other top-level API modules. + +#![allow(unsafe_code)] + +use crate::{backend, io, ioctl}; +use backend::c; +use backend::fd::AsFd; + +/// `ioctl(fd, FIOCLEX, NULL)`—Set the close-on-exec flag. +/// +/// This is similar to `fcntl(fd, F_SETFD, FD_CLOEXEC)`, except that it avoids +/// clearing any other flags that might be set. +#[cfg(apple)] +#[inline] +#[doc(alias = "FIOCLEX")] +#[doc(alias = "FD_CLOEXEC")] +pub fn ioctl_fioclex<Fd: AsFd>(fd: Fd) -> io::Result<()> { + // SAFETY: FIOCLEX is a no-argument setter opcode. + unsafe { + let ctl = ioctl::NoArg::<ioctl::BadOpcode<{ c::FIOCLEX }>>::new(); + ioctl::ioctl(fd, ctl) + } +} + +/// `ioctl(fd, FIONBIO, &value)`—Enables or disables non-blocking mode. +/// +/// # References +/// - [Winsock] +/// - [NetBSD] +/// - [OpenBSD] +/// +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes +/// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS +/// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS +#[inline] +#[doc(alias = "FIONBIO")] +pub fn ioctl_fionbio<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { + // SAFETY: FIONBIO is a pointer setter opcode. + unsafe { + let ctl = ioctl::Setter::<ioctl::BadOpcode<{ c::FIONBIO }>, c::c_int>::new(value.into()); + ioctl::ioctl(fd, ctl) + } +} + +/// `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] +/// - [Winsock] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_tty.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=ioctl&sektion=2#GENERIC%09IOCTLS +/// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS +/// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS +#[cfg(not(any(target_os = "espidf", target_os = "vita")))] +#[inline] +#[doc(alias = "FIONREAD")] +pub fn ioctl_fionread<Fd: AsFd>(fd: Fd) -> io::Result<u64> { + // SAFETY: FIONREAD is a getter opcode that gets a c_int. + unsafe { + let ctl = ioctl::Getter::<ioctl::BadOpcode<{ c::FIONREAD }>, c::c_int>::new(); + ioctl::ioctl(fd, ctl).map(|n| n as u64) + } +} diff --git a/third_party/rust/rustix/src/io/is_read_write.rs b/third_party/rust/rustix/src/io/is_read_write.rs new file mode 100644 index 0000000000..af33806cb2 --- /dev/null +++ b/third_party/rust/rustix/src/io/is_read_write.rs @@ -0,0 +1,19 @@ +//! The [`is_read_write`] function. +//! +//! [`is_read_write`]: https://docs.rs/rustix/*/rustix/io/fn.is_read_write.html + +use crate::{backend, io}; +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_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()) +} diff --git a/third_party/rust/rustix/src/io/mod.rs b/third_party/rust/rustix/src/io/mod.rs new file mode 100644 index 0000000000..bddd12acda --- /dev/null +++ b/third_party/rust/rustix/src/io/mod.rs @@ -0,0 +1,32 @@ +//! I/O operations. +//! +//! If you're looking for [`SeekFrom`], that's in the [`fs`] module. +//! +//! [`SeekFrom`]: https://docs.rs/rustix/*/rustix/fs/enum.SeekFrom.html +//! [`fs`]: https://docs.rs/rustix/*/rustix/fs/index.html + +mod close; +#[cfg(not(windows))] +mod dup; +mod errno; +#[cfg(not(windows))] +mod fcntl; +mod ioctl; +#[cfg(not(any(windows, target_os = "redox")))] +#[cfg(all(feature = "fs", feature = "net"))] +mod is_read_write; +#[cfg(not(windows))] +mod read_write; + +pub use close::close; +#[cfg(not(windows))] +pub use dup::*; +pub use errno::{retry_on_intr, Errno, Result}; +#[cfg(not(windows))] +pub use fcntl::*; +pub use ioctl::*; +#[cfg(not(any(windows, target_os = "redox")))] +#[cfg(all(feature = "fs", feature = "net"))] +pub use is_read_write::*; +#[cfg(not(windows))] +pub use read_write::*; diff --git a/third_party/rust/rustix/src/io/read_write.rs b/third_party/rust/rustix/src/io/read_write.rs new file mode 100644 index 0000000000..2ed9dd7165 --- /dev/null +++ b/third_party/rust/rustix/src/io/read_write.rs @@ -0,0 +1,312 @@ +//! `read` and `write`, optionally positioned, optionally vectored + +#![allow(unsafe_code)] + +use crate::buffer::split_init; +use crate::{backend, io}; +use backend::fd::AsFd; +use core::mem::MaybeUninit; + +// Declare `IoSlice` and `IoSliceMut`. +#[cfg(not(windows))] +pub use crate::maybe_polyfill::io::{IoSlice, IoSliceMut}; + +#[cfg(linux_kernel)] +pub use backend::io::types::ReadWriteFlags; + +/// `read(fd, buf)`—Reads from a stream. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=read&sektion=2 +/// [NetBSD]: https://man.netbsd.org/read.2 +/// [OpenBSD]: https://man.openbsd.org/read.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=read§ion=2 +/// [illumos]: https://illumos.org/man/2/read +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/I_002fO-Primitives.html#index-reading-from-a-file-descriptor +#[inline] +pub fn read<Fd: AsFd>(fd: Fd, buf: &mut [u8]) -> io::Result<usize> { + unsafe { backend::io::syscalls::read(fd.as_fd(), buf.as_mut_ptr(), buf.len()) } +} + +/// `read(fd, buf)`—Reads from a stream. +/// +/// This is equivalent to [`read`], except that it can read into uninitialized +/// memory. It returns the slice that was initialized by this function and the +/// slice that remains uninitialized. +#[inline] +pub fn read_uninit<Fd: AsFd>( + fd: Fd, + buf: &mut [MaybeUninit<u8>], +) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>])> { + // Get number of initialized bytes. + let length = + unsafe { backend::io::syscalls::read(fd.as_fd(), buf.as_mut_ptr() as *mut u8, buf.len()) }; + + // Split into the initialized and uninitialized portions. + Ok(unsafe { split_init(buf, length?) }) +} + +/// `write(fd, buf)`—Writes to a stream. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=write&sektion=2 +/// [NetBSD]: https://man.netbsd.org/write.2 +/// [OpenBSD]: https://man.openbsd.org/write.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=write§ion=2 +/// [illumos]: https://illumos.org/man/2/write +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/I_002fO-Primitives.html#index-writing-to-a-file-descriptor +#[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] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pread&sektion=2 +/// [NetBSD]: https://man.netbsd.org/pread.2 +/// [OpenBSD]: https://man.openbsd.org/pread.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pread§ion=2 +/// [illumos]: https://illumos.org/man/2/pread +#[inline] +pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: u64) -> io::Result<usize> { + unsafe { backend::io::syscalls::pread(fd.as_fd(), buf.as_mut_ptr(), buf.len(), offset) } +} + +/// `pread(fd, buf, offset)`—Reads from a file at a given position. +/// +/// This is equivalent to [`pread`], except that it can read into uninitialized +/// memory. It returns the slice that was initialized by this function and the +/// slice that remains uninitialized. +#[inline] +pub fn pread_uninit<Fd: AsFd>( + fd: Fd, + buf: &mut [MaybeUninit<u8>], + offset: u64, +) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>])> { + let length = unsafe { + backend::io::syscalls::pread(fd.as_fd(), buf.as_mut_ptr() as *mut u8, buf.len(), offset) + }; + Ok(unsafe { split_init(buf, length?) }) +} + +/// `pwrite(fd, bufs)`—Writes to a file at a given position. +/// +/// Contrary to POSIX, on many popular platforms including Linux and FreeBSD, +/// if the file is opened in append mode, this ignores the offset appends the +/// data to the end of the file. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pwrite&sektion=2 +/// [NetBSD]: https://man.netbsd.org/pwrite.2 +/// [OpenBSD]: https://man.openbsd.org/pwrite.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pwrite§ion=2 +/// [illumos]: https://illumos.org/man/2/pwrite +#[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] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=readv&sektion=2 +/// [NetBSD]: https://man.netbsd.org/readv.2 +/// [OpenBSD]: https://man.openbsd.org/readv.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=readv§ion=2 +/// [illumos]: https://illumos.org/man/2/readv +#[cfg(not(target_os = "espidf"))] +#[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] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [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 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=writev&sektion=2 +/// [NetBSD]: https://man.netbsd.org/writev.2 +/// [OpenBSD]: https://man.openbsd.org/writev.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=writev§ion=2 +/// [illumos]: https://illumos.org/man/2/writev +#[cfg(not(target_os = "espidf"))] +#[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] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/preadv.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=preadv&sektion=2 +/// [NetBSD]: https://man.netbsd.org/preadv.2 +/// [OpenBSD]: https://man.openbsd.org/preadv.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=preadv§ion=2 +/// [illumos]: https://illumos.org/man/2/preadv +#[cfg(not(any( + target_os = "espidf", + target_os = "haiku", + target_os = "nto", + target_os = "redox", + target_os = "solaris", + target_os = "vita" +)))] +#[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. +/// +/// Contrary to POSIX, on many popular platforms including Linux and FreeBSD, +/// if the file is opened in append mode, this ignores the offset appends the +/// data to the end of the file. +/// +/// # References +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/pwritev.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pwritev&sektion=2 +/// [NetBSD]: https://man.netbsd.org/pwritev.2 +/// [OpenBSD]: https://man.openbsd.org/pwritev.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pwritev§ion=2 +/// [illumos]: https://illumos.org/man/2/pwritev +#[cfg(not(any( + target_os = "espidf", + target_os = "haiku", + target_os = "nto", + target_os = "redox", + target_os = "solaris", + target_os = "vita" +)))] +#[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(linux_kernel)] +#[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(linux_kernel)] +#[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) +} |