summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/io
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /vendor/rustix/src/io
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-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.rs3
-rw-r--r--vendor/rustix/src/io/fd/owned.rs6
-rw-r--r--vendor/rustix/src/io/ioctl.rs15
-rw-r--r--vendor/rustix/src/io/kqueue.rs421
-rw-r--r--vendor/rustix/src/io/mod.rs67
-rw-r--r--vendor/rustix/src/io/pipe.rs30
-rw-r--r--vendor/rustix/src/io/port.rs151
-rw-r--r--vendor/rustix/src/io/read_write.rs9
-rw-r--r--vendor/rustix/src/io/seek_from.rs18
-rw-r--r--vendor/rustix/src/io/stdio.rs209
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(())
+}