diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:39 +0000 |
commit | 1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch) | |
tree | 3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /vendor/rustix/src/io | |
parent | Releasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip |
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rustix/src/io')
-rw-r--r-- | vendor/rustix/src/io/dup.rs | 3 | ||||
-rw-r--r-- | vendor/rustix/src/io/fd/owned.rs | 6 | ||||
-rw-r--r-- | vendor/rustix/src/io/ioctl.rs | 15 | ||||
-rw-r--r-- | vendor/rustix/src/io/kqueue.rs | 421 | ||||
-rw-r--r-- | vendor/rustix/src/io/mod.rs | 67 | ||||
-rw-r--r-- | vendor/rustix/src/io/pipe.rs | 30 | ||||
-rw-r--r-- | vendor/rustix/src/io/port.rs | 151 | ||||
-rw-r--r-- | vendor/rustix/src/io/read_write.rs | 9 | ||||
-rw-r--r-- | vendor/rustix/src/io/seek_from.rs | 18 | ||||
-rw-r--r-- | vendor/rustix/src/io/stdio.rs | 209 |
10 files changed, 806 insertions, 123 deletions
diff --git a/vendor/rustix/src/io/dup.rs b/vendor/rustix/src/io/dup.rs index 8da6aa091..97a11f35c 100644 --- a/vendor/rustix/src/io/dup.rs +++ b/vendor/rustix/src/io/dup.rs @@ -44,6 +44,9 @@ pub fn dup<Fd: AsFd>(fd: Fd) -> io::Result<OwnedFd> { /// 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 [`io::dup2_stdin`], +/// [`io::dup2_stdout`], and [`io::dup2_stderr`]. +/// /// # References /// - [POSIX] /// - [Linux] diff --git a/vendor/rustix/src/io/fd/owned.rs b/vendor/rustix/src/io/fd/owned.rs index c2972b073..2b9238ca7 100644 --- a/vendor/rustix/src/io/fd/owned.rs +++ b/vendor/rustix/src/io/fd/owned.rs @@ -168,7 +168,7 @@ impl Drop for OwnedFd { // 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 _); + close(self.fd as _); } } } @@ -198,7 +198,7 @@ pub trait AsFd { /// /// # Example /// - /// ```rust,no_run + /// ```no_run /// # #![feature(io_safety)] /// use std::fs::File; /// # use std::io; @@ -244,7 +244,7 @@ impl AsFd for BorrowedFd<'_> { impl AsFd for OwnedFd { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { - // Safety: `OwnedFd` and `BorrowedFd` have the same validity + // SAFETY: `OwnedFd` and `BorrowedFd` have the same validity // invariants, and the `BorrowedFd` is bounded by the lifetime // of `&self`. unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } diff --git a/vendor/rustix/src/io/ioctl.rs b/vendor/rustix/src/io/ioctl.rs index 01ded2e12..429b4f8db 100644 --- a/vendor/rustix/src/io/ioctl.rs +++ b/vendor/rustix/src/io/ioctl.rs @@ -42,7 +42,7 @@ pub fn ioctl_tiocnxcl<Fd: AsFd>(fd: Fd) -> io::Result<()> { /// /// [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"))] +#[cfg(apple)] #[inline] #[doc(alias = "FIOCLEX")] #[doc(alias = "FD_CLOEXEC")] @@ -97,3 +97,16 @@ pub fn ioctl_blksszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> { pub fn ioctl_blkpbszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> { backend::io::syscalls::ioctl_blkpbszget(fd.as_fd()) } + +/// `ioctl(fd, FICLONE, src_fd)`—Share data between open files. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_ficlone.2.html +#[cfg(any(target_os = "android", target_os = "linux"))] +#[inline] +#[doc(alias = "FICLONE")] +pub fn ioctl_ficlone<Fd: AsFd, SrcFd: AsFd>(fd: Fd, src_fd: SrcFd) -> io::Result<()> { + backend::io::syscalls::ioctl_ficlone(fd.as_fd(), src_fd.as_fd()) +} diff --git a/vendor/rustix/src/io/kqueue.rs b/vendor/rustix/src/io/kqueue.rs new file mode 100644 index 000000000..09fa0a4e2 --- /dev/null +++ b/vendor/rustix/src/io/kqueue.rs @@ -0,0 +1,421 @@ +//! An API for interfacing with `kqueue`. + +use crate::fd::{AsFd, AsRawFd, OwnedFd, RawFd}; +use crate::{backend, io}; + +use backend::c::{self, kevent as kevent_t, uintptr_t}; +use backend::io::syscalls; + +#[cfg(any(apple, freebsdlike))] +use backend::c::intptr_t; + +use alloc::vec::Vec; +use core::ptr::slice_from_raw_parts_mut; +use core::time::Duration; + +/// A `kqueue` event. +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct Event { + // The layout varies between BSDs and macOS. + inner: kevent_t, +} + +impl Event { + /// Create a new `Event`. + #[allow(clippy::needless_update)] + pub fn new(filter: EventFilter, flags: EventFlags, udata: isize) -> Event { + let (ident, filter, fflags) = match filter { + EventFilter::Read(fd) => (fd.as_raw_fd() as uintptr_t, c::EVFILT_READ, 0), + EventFilter::Write(fd) => (fd.as_raw_fd() as _, c::EVFILT_WRITE, 0), + #[cfg(target_os = "freebsd")] + EventFilter::Empty(fd) => (fd.as_raw_fd() as _, c::EVFILT_EMPTY, 0), + EventFilter::Vnode { vnode, flags } => { + (vnode.as_raw_fd() as _, c::EVFILT_VNODE, flags.bits()) + } + #[cfg(feature = "process")] + EventFilter::Proc { pid, flags } => ( + crate::process::Pid::as_raw(Some(pid)) as _, + c::EVFILT_PROC, + flags.bits(), + ), + #[cfg(feature = "process")] + EventFilter::Signal { signal, times: _ } => (signal as _, c::EVFILT_SIGNAL, 0), + EventFilter::Timer(timer) => { + #[cfg(any(apple, target_os = "freebsd", target_os = "netbsd"))] + let (data, fflags) = match timer { + Some(timer) => { + if timer.subsec_millis() == 0 { + (timer.as_secs() as _, c::NOTE_SECONDS) + } else if timer.subsec_nanos() == 0 { + (timer.as_micros() as _, c::NOTE_USECONDS) + } else { + (timer.as_nanos() as _, c::NOTE_NSECONDS) + } + } + None => (uintptr_t::MAX, c::NOTE_SECONDS), + }; + #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] + let (data, fflags) = match timer { + Some(timer) => (timer.as_millis() as _, 0), + None => (uintptr_t::MAX, 0), + }; + + (data, c::EVFILT_TIMER, fflags) + } + #[cfg(any(apple, freebsdlike))] + EventFilter::User { + ident, + flags, + user_flags, + } => (ident as _, c::EVFILT_USER, flags.bits() | user_flags.0), + EventFilter::Unknown => panic!("unknown filter"), + }; + + Event { + inner: kevent_t { + ident, + filter: filter as _, + flags: flags.bits() as _, + fflags, + data: 0, + udata: { + // On netbsd, udata is an isize and not a pointer. + // TODO: Strict provenance, prevent int-to-ptr cast. + udata as _ + }, + ..unsafe { core::mem::zeroed() } + }, + } + } + + /// Get the event flags for this event. + pub fn flags(&self) -> EventFlags { + EventFlags::from_bits_truncate(self.inner.flags as _) + } + + /// Get the user data for this event. + pub fn udata(&self) -> isize { + // On netbsd, udata is an isize and not a pointer. + // TODO: Strict provenance, prevent ptr-to-int cast. + + self.inner.udata as _ + } + + /// Get the filter of this event. + pub fn filter(&self) -> EventFilter { + match self.inner.filter as _ { + c::EVFILT_READ => EventFilter::Read(self.inner.ident as _), + c::EVFILT_WRITE => EventFilter::Write(self.inner.ident as _), + #[cfg(target_os = "freebsd")] + c::EVFILT_EMPTY => EventFilter::Empty(self.inner.ident as _), + c::EVFILT_VNODE => EventFilter::Vnode { + vnode: self.inner.ident as _, + flags: VnodeEvents::from_bits_truncate(self.inner.fflags), + }, + #[cfg(feature = "process")] + c::EVFILT_PROC => EventFilter::Proc { + pid: unsafe { crate::process::Pid::from_raw(self.inner.ident as _) }.unwrap(), + flags: ProcessEvents::from_bits_truncate(self.inner.fflags), + }, + #[cfg(feature = "process")] + c::EVFILT_SIGNAL => EventFilter::Signal { + signal: crate::process::Signal::from_raw(self.inner.ident as _).unwrap(), + times: self.inner.data as _, + }, + c::EVFILT_TIMER => EventFilter::Timer({ + let (data, fflags) = (self.inner.data, self.inner.fflags); + #[cfg(any(apple, target_os = "freebsd", target_os = "netbsd"))] + match fflags as _ { + c::NOTE_SECONDS => Some(Duration::from_secs(data as _)), + c::NOTE_USECONDS => Some(Duration::from_micros(data as _)), + c::NOTE_NSECONDS => Some(Duration::from_nanos(data as _)), + _ => { + // Unknown timer flags. + None + } + } + #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] + Some(Duration::from_millis(data as _)) + }), + #[cfg(any(apple, freebsdlike))] + c::EVFILT_USER => EventFilter::User { + ident: self.inner.ident as _, + flags: UserFlags::from_bits_truncate(self.inner.fflags), + user_flags: UserDefinedFlags(self.inner.fflags & EVFILT_USER_FLAGS), + }, + _ => EventFilter::Unknown, + } + } +} + +/// Bottom 24 bits of a u32. +#[cfg(any(apple, freebsdlike))] +const EVFILT_USER_FLAGS: u32 = 0x00ff_ffff; + +/// The possible filters for a `kqueue`. +#[repr(i16)] +#[non_exhaustive] +pub enum EventFilter { + /// A read filter. + Read(RawFd), + + /// A write filter. + Write(RawFd), + + /// An empty filter. + #[cfg(target_os = "freebsd")] + Empty(RawFd), + + /// A VNode filter. + Vnode { + /// The file descriptor we looked for events in. + vnode: RawFd, + + /// The flags for this event. + flags: VnodeEvents, + }, + + /// A process filter. + #[cfg(feature = "process")] + Proc { + /// The process ID we waited on. + pid: crate::process::Pid, + + /// The flags for this event. + flags: ProcessEvents, + }, + + /// A signal filter. + #[cfg(feature = "process")] + Signal { + /// The signal number we waited on. + signal: crate::process::Signal, + + /// The number of times the signal has been + /// received since the last call to kevent. + times: usize, + }, + + /// A timer filter. + Timer(Option<Duration>), + + /// A user filter. + #[cfg(any(apple, freebsdlike))] + User { + /// The identifier for this event. + ident: intptr_t, + + /// The flags for this event. + flags: UserFlags, + + /// The user-defined flags for this event. + user_flags: UserDefinedFlags, + }, + + /// This filter is unknown. + /// + /// # Panics + /// + /// Passing this into `Event::new()` will result in a panic. + Unknown, +} + +bitflags::bitflags! { + /// The flags for a `kqueue` event. + pub struct EventFlags: u16 { + /// Add the event to the `kqueue`. + const ADD = c::EV_ADD as _; + + /// Enable the event. + const ENABLE = c::EV_ENABLE as _; + + /// Disable the event. + const DISABLE = c::EV_DISABLE as _; + + /// Delete the event from the `kqueue`. + const DELETE = c::EV_DELETE as _; + + /// TODO + const RECEIPT = c::EV_RECEIPT as _; + + /// Clear the event after it is triggered. + const ONESHOT = c::EV_ONESHOT as _; + + /// TODO + const CLEAR = c::EV_CLEAR as _; + + /// TODO + const EOF = c::EV_EOF as _; + + /// TODO + const ERROR = c::EV_ERROR as _; + } +} + +bitflags::bitflags! { + /// The flags for a virtual node event. + pub struct VnodeEvents: u32 { + /// The file was deleted. + const DELETE = c::NOTE_DELETE; + + /// The file was written to. + const WRITE = c::NOTE_WRITE; + + /// The file was extended. + const EXTEND = c::NOTE_EXTEND; + + /// The file had its attributes changed. + const ATTRIBUTES = c::NOTE_ATTRIB; + + /// The file was renamed. + const RENAME = c::NOTE_RENAME; + + /// Access to the file was revoked. + const REVOKE = c::NOTE_REVOKE; + + /// The link count of the file has changed. + const LINK = c::NOTE_LINK; + } +} + +#[cfg(feature = "process")] +bitflags::bitflags! { + /// The flags for a process event. + pub struct ProcessEvents: u32 { + /// The process exited. + const EXIT = c::NOTE_EXIT; + + /// The process forked itself. + const FORK = c::NOTE_FORK; + + /// The process executed a new process. + const EXEC = c::NOTE_EXEC; + + /// Follow the process through fork() calls (write only). + const TRACK = c::NOTE_TRACK; + + /// An error has occurred with following the process. + const TRACKERR = c::NOTE_TRACKERR; + } +} + +#[cfg(any(apple, freebsdlike))] +bitflags::bitflags! { + /// The flags for a user event. + pub struct UserFlags: u32 { + /// Ignore the user input flags. + const NOINPUT = c::NOTE_FFNOP; + + /// Bitwise AND fflags. + const AND = c::NOTE_FFAND; + + /// Bitwise OR fflags. + const OR = c::NOTE_FFOR; + + /// Copy fflags. + const COPY = c::NOTE_FFCOPY; + + /// Control mask for operations. + const CTRLMASK = c::NOTE_FFCTRLMASK; + + /// User defined flags for masks. + const UDFMASK = c::NOTE_FFLAGSMASK; + + /// Trigger the event. + const TRIGGER = c::NOTE_TRIGGER; + } +} + +/// User-defined flags. +/// +/// Only the lower 24 bits are used in this struct. +#[repr(transparent)] +#[cfg(any(apple, freebsdlike))] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct UserDefinedFlags(u32); + +#[cfg(any(apple, freebsdlike))] +impl UserDefinedFlags { + /// Create a new `UserDefinedFlags` from a `u32`. + pub fn new(flags: u32) -> Self { + Self(flags & EVFILT_USER_FLAGS) + } + + /// Get the underlying `u32`. + pub fn get(self) -> u32 { + self.0 + } +} + +/// `kqueue()`—Create a new `kqueue` file descriptor. +/// +/// # References +/// - [Apple] +/// - [FreeBSD] +/// - [OpenBSD] +/// - [NetBSD] +/// - [DragonflyBSD] +/// +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html +/// [FreeBSD]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 +/// [OpenBSD]: https://man.openbsd.org/kqueue.2 +/// [NetBSD]: https://man.netbsd.org/kqueue.2 +/// [DragonflyBSD]: https://www.dragonflybsd.org/cgi/web-man/?command=kqueue +pub fn kqueue() -> io::Result<OwnedFd> { + syscalls::kqueue() +} + +/// `kevent(kqueue, changelist, eventlist, timeout)`—Wait for events on a +/// `kqueue`. +/// +/// Note: in order to receive events, make sure to allocate capacity in the +/// eventlist! Otherwise, the function will return immediately. +/// +/// # Safety +/// +/// The file descriptors referred to by the `Event` structs must be valid for +/// the lifetime of the `kqueue` file descriptor. +/// +/// # References +/// - [Apple] +/// - [FreeBSD] +/// - [OpenBSD] +/// - [NetBSD] +/// - [DragonflyBSD] +/// +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kevent.2.html +/// [FreeBSD]: https://www.freebsd.org/cgi/man.cgi?query=kevent&sektion=2 +/// [OpenBSD]: https://man.openbsd.org/kevent.2 +/// [NetBSD]: https://man.netbsd.org/kevent.2 +/// [DragonflyBSD]: https://www.dragonflybsd.org/cgi/web-man/?command=kevent +pub unsafe fn kevent( + kqueue: impl AsFd, + changelist: &[Event], + eventlist: &mut Vec<Event>, + timeout: Option<Duration>, +) -> io::Result<usize> { + let timeout = timeout.map(|timeout| crate::backend::c::timespec { + tv_sec: timeout.as_secs() as _, + tv_nsec: timeout.subsec_nanos() as _, + }); + + // Populate the event list with events. + eventlist.set_len(0); + let out_slice = + slice_from_raw_parts_mut(eventlist.as_mut_ptr() as *mut _, eventlist.capacity()); + let res = syscalls::kevent( + kqueue.as_fd(), + changelist, + &mut *out_slice, + timeout.as_ref(), + ) + .map(|res| res as _); + + // Update the event list. + if let Ok(len) = res { + eventlist.set_len(len); + } + + res +} diff --git a/vendor/rustix/src/io/mod.rs b/vendor/rustix/src/io/mod.rs index 03f06c4ac..4e9b3e23a 100644 --- a/vendor/rustix/src/io/mod.rs +++ b/vendor/rustix/src/io/mod.rs @@ -13,14 +13,17 @@ pub(crate) mod fd; mod ioctl; #[cfg(not(any(windows, target_os = "redox")))] mod is_read_write; +#[cfg(bsd)] +pub mod kqueue; #[cfg(not(any(windows, target_os = "wasi")))] mod pipe; mod poll; +#[cfg(solarish)] +pub mod port; #[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; @@ -28,70 +31,24 @@ 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}; +#[cfg(not(windows))] +pub use dup::*; 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}; +pub use fcntl::*; +pub use ioctl::*; #[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 pipe::*; 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, -}; +pub use procfs::*; #[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 read_write::*; 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, -}; +pub use stdio::*; diff --git a/vendor/rustix/src/io/pipe.rs b/vendor/rustix/src/io/pipe.rs index 2b8af6a84..9d4b081c5 100644 --- a/vendor/rustix/src/io/pipe.rs +++ b/vendor/rustix/src/io/pipe.rs @@ -1,3 +1,9 @@ +//! `pipe` and related APIs. +//! +//! # Safety +//! +//! `vmsplice` is an unsafe function. + #![allow(unsafe_code)] use crate::fd::OwnedFd; @@ -5,7 +11,7 @@ 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")))] +#[cfg(not(apple))] pub use backend::io::types::PipeFlags; #[cfg(any(target_os = "android", target_os = "linux"))] @@ -20,11 +26,10 @@ pub use backend::io::types::{IoSliceRaw, SpliceFlags}; /// [Linux]: https://man7.org/linux/man-pages/man7/pipe.7.html /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html #[cfg(not(any( + solarish, 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; @@ -54,22 +59,18 @@ pub fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { /// - [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" -)))] +#[cfg(not(any(apple, target_os = "aix", target_os = "haiku")))] #[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. +/// `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 +/// 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. @@ -107,8 +108,9 @@ pub fn splice<FdIn: AsFd, FdOut: AsFd>( /// /// # 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`. +/// 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, diff --git a/vendor/rustix/src/io/port.rs b/vendor/rustix/src/io/port.rs new file mode 100644 index 000000000..4eb0bcd9e --- /dev/null +++ b/vendor/rustix/src/io/port.rs @@ -0,0 +1,151 @@ +//! Solaris/illumos event ports. + +use crate::backend::c; +use crate::backend::io::syscalls; +use crate::fd::{AsFd, AsRawFd, OwnedFd}; +use crate::io; + +use super::PollFlags; + +use core::convert::TryInto; +use core::time::Duration; + +/// The structure representing a port event. +#[repr(transparent)] +pub struct Event(pub(crate) c::port_event); + +impl Event { + /// Get the events associated with this event. + pub fn events(&self) -> i32 { + self.0.portev_events + } + + /// Get the event source associated with this event. + pub fn object(&self) -> usize { + self.0.portev_object + } + + /// Get the userdata associated with this event. + pub fn userdata(&self) -> *mut c::c_void { + self.0.portev_user + } +} + +/// `port_create()`—Creates a new port. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_create/ +/// [illumos]: https://illumos.org/man/3C/port_create +pub fn port_create() -> io::Result<OwnedFd> { + syscalls::port_create() +} + +/// `port_associate(_, PORT_SOURCE_FD, _, _, _)`—Associates a file descriptor +/// with a port. +/// +/// # Safety +/// +/// Any `object`s passed into the `port` must be valid for the lifetime of the +/// `port`. Logically, `port` keeps a borrowed reference to the `object` until +/// it is removed via `port_dissociate_fd`. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_associate/ +/// [illumos]: https://illumos.org/man/3C/port_associate +pub unsafe fn port_associate_fd( + port: impl AsFd, + object: impl AsRawFd, + events: PollFlags, + userdata: *mut c::c_void, +) -> io::Result<()> { + syscalls::port_associate( + port.as_fd(), + c::PORT_SOURCE_FD, + object.as_raw_fd() as _, + events.bits() as _, + userdata.cast(), + ) +} + +/// `port_dissociate(_, PORT_SOURCE_FD, _)`—Dissociates a file descriptor from +/// a port. +/// +/// # Safety +/// +/// The file descriptor passed into this function must have been previously +/// associated with the port via [`port_associate_fd`]. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_dissociate +/// [illumos]: https://illumos.org/man/3C/port_dissociate +pub unsafe fn port_dissociate_fd(port: impl AsFd, object: impl AsRawFd) -> io::Result<()> { + syscalls::port_dissociate(port.as_fd(), c::PORT_SOURCE_FD, object.as_raw_fd() as _) +} + +/// `port_get(port, timeout)`—Gets an event from a port. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_get/ +/// [illumos]: https://illumos.org/man/3C/port_get +pub fn port_get(port: impl AsFd, timeout: Option<Duration>) -> io::Result<Event> { + let mut timeout = timeout.map(|timeout| c::timespec { + tv_sec: timeout.as_secs().try_into().unwrap(), + tv_nsec: timeout.subsec_nanos() as _, + }); + + syscalls::port_get(port.as_fd(), timeout.as_mut()) +} + +/// `port_getn(port, events, min_events, timeout)`—Gets multiple events from a +/// port. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_getn/ +/// [illumos]: https://illumos.org/man/3C/port_getn +pub fn port_getn( + port: impl AsFd, + events: &mut Vec<Event>, + min_events: usize, + timeout: Option<Duration>, +) -> io::Result<()> { + events.clear(); + + let mut timeout = timeout.map(|timeout| c::timespec { + tv_sec: timeout.as_secs().try_into().unwrap(), + tv_nsec: timeout.subsec_nanos() as _, + }); + + syscalls::port_getn( + port.as_fd(), + timeout.as_mut(), + events, + min_events.try_into().unwrap(), + ) +} + +/// `port_send(port, events, userdata)`—Sends an event to a port. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_send/ +/// [illumos]: https://illumos.org/man/3C/port_send +pub fn port_send(port: impl AsFd, events: i32, userdata: *mut c::c_void) -> io::Result<()> { + syscalls::port_send(port.as_fd(), events, userdata.cast()) +} diff --git a/vendor/rustix/src/io/read_write.rs b/vendor/rustix/src/io/read_write.rs index 1a4d37b65..d89ce7c7d 100644 --- a/vendor/rustix/src/io/read_write.rs +++ b/vendor/rustix/src/io/read_write.rs @@ -11,7 +11,6 @@ pub use backend::io::io_slice::{IoSlice, IoSliceMut}; #[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; @@ -62,6 +61,10 @@ pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: u64) -> io::Result<usize> /// `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] @@ -121,6 +124,10 @@ pub fn preadv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io: /// `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] /// diff --git a/vendor/rustix/src/io/seek_from.rs b/vendor/rustix/src/io/seek_from.rs index 265369b6b..cca23ed62 100644 --- a/vendor/rustix/src/io/seek_from.rs +++ b/vendor/rustix/src/io/seek_from.rs @@ -5,6 +5,8 @@ /// Enumeration of possible methods to seek within an I/O object. /// /// It is used by the [`Seek`] trait. +/// +/// [`Seek`]: std::io::Seek #[derive(Copy, PartialEq, Eq, Clone, Debug)] #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] pub enum SeekFrom { @@ -27,4 +29,20 @@ pub enum SeekFrom { /// 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), + + /// Sets the offset to the current position plus the specified number of bytes, + /// plus the distance to the next byte which is not in a hole. + /// + /// If the offset is in a hole at the end of the file, the seek will produce + /// an `NXIO` error. + #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))] + Data(i64), + + /// Sets the offset to the current position plus the specified number of bytes, + /// plus the distance to the next byte which is in a hole. + /// + /// If there is no hole past the offset, it will be set to the end of the file + /// i.e. there is an implicit hole at the end of any file. + #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))] + Hole(i64), } diff --git a/vendor/rustix/src/io/stdio.rs b/vendor/rustix/src/io/stdio.rs index caa8183c2..15af6b005 100644 --- a/vendor/rustix/src/io/stdio.rs +++ b/vendor/rustix/src/io/stdio.rs @@ -12,23 +12,56 @@ use crate::backend; use crate::fd::OwnedFd; use backend::fd::{BorrowedFd, FromRawFd, RawFd}; +#[cfg(not(any(windows, target_os = "wasi")))] +use crate::io; +#[cfg(not(any(windows, target_os = "wasi")))] +use backend::fd::AsFd; + /// `STDIN_FILENO`—Standard input, borrowed. /// -/// # Safety +/// 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`. /// -/// 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. +/// # Warning /// -/// 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. +/// This function allows reading directly from stdin without coordinating +/// with the buffering performed by [`std::io::Stdin`], so it could cause +/// corrupted input. /// -/// # Other hazards +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html +#[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(backend::io::types::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 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. /// -/// 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. +/// # 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] @@ -36,6 +69,7 @@ use backend::fd::{BorrowedFd, FromRawFd, RawFd}; /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html +#[cfg(not(feature = "std"))] #[doc(alias = "STDIN_FILENO")] #[inline] pub const unsafe fn stdin() -> BorrowedFd<'static> { @@ -49,17 +83,14 @@ pub const unsafe fn stdin() -> BorrowedFd<'static> { /// /// # Safety /// -/// This is unsafe for the same reasons as [`stdin`]. +/// 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. /// -/// # Other hazards +/// # Warning /// /// 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] @@ -74,22 +105,49 @@ pub unsafe fn take_stdin() -> OwnedFd { /// `STDOUT_FILENO`—Standard output, borrowed. /// -/// # Safety +/// 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`. /// -/// 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. +/// # Warning /// -/// 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. +/// This function allows reading directly from stdout without coordinating +/// with the buffering performed by [`std::io::Stdout`], so it could cause +/// corrupted input. /// -/// # Other hazards +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html +#[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(backend::io::types::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 stdin file descriptor is always +/// valid. In `no_std` configurations, it is `unsafe`. +/// +/// # Safety /// -/// 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. +/// In `no_std` configurations, 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. +/// +/// # Warning +/// +/// This function allows reading directly from stdout without coordinating +/// with the buffering performed by [`std::io::Stdout`], so it could cause +/// corrupted input. /// /// # References /// - [POSIX] @@ -97,6 +155,7 @@ pub unsafe fn take_stdin() -> OwnedFd { /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html /// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html +#[cfg(not(feature = "std"))] #[doc(alias = "STDOUT_FILENO")] #[inline] pub const unsafe fn stdout() -> BorrowedFd<'static> { @@ -110,17 +169,14 @@ pub const unsafe fn stdout() -> BorrowedFd<'static> { /// /// # Safety /// -/// This is unsafe for the same reasons as [`stdout`]. +/// 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. /// -/// # Other hazards +/// # Warning /// /// 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] @@ -135,21 +191,37 @@ pub unsafe fn take_stdout() -> OwnedFd { /// `STDERR_FILENO`—Standard error, borrowed. /// -/// # Safety +/// 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`. /// -/// 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. +/// # References +/// - [POSIX] +/// - [Linux] /// -/// 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. +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html +#[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(backend::io::types::STDERR_FILENO as RawFd) } +} + +/// `STDERR_FILENO`—Standard error, borrowed. /// -/// # Other hazards +/// 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 /// -/// 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. +/// In `no_std` configurations, 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. /// /// # References /// - [POSIX] @@ -157,6 +229,7 @@ pub unsafe fn take_stdout() -> OwnedFd { /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html /// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html +#[cfg(not(feature = "std"))] #[doc(alias = "STDERR_FILENO")] #[inline] pub const unsafe fn stderr() -> BorrowedFd<'static> { @@ -170,7 +243,9 @@ pub const unsafe fn stderr() -> BorrowedFd<'static> { /// /// # Safety /// -/// This is unsafe for the same reasons as [`stderr`]. +/// 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 /// @@ -252,3 +327,39 @@ pub const fn raw_stdout() -> RawFd { pub const fn raw_stderr() -> RawFd { backend::io::types::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: AsFd>(fd: Fd) -> io::Result<()> { + // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't + // dropped. + let mut target = unsafe { io::take_stdin() }; + backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; + core::mem::forget(target); + Ok(()) +} + +/// Utility function to safely `dup2` over stdout (fd 1). +#[cfg(not(any(windows, target_os = "wasi")))] +#[inline] +pub fn dup2_stdout<Fd: AsFd>(fd: Fd) -> io::Result<()> { + // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't + // dropped. + let mut target = unsafe { io::take_stdout() }; + backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; + core::mem::forget(target); + Ok(()) +} + +/// Utility function to safely `dup2` over stderr (fd 2). +#[cfg(not(any(windows, target_os = "wasi")))] +#[inline] +pub fn dup2_stderr<Fd: AsFd>(fd: Fd) -> io::Result<()> { + // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't + // dropped. + let mut target = unsafe { io::take_stderr() }; + backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; + core::mem::forget(target); + Ok(()) +} |