summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src')
-rw-r--r--vendor/rustix/src/const_assert.rs22
-rw-r--r--vendor/rustix/src/cstr.rs76
-rw-r--r--vendor/rustix/src/ffi/mod.rs16
-rw-r--r--vendor/rustix/src/fs/abs.rs33
-rw-r--r--vendor/rustix/src/fs/at.rs380
-rw-r--r--vendor/rustix/src/fs/constants.rs19
-rw-r--r--vendor/rustix/src/fs/copy_file_range.rs20
-rw-r--r--vendor/rustix/src/fs/cwd.rs32
-rw-r--r--vendor/rustix/src/fs/dir.rs5
-rw-r--r--vendor/rustix/src/fs/fadvise.rs19
-rw-r--r--vendor/rustix/src/fs/fcntl.rs131
-rw-r--r--vendor/rustix/src/fs/fcntl_darwin.rs24
-rw-r--r--vendor/rustix/src/fs/fcopyfile.rs90
-rw-r--r--vendor/rustix/src/fs/fd.rs301
-rw-r--r--vendor/rustix/src/fs/file_type.rs4
-rw-r--r--vendor/rustix/src/fs/getpath.rs14
-rw-r--r--vendor/rustix/src/fs/makedev.rs35
-rw-r--r--vendor/rustix/src/fs/memfd_create.rs15
-rw-r--r--vendor/rustix/src/fs/mod.rs196
-rw-r--r--vendor/rustix/src/fs/openat2.rs23
-rw-r--r--vendor/rustix/src/fs/sendfile.rs19
-rw-r--r--vendor/rustix/src/fs/statx.rs91
-rw-r--r--vendor/rustix/src/imp/libc/conv.rs220
-rw-r--r--vendor/rustix/src/imp/libc/fs/dir.rs402
-rw-r--r--vendor/rustix/src/imp/libc/fs/makedev.rs90
-rw-r--r--vendor/rustix/src/imp/libc/fs/mod.rs18
-rw-r--r--vendor/rustix/src/imp/libc/fs/syscalls.rs1670
-rw-r--r--vendor/rustix/src/imp/libc/fs/types.rs1028
-rw-r--r--vendor/rustix/src/imp/libc/io/epoll.rs568
-rw-r--r--vendor/rustix/src/imp/libc/io/errno.rs997
-rw-r--r--vendor/rustix/src/imp/libc/io/io_slice.rs85
-rw-r--r--vendor/rustix/src/imp/libc/io/mod.rs13
-rw-r--r--vendor/rustix/src/imp/libc/io/poll_fd.rs136
-rw-r--r--vendor/rustix/src/imp/libc/io/syscalls.rs456
-rw-r--r--vendor/rustix/src/imp/libc/io/types.rs89
-rw-r--r--vendor/rustix/src/imp/libc/io/windows_syscalls.rs39
-rw-r--r--vendor/rustix/src/imp/libc/io_lifetimes.rs109
-rw-r--r--vendor/rustix/src/imp/libc/io_uring/mod.rs1
-rw-r--r--vendor/rustix/src/imp/libc/io_uring/syscalls.rs55
-rw-r--r--vendor/rustix/src/imp/libc/mm/mod.rs2
-rw-r--r--vendor/rustix/src/imp/libc/mm/syscalls.rs218
-rw-r--r--vendor/rustix/src/imp/libc/mm/types.rs397
-rw-r--r--vendor/rustix/src/imp/libc/mod.rs111
-rw-r--r--vendor/rustix/src/imp/libc/net/addr.rs320
-rw-r--r--vendor/rustix/src/imp/libc/net/ext.rs223
-rw-r--r--vendor/rustix/src/imp/libc/net/mod.rs7
-rw-r--r--vendor/rustix/src/imp/libc/net/read_sockaddr.rs249
-rw-r--r--vendor/rustix/src/imp/libc/net/send_recv.rs77
-rw-r--r--vendor/rustix/src/imp/libc/net/syscalls.rs866
-rw-r--r--vendor/rustix/src/imp/libc/net/types.rs621
-rw-r--r--vendor/rustix/src/imp/libc/net/write_sockaddr.rs96
-rw-r--r--vendor/rustix/src/imp/libc/offset.rs361
-rw-r--r--vendor/rustix/src/imp/libc/param/auxv.rs66
-rw-r--r--vendor/rustix/src/imp/libc/param/mod.rs1
-rw-r--r--vendor/rustix/src/imp/libc/process/cpu_set.rs49
-rw-r--r--vendor/rustix/src/imp/libc/process/mod.rs12
-rw-r--r--vendor/rustix/src/imp/libc/process/syscalls.rs419
-rw-r--r--vendor/rustix/src/imp/libc/process/types.rs361
-rw-r--r--vendor/rustix/src/imp/libc/process/wait.rs6
-rw-r--r--vendor/rustix/src/imp/libc/rand/mod.rs2
-rw-r--r--vendor/rustix/src/imp/libc/rand/syscalls.rs16
-rw-r--r--vendor/rustix/src/imp/libc/rand/types.rs19
-rw-r--r--vendor/rustix/src/imp/libc/termios/mod.rs2
-rw-r--r--vendor/rustix/src/imp/libc/termios/syscalls.rs159
-rw-r--r--vendor/rustix/src/imp/libc/termios/types.rs951
-rw-r--r--vendor/rustix/src/imp/libc/thread/mod.rs2
-rw-r--r--vendor/rustix/src/imp/libc/thread/syscalls.rs282
-rw-r--r--vendor/rustix/src/imp/libc/time/mod.rs3
-rw-r--r--vendor/rustix/src/imp/libc/time/syscalls.rs414
-rw-r--r--vendor/rustix/src/imp/libc/time/types.rs362
-rw-r--r--vendor/rustix/src/imp/libc/weak.rs226
-rw-r--r--vendor/rustix/src/imp/libc/winsock_c.rs82
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/aarch64.rs266
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/arm.rs263
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/mips.rs543
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/mips64.rs464
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/mod.rs17
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/powerpc64.rs411
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/riscv64.rs263
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/x86.rs492
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/inline/x86_64.rs291
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/mod.rs218
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/aarch64.s119
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/arm.s135
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/mips.s213
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/mips64.s189
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/mod.rs33
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs166
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/powerpc64.s132
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/riscv64.s116
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/x86.rs285
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/x86.s381
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/x86_64.s122
-rw-r--r--vendor/rustix/src/imp/linux_raw/c.rs29
-rw-r--r--vendor/rustix/src/imp/linux_raw/conv.rs770
-rw-r--r--vendor/rustix/src/imp/linux_raw/elf.rs172
-rw-r--r--vendor/rustix/src/imp/linux_raw/fs/dir.rs213
-rw-r--r--vendor/rustix/src/imp/linux_raw/fs/makedev.rs19
-rw-r--r--vendor/rustix/src/imp/linux_raw/fs/mod.rs5
-rw-r--r--vendor/rustix/src/imp/linux_raw/fs/syscalls.rs1391
-rw-r--r--vendor/rustix/src/imp/linux_raw/fs/types.rs613
-rw-r--r--vendor/rustix/src/imp/linux_raw/io/epoll.rs551
-rw-r--r--vendor/rustix/src/imp/linux_raw/io/errno.rs511
-rw-r--r--vendor/rustix/src/imp/linux_raw/io/io_slice.rs98
-rw-r--r--vendor/rustix/src/imp/linux_raw/io/mod.rs7
-rw-r--r--vendor/rustix/src/imp/linux_raw/io/poll_fd.rs93
-rw-r--r--vendor/rustix/src/imp/linux_raw/io/syscalls.rs560
-rw-r--r--vendor/rustix/src/imp/linux_raw/io/types.rs67
-rw-r--r--vendor/rustix/src/imp/linux_raw/io_uring/mod.rs1
-rw-r--r--vendor/rustix/src/imp/linux_raw/io_uring/syscalls.rs64
-rw-r--r--vendor/rustix/src/imp/linux_raw/mm/mod.rs2
-rw-r--r--vendor/rustix/src/imp/linux_raw/mm/syscalls.rs214
-rw-r--r--vendor/rustix/src/imp/linux_raw/mm/types.rs208
-rw-r--r--vendor/rustix/src/imp/linux_raw/mod.rs68
-rw-r--r--vendor/rustix/src/imp/linux_raw/net/addr.rs172
-rw-r--r--vendor/rustix/src/imp/linux_raw/net/ext.rs64
-rw-r--r--vendor/rustix/src/imp/linux_raw/net/mod.rs8
-rw-r--r--vendor/rustix/src/imp/linux_raw/net/read_sockaddr.rs175
-rw-r--r--vendor/rustix/src/imp/linux_raw/net/send_recv.rs42
-rw-r--r--vendor/rustix/src/imp/linux_raw/net/syscalls.rs1234
-rw-r--r--vendor/rustix/src/imp/linux_raw/net/types.rs282
-rw-r--r--vendor/rustix/src/imp/linux_raw/net/write_sockaddr.rs60
-rw-r--r--vendor/rustix/src/imp/linux_raw/param/auxv.rs203
-rw-r--r--vendor/rustix/src/imp/linux_raw/param/mod.rs1
-rw-r--r--vendor/rustix/src/imp/linux_raw/process/cpu_set.rs47
-rw-r--r--vendor/rustix/src/imp/linux_raw/process/mod.rs4
-rw-r--r--vendor/rustix/src/imp/linux_raw/process/syscalls.rs517
-rw-r--r--vendor/rustix/src/imp/linux_raw/process/types.rs246
-rw-r--r--vendor/rustix/src/imp/linux_raw/process/wait.rs39
-rw-r--r--vendor/rustix/src/imp/linux_raw/rand/mod.rs2
-rw-r--r--vendor/rustix/src/imp/linux_raw/rand/syscalls.rs17
-rw-r--r--vendor/rustix/src/imp/linux_raw/rand/types.rs15
-rw-r--r--vendor/rustix/src/imp/linux_raw/reg.rs258
-rw-r--r--vendor/rustix/src/imp/linux_raw/runtime/mod.rs2
-rw-r--r--vendor/rustix/src/imp/linux_raw/runtime/syscalls.rs104
-rw-r--r--vendor/rustix/src/imp/linux_raw/runtime/tls.rs62
-rw-r--r--vendor/rustix/src/imp/linux_raw/termios/mod.rs2
-rw-r--r--vendor/rustix/src/imp/linux_raw/termios/syscalls.rs249
-rw-r--r--vendor/rustix/src/imp/linux_raw/termios/types.rs456
-rw-r--r--vendor/rustix/src/imp/linux_raw/thread/futex.rs39
-rw-r--r--vendor/rustix/src/imp/linux_raw/thread/mod.rs4
-rw-r--r--vendor/rustix/src/imp/linux_raw/thread/syscalls.rs280
-rw-r--r--vendor/rustix/src/imp/linux_raw/time/mod.rs3
-rw-r--r--vendor/rustix/src/imp/linux_raw/time/syscalls.rs229
-rw-r--r--vendor/rustix/src/imp/linux_raw/time/types.rs154
-rw-r--r--vendor/rustix/src/imp/linux_raw/vdso.rs435
-rw-r--r--vendor/rustix/src/imp/linux_raw/vdso_wrappers.rs397
-rw-r--r--vendor/rustix/src/io/close.rs41
-rw-r--r--vendor/rustix/src/io/dup.rs80
-rw-r--r--vendor/rustix/src/io/errno.rs85
-rw-r--r--vendor/rustix/src/io/eventfd.rs16
-rw-r--r--vendor/rustix/src/io/fd/mod.rs17
-rw-r--r--vendor/rustix/src/io/fd/owned.rs252
-rw-r--r--vendor/rustix/src/io/fd/raw.rs159
-rw-r--r--vendor/rustix/src/io/ioctl.rs99
-rw-r--r--vendor/rustix/src/io/is_read_write.rs16
-rw-r--r--vendor/rustix/src/io/mod.rs74
-rw-r--r--vendor/rustix/src/io/owned_fd.rs272
-rw-r--r--vendor/rustix/src/io/pipe.rs53
-rw-r--r--vendor/rustix/src/io/poll.rs20
-rw-r--r--vendor/rustix/src/io/procfs.rs482
-rw-r--r--vendor/rustix/src/io/read_write.rs170
-rw-r--r--vendor/rustix/src/io/seek_from.rs30
-rw-r--r--vendor/rustix/src/io/stdio.rs194
-rw-r--r--vendor/rustix/src/io_uring.rs1141
-rw-r--r--vendor/rustix/src/lib.rs230
-rw-r--r--vendor/rustix/src/mm/madvise.rs35
-rw-r--r--vendor/rustix/src/mm/mmap.rs231
-rw-r--r--vendor/rustix/src/mm/mod.rs21
-rw-r--r--vendor/rustix/src/mm/msync.rs32
-rw-r--r--vendor/rustix/src/mm/userfaultfd.rs30
-rw-r--r--vendor/rustix/src/net/addr.rs759
-rw-r--r--vendor/rustix/src/net/ip.rs2059
-rw-r--r--vendor/rustix/src/net/mod.rs48
-rw-r--r--vendor/rustix/src/net/send_recv.rs210
-rw-r--r--vendor/rustix/src/net/socket.rs439
-rw-r--r--vendor/rustix/src/net/socket_addr_any.rs81
-rw-r--r--vendor/rustix/src/net/socketpair.rs21
-rw-r--r--vendor/rustix/src/net/sockopt.rs600
-rw-r--r--vendor/rustix/src/net/wsa.rs49
-rw-r--r--vendor/rustix/src/param/auxv.rs96
-rw-r--r--vendor/rustix/src/param/init.rs23
-rw-r--r--vendor/rustix/src/param/mod.rs37
-rw-r--r--vendor/rustix/src/path/arg.rs963
-rw-r--r--vendor/rustix/src/path/dec_int.rs126
-rw-r--r--vendor/rustix/src/path/mod.rs11
-rw-r--r--vendor/rustix/src/process/chdir.rs72
-rw-r--r--vendor/rustix/src/process/exit.rs34
-rw-r--r--vendor/rustix/src/process/id.rs298
-rw-r--r--vendor/rustix/src/process/kill.rs51
-rw-r--r--vendor/rustix/src/process/membarrier.rs93
-rw-r--r--vendor/rustix/src/process/mod.rs76
-rw-r--r--vendor/rustix/src/process/priority.rs131
-rw-r--r--vendor/rustix/src/process/rlimit.rs53
-rw-r--r--vendor/rustix/src/process/sched.rs110
-rw-r--r--vendor/rustix/src/process/sched_yield.rs16
-rw-r--r--vendor/rustix/src/process/uname.rs101
-rw-r--r--vendor/rustix/src/process/wait.rs129
-rw-r--r--vendor/rustix/src/rand/getrandom.rs21
-rw-r--r--vendor/rustix/src/rand/mod.rs7
-rw-r--r--vendor/rustix/src/runtime.rs265
-rw-r--r--vendor/rustix/src/termios/cf.rs40
-rw-r--r--vendor/rustix/src/termios/constants.rs719
-rw-r--r--vendor/rustix/src/termios/mod.rs610
-rw-r--r--vendor/rustix/src/termios/tc.rs196
-rw-r--r--vendor/rustix/src/termios/tty.rs72
-rw-r--r--vendor/rustix/src/thread/clock.rs96
-rw-r--r--vendor/rustix/src/thread/futex.rs38
-rw-r--r--vendor/rustix/src/thread/id.rs17
-rw-r--r--vendor/rustix/src/thread/mod.rs26
-rw-r--r--vendor/rustix/src/time/clock.rs56
-rw-r--r--vendor/rustix/src/time/mod.rs20
-rw-r--r--vendor/rustix/src/time/timerfd.rs42
-rw-r--r--vendor/rustix/src/utils.rs13
214 files changed, 43804 insertions, 0 deletions
diff --git a/vendor/rustix/src/const_assert.rs b/vendor/rustix/src/const_assert.rs
new file mode 100644
index 000000000..8761a4a21
--- /dev/null
+++ b/vendor/rustix/src/const_assert.rs
@@ -0,0 +1,22 @@
+/// A simple `assert` macro that works in `const fn`, for use until the
+/// standard `assert` macro works in `const fn`.
+///
+/// TODO: Replace this with just `assert!`, once that's stable for use in
+/// a `const fn` context.
+#[allow(unused_macros)]
+macro_rules! const_assert {
+ ($x:expr) => {
+ let b: bool = $x;
+ let _ = [()][!b as usize];
+ };
+}
+
+#[test]
+fn test_const_assert() {
+ const_assert!(true);
+}
+
+#[test]
+const fn test_const_assert_in_const_fn() {
+ const_assert!(true);
+}
diff --git a/vendor/rustix/src/cstr.rs b/vendor/rustix/src/cstr.rs
new file mode 100644
index 000000000..5e3364380
--- /dev/null
+++ b/vendor/rustix/src/cstr.rs
@@ -0,0 +1,76 @@
+/// A macro for [`CStr`] literals.
+///
+/// This can make passing string literals to rustix APIs more efficient, since
+/// most underlying system calls with string arguments expect NUL-terminated
+/// strings, and passing strings to rustix as `CStr`s means that rustix doesn't
+/// need to copy them into a separate buffer to NUL-terminate them.
+///
+/// [`CStr`]: crate::ffi::CStr
+///
+/// # Examples
+///
+/// ```rust,no_run
+/// # #[cfg(feature = "fs")]
+/// # fn main() -> rustix::io::Result<()> {
+/// use rustix::cstr;
+/// use rustix::fs::{cwd, statat, AtFlags};
+///
+/// let metadata = statat(cwd(), cstr!("test.txt"), AtFlags::empty())?;
+/// # Ok(())
+/// # }
+/// # #[cfg(not(feature = "fs"))]
+/// # fn main() {}
+/// ```
+#[allow(unused_macros)]
+#[macro_export]
+macro_rules! cstr {
+ ($str:literal) => {{
+ // Check for NUL manually, to ensure safety.
+ //
+ // In release builds, with strings that don't contain NULs, this
+ // constant-folds away.
+ //
+ // We don't use std's `CStr::from_bytes_with_nul`; as of this writing,
+ // that function isn't defined as `#[inline]` in std and doesn't
+ // constant-fold away.
+ assert!(
+ !$str.bytes().any(|b| b == b'\0'),
+ "cstr argument contains embedded NUL bytes",
+ );
+
+ #[allow(unsafe_code, unused_unsafe)]
+ {
+ // Now that we know the string doesn't have embedded NULs, we can call
+ // `from_bytes_with_nul_unchecked`, which as of this writing is defined
+ // as `#[inline]` and completely optimizes away.
+ //
+ // Safety: We have manually checked that the string does not contain
+ // embedded NULs above, and we append or own NUL terminator here.
+ unsafe {
+ $crate::ffi::CStr::from_bytes_with_nul_unchecked(concat!($str, "\0").as_bytes())
+ }
+ }
+ }};
+}
+
+#[test]
+fn test_cstr() {
+ use crate::ffi::CString;
+ use alloc::borrow::ToOwned;
+ assert_eq!(cstr!(""), &*CString::new("").unwrap());
+ assert_eq!(cstr!("").to_owned(), CString::new("").unwrap());
+ assert_eq!(cstr!("hello"), &*CString::new("hello").unwrap());
+ assert_eq!(cstr!("hello").to_owned(), CString::new("hello").unwrap());
+}
+
+#[test]
+#[should_panic]
+fn test_invalid_cstr() {
+ let _ = cstr!("hello\0world");
+}
+
+#[test]
+#[should_panic]
+fn test_invalid_empty_cstr() {
+ let _ = cstr!("\0");
+}
diff --git a/vendor/rustix/src/ffi/mod.rs b/vendor/rustix/src/ffi/mod.rs
new file mode 100644
index 000000000..eb9983610
--- /dev/null
+++ b/vendor/rustix/src/ffi/mod.rs
@@ -0,0 +1,16 @@
+//! Utilities related to FFI bindings.
+
+// If we have std, use it.
+#[cfg(feature = "std")]
+pub use {
+ std::ffi::{CStr, CString, FromBytesWithNulError, NulError},
+ std::os::raw::c_char,
+};
+
+// If we don't have std, we can depend on core and alloc having these features
+// in new versions of Rust.
+#[cfg(not(feature = "std"))]
+pub use {
+ alloc::ffi::{CString, NulError},
+ core::ffi::{c_char, CStr, FromBytesWithNulError},
+};
diff --git a/vendor/rustix/src/fs/abs.rs b/vendor/rustix/src/fs/abs.rs
new file mode 100644
index 000000000..25556304b
--- /dev/null
+++ b/vendor/rustix/src/fs/abs.rs
@@ -0,0 +1,33 @@
+//! POSIX-style filesystem functions which operate on bare paths.
+
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+use crate::fs::StatFs;
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+use crate::{imp, io, path};
+
+/// `statfs`—Queries filesystem metadata.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/statfs.2.html
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[inline]
+pub fn statfs<P: path::Arg>(path: P) -> io::Result<StatFs> {
+ path.into_with_c_str(imp::fs::syscalls::statfs)
+}
diff --git a/vendor/rustix/src/fs/at.rs b/vendor/rustix/src/fs/at.rs
new file mode 100644
index 000000000..2ecd90324
--- /dev/null
+++ b/vendor/rustix/src/fs/at.rs
@@ -0,0 +1,380 @@
+//! POSIX-style `*at` functions.
+//!
+//! The `dirfd` argument to these functions may be a file descriptor for a
+//! directory, or the special value returned by [`cwd`].
+//!
+//! [`cwd`]: crate::fs::cwd
+
+use crate::ffi::{CStr, CString};
+#[cfg(not(target_os = "illumos"))]
+use crate::fs::Access;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+use crate::fs::CloneFlags;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
+use crate::fs::FileType;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::fs::RenameFlags;
+use crate::fs::{AtFlags, Mode, OFlags, Stat, Timestamps};
+use crate::io::{self, OwnedFd};
+use crate::path::SMALL_PATH_BUFFER_SIZE;
+#[cfg(not(target_os = "wasi"))]
+use crate::process::{Gid, Uid};
+use crate::{imp, path};
+use alloc::vec::Vec;
+use imp::fd::{AsFd, BorrowedFd};
+use imp::time::types::Nsecs;
+
+pub use imp::fs::types::{Dev, RawMode};
+
+/// `UTIME_NOW` for use with [`utimensat`].
+///
+/// [`utimensat`]: crate::fs::utimensat
+#[cfg(not(target_os = "redox"))]
+pub const UTIME_NOW: Nsecs = imp::fs::types::UTIME_NOW as Nsecs;
+
+/// `UTIME_OMIT` for use with [`utimensat`].
+///
+/// [`utimensat`]: crate::fs::utimensat
+#[cfg(not(target_os = "redox"))]
+pub const UTIME_OMIT: Nsecs = imp::fs::types::UTIME_OMIT as Nsecs;
+
+/// `openat(dirfd, path, oflags, mode)`—Opens a file.
+///
+/// POSIX guarantees that `openat` 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.
+///
+/// The `Mode` argument is only significant when creating a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/openat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/open.2.html
+#[inline]
+pub fn openat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ oflags: OFlags,
+ create_mode: Mode,
+) -> io::Result<OwnedFd> {
+ path.into_with_c_str(|path| imp::fs::syscalls::openat(dirfd.as_fd(), path, oflags, create_mode))
+}
+
+/// `readlinkat(fd, path)`—Reads the contents of a symlink.
+///
+/// If `reuse` is non-empty, reuse its buffer to store the result if possible.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlinkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/readlinkat.2.html
+#[inline]
+pub fn readlinkat<P: path::Arg, Fd: AsFd, B: Into<Vec<u8>>>(
+ dirfd: Fd,
+ path: P,
+ reuse: B,
+) -> io::Result<CString> {
+ path.into_with_c_str(|path| _readlinkat(dirfd.as_fd(), path, reuse.into()))
+}
+
+fn _readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, mut buffer: Vec<u8>) -> io::Result<CString> {
+ // This code would benefit from having a better way to read into
+ // uninitialized memory, but that requires `unsafe`.
+ buffer.clear();
+ buffer.reserve(SMALL_PATH_BUFFER_SIZE);
+ buffer.resize(buffer.capacity(), 0_u8);
+
+ loop {
+ let nread = imp::fs::syscalls::readlinkat(dirfd.as_fd(), path, &mut buffer)?;
+
+ let nread = nread as usize;
+ assert!(nread <= buffer.len());
+ if nread < buffer.len() {
+ buffer.resize(nread, 0_u8);
+ return Ok(CString::new(buffer).unwrap());
+ }
+ buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially
+ buffer.resize(buffer.capacity(), 0_u8);
+ }
+}
+
+/// `mkdirat(fd, path, mode)`—Creates a directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdirat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mkdirat.2.html
+#[inline]
+pub fn mkdirat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, mode: Mode) -> io::Result<()> {
+ path.into_with_c_str(|path| imp::fs::syscalls::mkdirat(dirfd.as_fd(), path, mode))
+}
+
+/// `linkat(old_dirfd, old_path, new_dirfd, new_path, flags)`—Creates a hard
+/// link.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/linkat.2.html
+#[inline]
+pub fn linkat<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
+ old_dirfd: PFd,
+ old_path: P,
+ new_dirfd: QFd,
+ new_path: Q,
+ flags: AtFlags,
+) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| {
+ imp::fs::syscalls::linkat(
+ old_dirfd.as_fd(),
+ old_path,
+ new_dirfd.as_fd(),
+ new_path,
+ flags,
+ )
+ })
+ })
+}
+
+/// `unlinkat(fd, path, flags)`—Unlinks a file or remove a directory.
+///
+/// With the [`REMOVEDIR`] flag, this removes a directory. This is in place
+/// of a `rmdirat` function.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [`REMOVEDIR`]: AtFlags::REMOVEDIR
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/unlinkat.2.html
+#[inline]
+pub fn unlinkat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, flags: AtFlags) -> io::Result<()> {
+ path.into_with_c_str(|path| imp::fs::syscalls::unlinkat(dirfd.as_fd(), path, flags))
+}
+
+/// `renameat(old_dirfd, old_path, new_dirfd, new_path)`—Renames a file or
+/// directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/renameat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/renameat.2.html
+#[inline]
+pub fn renameat<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
+ old_dirfd: PFd,
+ old_path: P,
+ new_dirfd: QFd,
+ new_path: Q,
+) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| {
+ imp::fs::syscalls::renameat(old_dirfd.as_fd(), old_path, new_dirfd.as_fd(), new_path)
+ })
+ })
+}
+
+/// `renameat2(old_dirfd, old_path, new_dirfd, new_path, flags)`—Renames a
+/// file or directory.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/renameat2.2.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[doc(alias = "renameat2")]
+pub fn renameat_with<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
+ old_dirfd: PFd,
+ old_path: P,
+ new_dirfd: QFd,
+ new_path: Q,
+ flags: RenameFlags,
+) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| {
+ imp::fs::syscalls::renameat2(
+ old_dirfd.as_fd(),
+ old_path,
+ new_dirfd.as_fd(),
+ new_path,
+ flags,
+ )
+ })
+ })
+}
+
+/// `symlinkat(old_dirfd, old_path, new_dirfd, new_path)`—Creates a symlink.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/symlinkat.2.html
+#[inline]
+pub fn symlinkat<P: path::Arg, Q: path::Arg, Fd: AsFd>(
+ old_path: P,
+ new_dirfd: Fd,
+ new_path: Q,
+) -> io::Result<()> {
+ old_path.into_with_c_str(|old_path| {
+ new_path.into_with_c_str(|new_path| {
+ imp::fs::syscalls::symlinkat(old_path, new_dirfd.as_fd(), new_path)
+ })
+ })
+}
+
+/// `fstatat(dirfd, path, flags)`—Queries metadata for a file or directory.
+///
+/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to
+/// interpret the `st_mode` field.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fstatat.2.html
+/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode
+/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode
+#[inline]
+#[doc(alias = "fstatat")]
+pub fn statat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, flags: AtFlags) -> io::Result<Stat> {
+ path.into_with_c_str(|path| imp::fs::syscalls::statat(dirfd.as_fd(), path, flags))
+}
+
+/// `faccessat(dirfd, path, access, flags)`—Tests permissions for a file or
+/// directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/faccessat.2.html
+#[cfg(not(target_os = "illumos"))]
+#[inline]
+#[doc(alias = "faccessat")]
+pub fn accessat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ access: Access,
+ flags: AtFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| imp::fs::syscalls::accessat(dirfd.as_fd(), path, access, flags))
+}
+
+/// `utimensat(dirfd, path, times, flags)`—Sets file or directory timestamps.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimensat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/utimensat.2.html
+#[inline]
+pub fn utimensat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ times: &Timestamps,
+ flags: AtFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| imp::fs::syscalls::utimensat(dirfd.as_fd(), path, times, flags))
+}
+
+/// `fchmodat(dirfd, path, mode, 0)`—Sets file or directory permissions.
+///
+/// The flags argument is fixed to 0, so `AT_SYMLINK_NOFOLLOW` is not
+/// supported. <details>Platform support for this flag varies widely.</details>
+///
+/// This implementation does not support `O_PATH` file descriptors, even on
+/// platforms where the host libc emulates it.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchmodat.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[doc(alias = "fchmodat")]
+pub fn chmodat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, mode: Mode) -> io::Result<()> {
+ path.into_with_c_str(|path| imp::fs::syscalls::chmodat(dirfd.as_fd(), path, mode))
+}
+
+/// `fclonefileat(src, dst_dir, dst, flags)`—Efficiently copies between files.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://opensource.apple.com/source/xnu/xnu-3789.21.4/bsd/man/man2/clonefile.2.auto.html
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[inline]
+pub fn fclonefileat<Fd: AsFd, DstFd: AsFd, P: path::Arg>(
+ src: Fd,
+ dst_dir: DstFd,
+ dst: P,
+ flags: CloneFlags,
+) -> io::Result<()> {
+ dst.into_with_c_str(|dst| {
+ imp::fs::syscalls::fclonefileat(src.as_fd(), dst_dir.as_fd(), &dst, flags)
+ })
+}
+
+/// `mknodat(dirfd, path, mode, dev)`—Creates special or normal files.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mknodat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mknodat.2.html
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
+#[inline]
+pub fn mknodat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ file_type: FileType,
+ mode: Mode,
+ dev: Dev,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| {
+ imp::fs::syscalls::mknodat(dirfd.as_fd(), path, file_type, mode, dev)
+ })
+}
+
+/// `fchownat(dirfd, path, owner, group, flags)`—Sets file or directory
+/// ownership.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchownat.2.html
+#[cfg(not(any(target_os = "wasi")))]
+#[inline]
+pub fn chownat<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ owner: Option<Uid>,
+ group: Option<Gid>,
+ flags: AtFlags,
+) -> io::Result<()> {
+ path.into_with_c_str(|path| {
+ imp::fs::syscalls::chownat(dirfd.as_fd(), path, owner, group, flags)
+ })
+}
diff --git a/vendor/rustix/src/fs/constants.rs b/vendor/rustix/src/fs/constants.rs
new file mode 100644
index 000000000..b6893a92e
--- /dev/null
+++ b/vendor/rustix/src/fs/constants.rs
@@ -0,0 +1,19 @@
+//! Filesystem API constants, translated into `bitflags` constants.
+
+use crate::imp;
+
+pub use imp::fs::types::{Access, FdFlags, Mode, OFlags};
+
+#[cfg(not(target_os = "redox"))]
+pub use imp::fs::types::AtFlags;
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub use imp::fs::types::{CloneFlags, CopyfileFlags};
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use imp::fs::types::{RenameFlags, ResolveFlags};
+
+#[cfg(not(target_os = "redox"))]
+pub use imp::fs::types::Dev;
+
+pub use imp::time::types::{Nsecs, Secs, Timespec};
diff --git a/vendor/rustix/src/fs/copy_file_range.rs b/vendor/rustix/src/fs/copy_file_range.rs
new file mode 100644
index 000000000..b12190472
--- /dev/null
+++ b/vendor/rustix/src/fs/copy_file_range.rs
@@ -0,0 +1,20 @@
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+/// `copy_file_range(fd_in, off_in, fd_out, off_out, len, 0)`—Copies data
+/// from one file to another.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/copy_file_range.2.html
+#[inline]
+pub fn copy_file_range<InFd: AsFd, OutFd: AsFd>(
+ fd_in: InFd,
+ off_in: Option<&mut u64>,
+ fd_out: OutFd,
+ off_out: Option<&mut u64>,
+ len: u64,
+) -> io::Result<u64> {
+ imp::fs::syscalls::copy_file_range(fd_in.as_fd(), off_in, fd_out.as_fd(), off_out, len)
+}
diff --git a/vendor/rustix/src/fs/cwd.rs b/vendor/rustix/src/fs/cwd.rs
new file mode 100644
index 000000000..95f97f85d
--- /dev/null
+++ b/vendor/rustix/src/fs/cwd.rs
@@ -0,0 +1,32 @@
+//! The `cwd` function, representing the current working directory.
+//!
+//! # Safety
+//!
+//! This file uses `AT_FDCWD`, which is a raw file descriptor, but which is
+//! always valid.
+
+#![allow(unsafe_code)]
+
+use crate::imp;
+use imp::fd::{BorrowedFd, RawFd};
+
+/// `AT_FDCWD`—Returns a handle representing the current working directory.
+///
+/// This returns a file descriptor which refers to the process current
+/// directory which can be used as the directory argument in `*at`
+/// functions such as [`openat`].
+///
+/// # References
+/// - [POSIX]
+///
+/// [`openat`]: crate::fs::openat
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html
+#[inline]
+#[doc(alias = "AT_FDCWD")]
+pub const fn cwd() -> BorrowedFd<'static> {
+ let at_fdcwd = imp::io::types::AT_FDCWD as RawFd;
+
+ // Safety: `AT_FDCWD` is a reserved value that is never dynamically
+ // allocated, so it'll remain valid for the duration of `'static`.
+ unsafe { BorrowedFd::<'static>::borrow_raw(at_fdcwd) }
+}
diff --git a/vendor/rustix/src/fs/dir.rs b/vendor/rustix/src/fs/dir.rs
new file mode 100644
index 000000000..f9d7ff871
--- /dev/null
+++ b/vendor/rustix/src/fs/dir.rs
@@ -0,0 +1,5 @@
+//! `Dir` and `Entry`.
+
+use crate::imp;
+
+pub use imp::fs::dir::{Dir, DirEntry};
diff --git a/vendor/rustix/src/fs/fadvise.rs b/vendor/rustix/src/fs/fadvise.rs
new file mode 100644
index 000000000..ead3ad9a3
--- /dev/null
+++ b/vendor/rustix/src/fs/fadvise.rs
@@ -0,0 +1,19 @@
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+pub use imp::fs::types::Advice;
+
+/// `posix_fadvise(fd, offset, len, advice)`—Declares an expected access
+/// pattern for a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fadvise.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/posix_fadvise.2.html
+#[inline]
+#[doc(alias = "posix_fadvise")]
+pub fn fadvise<Fd: AsFd>(fd: Fd, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
+ imp::fs::syscalls::fadvise(fd.as_fd(), offset, len, advice)
+}
diff --git a/vendor/rustix/src/fs/fcntl.rs b/vendor/rustix/src/fs/fcntl.rs
new file mode 100644
index 000000000..7f89873b5
--- /dev/null
+++ b/vendor/rustix/src/fs/fcntl.rs
@@ -0,0 +1,131 @@
+//! 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.
+
+use crate::imp;
+use crate::io::{self, OwnedFd};
+use imp::fd::{AsFd, RawFd};
+use imp::fs::types::{FdFlags, OFlags};
+
+/// `fcntl(fd, F_GETFD)`—Returns a file descriptor's flags.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[inline]
+#[doc(alias = "F_GETFD")]
+pub fn fcntl_getfd<Fd: AsFd>(fd: Fd) -> io::Result<FdFlags> {
+ imp::fs::syscalls::fcntl_getfd(fd.as_fd())
+}
+
+/// `fcntl(fd, F_SETFD, flags)`—Sets a file descriptor's flags.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[inline]
+#[doc(alias = "F_SETFD")]
+pub fn fcntl_setfd<Fd: AsFd>(fd: Fd, flags: FdFlags) -> io::Result<()> {
+ imp::fs::syscalls::fcntl_setfd(fd.as_fd(), flags)
+}
+
+/// `fcntl(fd, F_GETFL)`—Returns a file descriptor's access mode and status.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[inline]
+#[doc(alias = "F_GETFL")]
+pub fn fcntl_getfl<Fd: AsFd>(fd: Fd) -> io::Result<OFlags> {
+ imp::fs::syscalls::fcntl_getfl(fd.as_fd())
+}
+
+/// `fcntl(fd, F_SETFL, flags)`—Sets a file descriptor's status.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[inline]
+#[doc(alias = "F_SETFL")]
+pub fn fcntl_setfl<Fd: AsFd>(fd: Fd, flags: OFlags) -> io::Result<()> {
+ imp::fs::syscalls::fcntl_setfl(fd.as_fd(), flags)
+}
+
+/// `fcntl(fd, F_GET_SEALS)`
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[cfg(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+#[inline]
+#[doc(alias = "F_GET_SEALS")]
+pub fn fcntl_get_seals<Fd: AsFd>(fd: Fd) -> io::Result<SealFlags> {
+ imp::fs::syscalls::fcntl_get_seals(fd.as_fd())
+}
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+pub use imp::fs::types::SealFlags;
+
+/// `fcntl(fd, F_ADD_SEALS)`
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[cfg(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+#[inline]
+#[doc(alias = "F_ADD_SEALS")]
+pub fn fcntl_add_seals<Fd: AsFd>(fd: Fd, seals: SealFlags) -> io::Result<()> {
+ imp::fs::syscalls::fcntl_add_seals(fd.as_fd(), seals)
+}
+
+/// `fcntl(fd, F_DUPFD_CLOEXEC)`—Creates a new `OwnedFd` instance, with value
+/// at least `min`, that has `O_CLOEXEC` set and that shares the same
+/// underlying [file description] as `fd`.
+///
+/// POSIX guarantees that `F_DUPFD_CLOEXEC` will use the lowest unused file
+/// descriptor which is at least `min`, however it is not safe in general to
+/// rely on this, as file descriptors may be unexpectedly allocated on other
+/// threads or in libraries.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[doc(alias = "F_DUPFD_CLOEXEC")]
+pub fn fcntl_dupfd_cloexec<Fd: AsFd>(fd: Fd, min: RawFd) -> io::Result<OwnedFd> {
+ imp::fs::syscalls::fcntl_dupfd_cloexec(fd.as_fd(), min)
+}
diff --git a/vendor/rustix/src/fs/fcntl_darwin.rs b/vendor/rustix/src/fs/fcntl_darwin.rs
new file mode 100644
index 000000000..17d8f844f
--- /dev/null
+++ b/vendor/rustix/src/fs/fcntl_darwin.rs
@@ -0,0 +1,24 @@
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+/// `fcntl(fd, F_RDADVISE, radvisory { offset, len })`
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+#[inline]
+pub fn fcntl_rdadvise<Fd: AsFd>(fd: Fd, offset: u64, len: u64) -> io::Result<()> {
+ imp::fs::syscalls::fcntl_rdadvise(fd.as_fd(), offset, len)
+}
+
+/// `fcntl(fd, F_FULLFSYNC)`
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+#[inline]
+pub fn fcntl_fullfsync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::fs::syscalls::fcntl_fullfsync(fd.as_fd())
+}
diff --git a/vendor/rustix/src/fs/fcopyfile.rs b/vendor/rustix/src/fs/fcopyfile.rs
new file mode 100644
index 000000000..c5b00ce10
--- /dev/null
+++ b/vendor/rustix/src/fs/fcopyfile.rs
@@ -0,0 +1,90 @@
+use crate::fs::CopyfileFlags;
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+/// `copyfile_state_t`
+pub use imp::fs::types::copyfile_state_t;
+
+/// `fcopyfile(from, to, state, flags)`
+///
+/// # Safety
+///
+/// The `state` operand must be allocated with `copyfile_state_alloc` and not
+/// yet freed with `copyfile_state_free`.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub unsafe fn fcopyfile<FromFd: AsFd, ToFd: AsFd>(
+ from: FromFd,
+ to: ToFd,
+ state: copyfile_state_t,
+ flags: CopyfileFlags,
+) -> io::Result<()> {
+ imp::fs::syscalls::fcopyfile(from.as_fd(), to.as_fd(), state, flags)
+}
+
+/// `copyfile_state_alloc()`
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub fn copyfile_state_alloc() -> io::Result<copyfile_state_t> {
+ imp::fs::syscalls::copyfile_state_alloc()
+}
+
+/// `copyfile_state_free(state)`
+///
+/// # Safety
+///
+/// The `state` operand must be allocated with `copyfile_state_alloc` and not
+/// yet freed with `copyfile_state_free`.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub unsafe fn copyfile_state_free(state: copyfile_state_t) -> io::Result<()> {
+ imp::fs::syscalls::copyfile_state_free(state)
+}
+
+/// `copyfile_state_get(state, COPYFILE_STATE_COPIED)`
+///
+/// # Safety
+///
+/// The `state` operand must be allocated with `copyfile_state_alloc` and not
+/// yet freed with `copyfile_state_free`.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub unsafe fn copyfile_state_get_copied(state: copyfile_state_t) -> io::Result<u64> {
+ imp::fs::syscalls::copyfile_state_get_copied(state)
+}
+
+/// `copyfile_state_get(state, flags, dst)`
+///
+/// # Safety
+///
+/// The `state` operand must be allocated with `copyfile_state_alloc` and not
+/// yet freed with `copyfile_state_free`.
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html
+#[inline]
+pub unsafe fn copyfile_state_get(
+ state: copyfile_state_t,
+ flag: u32,
+ dst: *mut core::ffi::c_void,
+) -> io::Result<()> {
+ imp::fs::syscalls::copyfile_state_get(state, flag, dst)
+}
diff --git a/vendor/rustix/src/fs/fd.rs b/vendor/rustix/src/fs/fd.rs
new file mode 100644
index 000000000..b41579fb8
--- /dev/null
+++ b/vendor/rustix/src/fs/fd.rs
@@ -0,0 +1,301 @@
+//! Functions which operate on file descriptors.
+
+#[cfg(not(target_os = "wasi"))]
+use crate::fs::Mode;
+use crate::io::SeekFrom;
+#[cfg(not(target_os = "wasi"))]
+use crate::process::{Gid, Uid};
+use crate::{imp, io};
+use imp::fd::{AsFd, BorrowedFd};
+
+#[cfg(not(target_os = "wasi"))]
+pub use imp::fs::types::FlockOperation;
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::fs::types::FallocateFlags;
+
+pub use imp::fs::types::Stat;
+
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub use imp::fs::types::StatFs;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use imp::fs::types::FsWord;
+
+/// Timestamps used by [`utimensat`] and [`futimens`].
+///
+/// [`utimensat`]: crate::fs::utimensat
+/// [`futimens`]: crate::fs::futimens
+// This is `repr(C)` and specifically laid out to match the representation used
+// by `utimensat` and `futimens`, which expect 2-element arrays of timestamps.
+#[repr(C)]
+#[derive(Clone, Debug)]
+pub struct Timestamps {
+ /// The timestamp of the last access to a filesystem object.
+ pub last_access: crate::fs::Timespec,
+
+ /// The timestamp of the last modification of a filesystem object.
+ pub last_modification: crate::fs::Timespec,
+}
+
+/// The filesystem magic number for procfs.
+///
+/// See [the `fstatfs` man page] for more information.
+///
+/// [the `fstatfs` man page]: https://man7.org/linux/man-pages/man2/fstatfs.2.html#DESCRIPTION
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub const PROC_SUPER_MAGIC: FsWord = imp::fs::types::PROC_SUPER_MAGIC;
+
+/// The filesystem magic number for NFS.
+///
+/// See [the `fstatfs` man page] for more information.
+///
+/// [the `fstatfs` man page]: https://man7.org/linux/man-pages/man2/fstatfs.2.html#DESCRIPTION
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub const NFS_SUPER_MAGIC: FsWord = imp::fs::types::NFS_SUPER_MAGIC;
+
+/// `lseek(fd, offset, whence)`—Repositions a file descriptor within a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/lseek.2.html
+#[inline]
+pub fn seek<Fd: AsFd>(fd: Fd, pos: SeekFrom) -> io::Result<u64> {
+ imp::fs::syscalls::seek(fd.as_fd(), pos)
+}
+
+/// `lseek(fd, 0, SEEK_CUR)`—Returns the current position within a file.
+///
+/// Return the current position of the file descriptor. This is a subset of
+/// the functionality of `seek`, but this interface makes it easier for users
+/// to declare their intent not to mutate any state.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/lseek.2.html
+#[inline]
+pub fn tell<Fd: AsFd>(fd: Fd) -> io::Result<u64> {
+ imp::fs::syscalls::tell(fd.as_fd())
+}
+
+/// `fchmod(fd)`—Sets open file or directory permissions.
+///
+/// This implementation does not support `O_PATH` file descriptors, even on
+/// platforms where the host libc emulates it.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchmod.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn fchmod<Fd: AsFd>(fd: Fd, mode: Mode) -> io::Result<()> {
+ imp::fs::syscalls::fchmod(fd.as_fd(), mode)
+}
+
+/// `fchown(fd)`—Sets open file or directory ownership.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchown.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn fchown<Fd: AsFd>(fd: Fd, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
+ imp::fs::syscalls::fchown(fd.as_fd(), owner, group)
+}
+
+/// `fstat(fd)`—Queries metadata for an open file or directory.
+///
+/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to
+/// interpret the `st_mode` field.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstat.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fstat.2.html
+/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode
+/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode
+#[inline]
+pub fn fstat<Fd: AsFd>(fd: Fd) -> io::Result<Stat> {
+ imp::fs::syscalls::fstat(fd.as_fd())
+}
+
+/// `fstatfs(fd)`—Queries filesystem statistics for an open file or directory.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/fstatfs.2.html
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))] // not implemented in libc for netbsd yet
+#[inline]
+pub fn fstatfs<Fd: AsFd>(fd: Fd) -> io::Result<StatFs> {
+ imp::fs::syscalls::fstatfs(fd.as_fd())
+}
+
+/// `futimens(fd, times)`—Sets timestamps for an open file or directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/utimensat.2.html
+#[inline]
+pub fn futimens<Fd: AsFd>(fd: Fd, times: &Timestamps) -> io::Result<()> {
+ imp::fs::syscalls::futimens(fd.as_fd(), times)
+}
+
+/// `fallocate(fd, mode, offset, len)`—Adjusts file allocation.
+///
+/// This is a more general form of `posix_fallocate`, adding a `mode` argument
+/// which modifies the behavior. On platforms which only support
+/// `posix_fallocate` and not the more general form, no `FallocateFlags` values
+/// are defined so it will always be empty.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux `fallocate`]
+/// - [Linux `posix_fallocate`]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html
+/// [Linux `fallocate`]: https://man7.org/linux/man-pages/man2/fallocate.2.html
+/// [Linux `posix_fallocate`]: https://man7.org/linux/man-pages/man3/posix_fallocate.3.html
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))] // not implemented in libc for netbsd yet
+#[inline]
+#[doc(alias = "posix_fallocate")]
+pub fn fallocate<Fd: AsFd>(fd: Fd, mode: FallocateFlags, offset: u64, len: u64) -> io::Result<()> {
+ imp::fs::syscalls::fallocate(fd.as_fd(), mode, offset, len)
+}
+
+/// `fcntl(fd, F_GETFL) & O_ACCMODE`
+///
+/// Returns a pair of booleans indicating whether the file descriptor is
+/// readable and/or writable, respectively. This is only reliable on files; for
+/// example, it doesn't reflect whether sockets have been shut down; for
+/// general I/O handle support, use [`io::is_read_write`].
+#[inline]
+pub fn is_file_read_write<Fd: AsFd>(fd: Fd) -> io::Result<(bool, bool)> {
+ _is_file_read_write(fd.as_fd())
+}
+
+pub(crate) fn _is_file_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
+ let mode = imp::fs::syscalls::fcntl_getfl(fd)?;
+
+ // Check for `O_PATH`.
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux",
+ target_os = "emscripten",
+ ))]
+ if mode.contains(crate::fs::OFlags::PATH) {
+ return Ok((false, false));
+ }
+
+ // Use `RWMODE` rather than `ACCMODE` as `ACCMODE` may include `O_PATH`.
+ // We handled `O_PATH` above.
+ match mode & crate::fs::OFlags::RWMODE {
+ crate::fs::OFlags::RDONLY => Ok((true, false)),
+ crate::fs::OFlags::RDWR => Ok((true, true)),
+ crate::fs::OFlags::WRONLY => Ok((false, true)),
+ _ => unreachable!(),
+ }
+}
+
+/// `fsync(fd)`—Ensures that file data and metadata is written to the
+/// underlying storage device.
+///
+/// On iOS and macOS this isn't sufficient to ensure that data has reached
+/// persistent storage; use [`fcntl_fullfsync`] to ensure that.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fsync.2.html
+/// [`fcntl_fullfsync`]: https://docs.rs/rustix/*/x86_64-apple-darwin/rustix/fs/fn.fcntl_fullfsync.html
+#[inline]
+pub fn fsync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::fs::syscalls::fsync(fd.as_fd())
+}
+
+/// `fdatasync(fd)`—Ensures that file data is written to the underlying
+/// storage device.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fdatasync.2.html
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+#[inline]
+pub fn fdatasync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::fs::syscalls::fdatasync(fd.as_fd())
+}
+
+/// `ftruncate(fd, length)`—Sets the length of a file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/ftruncate.2.html
+#[inline]
+pub fn ftruncate<Fd: AsFd>(fd: Fd, length: u64) -> io::Result<()> {
+ imp::fs::syscalls::ftruncate(fd.as_fd(), length)
+}
+
+/// `flock(fd, operation)`—Acquire or release an advisory lock on an open file.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/flock.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn flock<Fd: AsFd>(fd: Fd, operation: FlockOperation) -> io::Result<()> {
+ imp::fs::syscalls::flock(fd.as_fd(), operation)
+}
diff --git a/vendor/rustix/src/fs/file_type.rs b/vendor/rustix/src/fs/file_type.rs
new file mode 100644
index 000000000..75935c794
--- /dev/null
+++ b/vendor/rustix/src/fs/file_type.rs
@@ -0,0 +1,4 @@
+use crate::imp;
+
+/// `S_IF*` constants.
+pub use imp::fs::types::FileType;
diff --git a/vendor/rustix/src/fs/getpath.rs b/vendor/rustix/src/fs/getpath.rs
new file mode 100644
index 000000000..bc40890d1
--- /dev/null
+++ b/vendor/rustix/src/fs/getpath.rs
@@ -0,0 +1,14 @@
+use crate::ffi::CString;
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+/// `fcntl(fd, F_GETPATH)`
+///
+/// # References
+/// - [Apple]
+///
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+#[inline]
+pub fn getpath<Fd: AsFd>(fd: Fd) -> io::Result<CString> {
+ imp::fs::syscalls::getpath(fd.as_fd())
+}
diff --git a/vendor/rustix/src/fs/makedev.rs b/vendor/rustix/src/fs/makedev.rs
new file mode 100644
index 000000000..75cc42540
--- /dev/null
+++ b/vendor/rustix/src/fs/makedev.rs
@@ -0,0 +1,35 @@
+use crate::fs::Dev;
+use crate::imp;
+
+/// `makedev(maj, min)`
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/makedev.3.html
+#[inline]
+pub fn makedev(maj: u32, min: u32) -> Dev {
+ imp::fs::makedev::makedev(maj, min)
+}
+
+/// `minor(dev)`
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/minor.3.html
+#[inline]
+pub fn minor(dev: Dev) -> u32 {
+ imp::fs::makedev::minor(dev)
+}
+
+/// `major(dev)`
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/major.3.html
+#[inline]
+pub fn major(dev: Dev) -> u32 {
+ imp::fs::makedev::major(dev)
+}
diff --git a/vendor/rustix/src/fs/memfd_create.rs b/vendor/rustix/src/fs/memfd_create.rs
new file mode 100644
index 000000000..74b432739
--- /dev/null
+++ b/vendor/rustix/src/fs/memfd_create.rs
@@ -0,0 +1,15 @@
+use crate::io::{self, OwnedFd};
+use crate::{imp, path};
+
+pub use imp::fs::types::MemfdFlags;
+
+/// `memfd_create(path, flags)`
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
+#[inline]
+pub fn memfd_create<P: path::Arg>(path: P, flags: MemfdFlags) -> io::Result<OwnedFd> {
+ path.into_with_c_str(|path| imp::fs::syscalls::memfd_create(path, flags))
+}
diff --git a/vendor/rustix/src/fs/mod.rs b/vendor/rustix/src/fs/mod.rs
new file mode 100644
index 000000000..49b9c3b51
--- /dev/null
+++ b/vendor/rustix/src/fs/mod.rs
@@ -0,0 +1,196 @@
+//! Filesystem operations.
+
+#[cfg(feature = "fs")]
+mod abs;
+#[cfg(not(target_os = "redox"))]
+#[cfg(any(feature = "fs", feature = "procfs"))]
+mod at;
+mod constants;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod copy_file_range;
+#[cfg(not(target_os = "redox"))]
+mod cwd;
+#[cfg(not(target_os = "redox"))]
+#[cfg(any(feature = "fs", feature = "procfs"))]
+mod dir;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+mod fadvise;
+pub(crate) mod fcntl;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+mod fcntl_darwin;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+mod fcopyfile;
+pub(crate) mod fd;
+mod file_type;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+mod getpath;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+mod makedev;
+#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+mod memfd_create;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(feature = "fs")]
+mod openat2;
+#[cfg(target_os = "linux")]
+mod sendfile;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod statx;
+
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[cfg(feature = "fs")]
+pub use abs::statfs;
+#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
+#[cfg(feature = "fs")]
+pub use at::accessat;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(feature = "fs")]
+pub use at::fclonefileat;
+#[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[cfg(feature = "fs")]
+pub use at::mknodat;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(feature = "fs")]
+pub use at::renameat_with;
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[cfg(feature = "fs")]
+pub use at::{chmodat, chownat};
+#[cfg(not(target_os = "redox"))]
+#[cfg(any(feature = "fs", feature = "procfs"))]
+pub use at::{
+ linkat, mkdirat, openat, readlinkat, renameat, statat, symlinkat, unlinkat, utimensat, RawMode,
+ UTIME_NOW, UTIME_OMIT,
+};
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub use constants::CloneFlags;
+/// `copyfile_flags_t`
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub use constants::CopyfileFlags;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use constants::RenameFlags;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use constants::ResolveFlags;
+pub use constants::{Access, FdFlags, Mode, Nsecs, OFlags, Secs, Timespec};
+#[cfg(not(target_os = "redox"))]
+pub use constants::{AtFlags, Dev};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use copy_file_range::copy_file_range;
+#[cfg(not(target_os = "redox"))]
+pub use cwd::cwd;
+#[cfg(not(target_os = "redox"))]
+#[cfg(any(feature = "fs", feature = "procfs"))]
+pub use dir::{Dir, DirEntry};
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use fadvise::{fadvise, Advice};
+#[cfg(not(target_os = "wasi"))]
+pub use fcntl::fcntl_dupfd_cloexec;
+#[cfg(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+pub use fcntl::{fcntl_add_seals, fcntl_get_seals, SealFlags};
+pub use fcntl::{fcntl_getfd, fcntl_getfl, fcntl_setfd, fcntl_setfl};
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub use fcntl_darwin::{fcntl_fullfsync, fcntl_rdadvise};
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub use fcopyfile::{
+ copyfile_state_alloc, copyfile_state_free, copyfile_state_get, copyfile_state_get_copied,
+ copyfile_state_t, fcopyfile,
+};
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub use fd::fdatasync;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use fd::{fallocate, FallocateFlags};
+#[cfg(not(target_os = "wasi"))]
+pub use fd::{fchmod, fchown, flock, FlockOperation};
+pub use fd::{fstat, fsync, ftruncate, futimens, is_file_read_write, seek, tell, Stat, Timestamps};
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+// not implemented in libc for netbsd yet
+pub use fd::{fstatfs, StatFs};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use fd::{FsWord, NFS_SUPER_MAGIC, PROC_SUPER_MAGIC};
+pub use file_type::FileType;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub use getpath::getpath;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub use makedev::{major, makedev, minor};
+#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+pub use memfd_create::{memfd_create, MemfdFlags};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(feature = "fs")]
+pub use openat2::openat2;
+#[cfg(target_os = "linux")]
+pub use sendfile::sendfile;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use statx::{statx, Statx, StatxFlags, StatxTimestamp};
+
+/// Re-export types common to POSIX-ish platforms.
+#[cfg(feature = "std")]
+#[cfg(unix)]
+pub use std::os::unix::fs::{DirEntryExt, FileExt, FileTypeExt, MetadataExt, OpenOptionsExt};
+#[cfg(feature = "std")]
+#[cfg(target_os = "wasi")]
+pub use std::os::wasi::fs::{DirEntryExt, FileExt, FileTypeExt, MetadataExt, OpenOptionsExt};
diff --git a/vendor/rustix/src/fs/openat2.rs b/vendor/rustix/src/fs/openat2.rs
new file mode 100644
index 000000000..d6f77357b
--- /dev/null
+++ b/vendor/rustix/src/fs/openat2.rs
@@ -0,0 +1,23 @@
+use crate::io::{self, OwnedFd};
+use crate::{imp, path};
+use imp::fd::AsFd;
+use imp::fs::types::{Mode, OFlags, ResolveFlags};
+
+/// `openat2(dirfd, path, OpenHow { oflags, mode, resolve }, sizeof(OpenHow))`
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/openat2.2.html
+#[inline]
+pub fn openat2<Fd: AsFd, P: path::Arg>(
+ dirfd: Fd,
+ path: P,
+ oflags: OFlags,
+ mode: Mode,
+ resolve: ResolveFlags,
+) -> io::Result<OwnedFd> {
+ path.into_with_c_str(|path| {
+ imp::fs::syscalls::openat2(dirfd.as_fd(), path, oflags, mode, resolve)
+ })
+}
diff --git a/vendor/rustix/src/fs/sendfile.rs b/vendor/rustix/src/fs/sendfile.rs
new file mode 100644
index 000000000..a4d8c24d4
--- /dev/null
+++ b/vendor/rustix/src/fs/sendfile.rs
@@ -0,0 +1,19 @@
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+/// `sendfile(out_fd, in_fd, offset, count)`
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/sendfile.2.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub fn sendfile<OutFd: AsFd, InFd: AsFd>(
+ out_fd: OutFd,
+ in_fd: InFd,
+ offset: Option<&mut u64>,
+ count: usize,
+) -> io::Result<usize> {
+ imp::fs::syscalls::sendfile(out_fd.as_fd(), in_fd.as_fd(), offset, count)
+}
diff --git a/vendor/rustix/src/fs/statx.rs b/vendor/rustix/src/fs/statx.rs
new file mode 100644
index 000000000..fa1d36779
--- /dev/null
+++ b/vendor/rustix/src/fs/statx.rs
@@ -0,0 +1,91 @@
+//! Linux `statx`.
+
+use crate::fd::{AsFd, BorrowedFd};
+use crate::ffi::CStr;
+use crate::fs::AtFlags;
+use crate::{imp, io, path};
+use core::sync::atomic::{AtomicU8, Ordering};
+
+pub use imp::fs::types::{Statx, StatxFlags, StatxTimestamp};
+
+/// `statx(dirfd, path, flags, mask, statxbuf)`
+///
+/// This function returns [`io::Errno::NOSYS`] if `statx` is not available on
+/// the platform, such as Linux before 4.11. This also includes older Docker
+/// versions where the actual syscall fails with different error codes; Rustix
+/// handles this and translates them into `NOSYS`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/statx.2.html
+#[inline]
+pub fn statx<P: path::Arg, Fd: AsFd>(
+ dirfd: Fd,
+ path: P,
+ flags: AtFlags,
+ mask: StatxFlags,
+) -> io::Result<Statx> {
+ path.into_with_c_str(|path| _statx(dirfd.as_fd(), path, flags, mask))
+}
+
+// Linux kernel prior to 4.11 old versions of Docker don't support `statx`. We
+// store the availability in a global to avoid unnecessary syscalls.
+//
+// 0: Unknown
+// 1: Not available
+// 2: Available
+static STATX_STATE: AtomicU8 = AtomicU8::new(0);
+
+#[inline]
+fn _statx(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ flags: AtFlags,
+ mask: StatxFlags,
+) -> io::Result<Statx> {
+ match STATX_STATE.load(Ordering::Relaxed) {
+ 0 => statx_init(dirfd, path, flags, mask),
+ 1 => Err(io::Errno::NOSYS),
+ _ => imp::fs::syscalls::statx(dirfd, path, flags, mask),
+ }
+}
+
+/// The first `statx` call. We don't know if `statx` is available yet.
+fn statx_init(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ flags: AtFlags,
+ mask: StatxFlags,
+) -> io::Result<Statx> {
+ match imp::fs::syscalls::statx(dirfd, path, flags, mask) {
+ Err(io::Errno::NOSYS) => statx_error_nosys(),
+ Err(io::Errno::PERM) => statx_error_perm(),
+ result => {
+ STATX_STATE.store(2, Ordering::Relaxed);
+ result
+ }
+ }
+}
+
+/// The first `statx` call failed with `NOSYS` (or something we're treating
+/// like `NOSYS`).
+#[cold]
+fn statx_error_nosys() -> io::Result<Statx> {
+ STATX_STATE.store(1, Ordering::Relaxed);
+ Err(io::Errno::NOSYS)
+}
+
+/// The first `statx` call failed with `PERM`.
+#[cold]
+fn statx_error_perm() -> io::Result<Statx> {
+ // Some old versions of Docker have `statx` fail with `PERM` when it isn't
+ // recognized. Check whether `statx` really is available, and if so, fail
+ // with `PERM`, and if not, treat it like `NOSYS`.
+ if imp::fs::syscalls::is_statx_available() {
+ STATX_STATE.store(2, Ordering::Relaxed);
+ Err(io::Errno::PERM)
+ } else {
+ statx_error_nosys()
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/conv.rs b/vendor/rustix/src/imp/libc/conv.rs
new file mode 100644
index 000000000..fed15fbd1
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/conv.rs
@@ -0,0 +1,220 @@
+//! Libc call arguments and return values are often things like `c_int`,
+//! `c_uint`, or libc-specific pointer types. This module provides functions
+//! for converting between rustix's types and libc types.
+
+#![allow(dead_code)]
+
+use super::c;
+use super::fd::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, LibcFd, RawFd};
+#[cfg(not(windows))]
+use super::offset::libc_off_t;
+#[cfg(not(windows))]
+use crate::ffi::CStr;
+use crate::io::{self, OwnedFd};
+#[cfg(windows)]
+use core::convert::TryInto;
+
+#[cfg(not(windows))]
+#[inline]
+pub(super) fn c_str(c: &CStr) -> *const c::c_char {
+ c.as_ptr()
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(super) fn no_fd() -> LibcFd {
+ -1
+}
+
+#[inline]
+pub(super) fn borrowed_fd(fd: BorrowedFd<'_>) -> LibcFd {
+ fd.as_raw_fd() as LibcFd
+}
+
+#[inline]
+pub(super) fn owned_fd(fd: OwnedFd) -> LibcFd {
+ fd.into_raw_fd() as LibcFd
+}
+
+#[inline]
+pub(super) fn ret(raw: c::c_int) -> io::Result<()> {
+ if raw == 0 {
+ Ok(())
+ } else {
+ Err(io::Errno::last_os_error())
+ }
+}
+
+#[inline]
+pub(super) fn syscall_ret(raw: c::c_long) -> io::Result<()> {
+ if raw == 0 {
+ Ok(())
+ } else {
+ Err(io::Errno::last_os_error())
+ }
+}
+
+#[inline]
+pub(super) fn nonnegative_ret(raw: c::c_int) -> io::Result<()> {
+ if raw >= 0 {
+ Ok(())
+ } else {
+ Err(io::Errno::last_os_error())
+ }
+}
+
+#[inline]
+pub(super) unsafe fn ret_infallible(raw: c::c_int) {
+ debug_assert_eq!(raw, 0, "unexpected error: {:?}", io::Errno::last_os_error());
+}
+
+#[inline]
+pub(super) fn ret_c_int(raw: c::c_int) -> io::Result<c::c_int> {
+ if raw == -1 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(raw)
+ }
+}
+
+#[inline]
+pub(super) fn ret_u32(raw: c::c_int) -> io::Result<u32> {
+ if raw == -1 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(raw as u32)
+ }
+}
+
+#[inline]
+pub(super) fn ret_ssize_t(raw: c::ssize_t) -> io::Result<c::ssize_t> {
+ if raw == -1 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(raw)
+ }
+}
+
+#[inline]
+pub(super) fn syscall_ret_ssize_t(raw: c::c_long) -> io::Result<c::ssize_t> {
+ if raw == -1 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(raw as c::ssize_t)
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub(super) fn syscall_ret_u32(raw: c::c_long) -> io::Result<u32> {
+ if raw == -1 {
+ Err(io::Errno::last_os_error())
+ } else {
+ let r32 = raw as u32;
+
+ // Converting `raw` to `u32` should be lossless.
+ debug_assert_eq!(r32 as c::c_long, raw);
+
+ Ok(r32)
+ }
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(super) fn ret_off_t(raw: libc_off_t) -> io::Result<libc_off_t> {
+ if raw == -1 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(raw)
+ }
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(super) fn ret_pid_t(raw: c::pid_t) -> io::Result<c::pid_t> {
+ if raw == -1 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(raw)
+ }
+}
+
+/// Convert a `c_int` returned from a libc function to an `OwnedFd`, if valid.
+///
+/// # Safety
+///
+/// The caller must ensure that this is the return value of a libc function
+/// which returns an owned file descriptor.
+#[inline]
+pub(super) unsafe fn ret_owned_fd(raw: LibcFd) -> io::Result<OwnedFd> {
+ if raw == !0 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(OwnedFd::from_raw_fd(raw as RawFd))
+ }
+}
+
+#[inline]
+pub(super) fn ret_discarded_fd(raw: LibcFd) -> io::Result<()> {
+ if raw == !0 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+#[inline]
+pub(super) fn ret_discarded_char_ptr(raw: *mut c::c_char) -> io::Result<()> {
+ if raw.is_null() {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+/// Convert a `c_long` returned from `syscall` to an `OwnedFd`, if valid.
+///
+/// # Safety
+///
+/// The caller must ensure that this is the return value of a `syscall` call
+/// which returns an owned file descriptor.
+#[cfg(not(windows))]
+#[inline]
+pub(super) unsafe fn syscall_ret_owned_fd(raw: c::c_long) -> io::Result<OwnedFd> {
+ if raw == -1 {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(OwnedFd::from_raw_fd(raw as RawFd))
+ }
+}
+
+/// Convert the buffer-length argument value of a `send` or `recv` call.
+#[cfg(not(windows))]
+#[inline]
+pub(super) fn send_recv_len(len: usize) -> usize {
+ len
+}
+
+/// Convert the buffer-length argument value of a `send` or `recv` call.
+#[cfg(windows)]
+#[inline]
+pub(super) fn send_recv_len(len: usize) -> i32 {
+ // On Windows, the length argument has type `i32`; saturate the length,
+ // since `send` and `recv` are allowed to send and recv less data than
+ // requested.
+ len.try_into().unwrap_or(i32::MAX)
+}
+
+/// Convert the return value of a `send` or `recv` call.
+#[cfg(not(windows))]
+#[inline]
+pub(super) fn ret_send_recv(len: isize) -> io::Result<c::ssize_t> {
+ ret_ssize_t(len)
+}
+
+/// Convert the return value of a `send` or `recv` call.
+#[cfg(windows)]
+#[inline]
+pub(super) fn ret_send_recv(len: i32) -> io::Result<c::ssize_t> {
+ ret_ssize_t(len as isize)
+}
diff --git a/vendor/rustix/src/imp/libc/fs/dir.rs b/vendor/rustix/src/imp/libc/fs/dir.rs
new file mode 100644
index 000000000..1e6b6066f
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/fs/dir.rs
@@ -0,0 +1,402 @@
+use super::super::c;
+use super::super::conv::owned_fd;
+#[cfg(not(target_os = "illumos"))]
+use super::types::FileType;
+use crate::fd::{AsFd, BorrowedFd};
+use crate::ffi::CStr;
+#[cfg(target_os = "wasi")]
+use crate::ffi::CString;
+use crate::fs::{fcntl_getfl, fstat, openat, Mode, OFlags, Stat};
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))] // not implemented in libc for netbsd yet
+use crate::fs::{fstatfs, StatFs};
+use crate::io;
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+use crate::process::fchdir;
+#[cfg(target_os = "wasi")]
+use alloc::borrow::ToOwned;
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "l4re",
+ target_os = "linux",
+ target_os = "openbsd",
+)))]
+use c::dirent as libc_dirent;
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "l4re",
+ target_os = "linux",
+)))]
+use c::readdir as libc_readdir;
+#[cfg(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "l4re",
+ target_os = "linux",
+))]
+use c::{dirent64 as libc_dirent, readdir64 as libc_readdir};
+use core::fmt;
+use core::mem::zeroed;
+use core::ptr::NonNull;
+use libc_errno::{errno, set_errno, Errno};
+
+/// `DIR*`
+#[repr(transparent)]
+pub struct Dir(NonNull<c::DIR>);
+
+impl Dir {
+ /// Construct a `Dir` that reads entries from the given directory
+ /// file descriptor.
+ #[inline]
+ pub fn read_from<Fd: AsFd>(fd: Fd) -> io::Result<Self> {
+ Self::_read_from(fd.as_fd())
+ }
+
+ #[inline]
+ fn _read_from(fd: BorrowedFd<'_>) -> io::Result<Self> {
+ // Given an arbitrary `OwnedFd`, it's impossible to know whether the
+ // user holds a `dup`'d copy which could continue to modify the
+ // file description state, which would cause Undefined Behavior after
+ // our call to `fdopendir`. To prevent this, we obtain an independent
+ // `OwnedFd`.
+ let flags = fcntl_getfl(&fd)?;
+ let fd_for_dir = openat(&fd, cstr!("."), flags | OFlags::CLOEXEC, Mode::empty())?;
+
+ let raw = owned_fd(fd_for_dir);
+ unsafe {
+ let libc_dir = c::fdopendir(raw);
+
+ if let Some(libc_dir) = NonNull::new(libc_dir) {
+ Ok(Self(libc_dir))
+ } else {
+ let e = io::Errno::last_os_error();
+ let _ = c::close(raw);
+ Err(e)
+ }
+ }
+ }
+
+ /// `rewinddir(self)`
+ #[inline]
+ pub fn rewind(&mut self) {
+ unsafe { c::rewinddir(self.0.as_ptr()) }
+ }
+
+ /// `readdir(self)`, where `None` means the end of the directory.
+ pub fn read(&mut self) -> Option<io::Result<DirEntry>> {
+ set_errno(Errno(0));
+ let dirent_ptr = unsafe { libc_readdir(self.0.as_ptr()) };
+ if dirent_ptr.is_null() {
+ let curr_errno = errno().0;
+ if curr_errno == 0 {
+ // We successfully reached the end of the stream.
+ None
+ } else {
+ // `errno` is unknown or non-zero, so an error occurred.
+ Some(Err(io::Errno(curr_errno)))
+ }
+ } else {
+ // We successfully read an entry.
+ unsafe {
+ // We have our own copy of OpenBSD's dirent; check that the
+ // layout minimally matches libc's.
+ #[cfg(target_os = "openbsd")]
+ check_dirent_layout(&*dirent_ptr);
+
+ let result = DirEntry {
+ dirent: read_dirent(&*dirent_ptr.cast()),
+
+ #[cfg(target_os = "wasi")]
+ name: CStr::from_ptr((*dirent_ptr).d_name.as_ptr()).to_owned(),
+ };
+
+ Some(Ok(result))
+ }
+ }
+ }
+
+ /// `fstat(self)`
+ #[inline]
+ pub fn stat(&self) -> io::Result<Stat> {
+ fstat(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
+ }
+
+ /// `fstatfs(self)`
+ #[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+ )))] // not implemented in libc for netbsd yet
+ #[inline]
+ pub fn statfs(&self) -> io::Result<StatFs> {
+ fstatfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
+ }
+
+ /// `fchdir(self)`
+ #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+ #[inline]
+ pub fn chdir(&self) -> io::Result<()> {
+ fchdir(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
+ }
+}
+
+// A `dirent` pointer returned from `readdir` may not point to a full `dirent`
+// struct, as the name is NUL-terminated and memory may not be allocated for
+// the full extent of the struct. Copy the fields one at a time.
+unsafe fn read_dirent(input: &libc_dirent) -> libc_dirent {
+ #[cfg(not(target_os = "illumos"))]
+ let d_type = input.d_type;
+
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "wasi",
+ )))]
+ let d_off = input.d_off;
+
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ let d_ino = input.d_ino;
+
+ #[cfg(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
+ let d_fileno = input.d_fileno;
+
+ #[cfg(not(target_os = "wasi"))]
+ let d_reclen = input.d_reclen;
+
+ #[cfg(any(
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "ios",
+ target_os = "macos",
+ ))]
+ let d_namlen = input.d_namlen;
+
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ let d_seekoff = input.d_seekoff;
+
+ // Construct the input. Rust will give us an error if any OS has a input
+ // with a field that we missed here. And we can avoid blindly copying the
+ // whole `d_name` field, which may not be entirely allocated.
+ #[cfg_attr(target_os = "wasi", allow(unused_mut))]
+ let mut dirent = libc_dirent {
+ #[cfg(not(target_os = "illumos"))]
+ d_type,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "wasi",
+ )))]
+ d_off,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ d_ino,
+ #[cfg(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
+ d_fileno,
+ #[cfg(not(target_os = "wasi"))]
+ d_reclen,
+ #[cfg(any(
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ d_namlen,
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ d_seekoff,
+ // The `d_name` field is NUL-terminated, and we need to be careful not
+ // to read bytes past the NUL, even though they're within the nominal
+ // extent of the `struct dirent`, because they may not be allocated. So
+ // don't read it from `dirent_ptr`.
+ //
+ // In theory this could use `MaybeUninit::uninit().assume_init()`, but
+ // that [invokes undefined behavior].
+ //
+ // [invokes undefined behavior]: https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#initialization-invariant
+ d_name: zeroed(),
+ #[cfg(target_os = "openbsd")]
+ __d_padding: zeroed(),
+ };
+
+ // Copy from d_name, reading up to and including the first NUL.
+ #[cfg(not(target_os = "wasi"))]
+ {
+ let name_len = CStr::from_ptr(input.d_name.as_ptr())
+ .to_bytes_with_nul()
+ .len();
+ dirent.d_name[..name_len].copy_from_slice(&input.d_name[..name_len]);
+ }
+
+ dirent
+}
+
+/// `Dir` implements `Send` but not `Sync`, because we use `readdir` which is
+/// not guaranteed to be thread-safe. Users can wrap this in a `Mutex` if they
+/// need `Sync`, which is effectively what'd need to do to implement `Sync`
+/// ourselves.
+unsafe impl Send for Dir {}
+
+impl Drop for Dir {
+ #[inline]
+ fn drop(&mut self) {
+ unsafe { c::closedir(self.0.as_ptr()) };
+ }
+}
+
+impl Iterator for Dir {
+ type Item = io::Result<DirEntry>;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ Self::read(self)
+ }
+}
+
+impl fmt::Debug for Dir {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Dir")
+ .field("fd", unsafe { &c::dirfd(self.0.as_ptr()) })
+ .finish()
+ }
+}
+
+/// `struct dirent`
+#[derive(Debug)]
+pub struct DirEntry {
+ dirent: libc_dirent,
+
+ #[cfg(target_os = "wasi")]
+ name: CString,
+}
+
+impl DirEntry {
+ /// Returns the file name of this directory entry.
+ #[inline]
+ pub fn file_name(&self) -> &CStr {
+ #[cfg(not(target_os = "wasi"))]
+ unsafe {
+ CStr::from_ptr(self.dirent.d_name.as_ptr())
+ }
+
+ #[cfg(target_os = "wasi")]
+ &self.name
+ }
+
+ /// Returns the type of this directory entry.
+ #[cfg(not(target_os = "illumos"))]
+ #[inline]
+ pub fn file_type(&self) -> FileType {
+ FileType::from_dirent_d_type(self.dirent.d_type)
+ }
+
+ /// Return the inode number of this directory entry.
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ #[inline]
+ pub fn ino(&self) -> u64 {
+ self.dirent.d_ino
+ }
+
+ /// Return the inode number of this directory entry.
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ #[inline]
+ pub fn ino(&self) -> u64 {
+ #[allow(clippy::useless_conversion)]
+ self.dirent.d_fileno.into()
+ }
+}
+
+/// libc's OpenBSD `dirent` has a private field so we can't construct it
+/// directly, so we declare it ourselves to make all fields accessible.
+#[cfg(target_os = "openbsd")]
+#[repr(C)]
+#[derive(Debug)]
+struct libc_dirent {
+ d_fileno: c::ino_t,
+ d_off: c::off_t,
+ d_reclen: u16,
+ d_type: u8,
+ d_namlen: u8,
+ __d_padding: [u8; 4],
+ d_name: [c::c_char; 256],
+}
+
+/// We have our own copy of OpenBSD's dirent; check that the layout
+/// minimally matches libc's.
+#[cfg(target_os = "openbsd")]
+fn check_dirent_layout(dirent: &c::dirent) {
+ use crate::utils::as_ptr;
+ use core::mem::{align_of, size_of};
+
+ // Check that the basic layouts match.
+ assert_eq!(size_of::<libc_dirent>(), size_of::<c::dirent>());
+ assert_eq!(align_of::<libc_dirent>(), align_of::<c::dirent>());
+
+ // Check that the field offsets match.
+ assert_eq!(
+ {
+ let z = libc_dirent {
+ d_fileno: 0_u64,
+ d_off: 0_i64,
+ d_reclen: 0_u16,
+ d_type: 0_u8,
+ d_namlen: 0_u8,
+ __d_padding: [0_u8; 4],
+ d_name: [0 as c::c_char; 256],
+ };
+ let base = as_ptr(&z) as usize;
+ (
+ (as_ptr(&z.d_fileno) as usize) - base,
+ (as_ptr(&z.d_off) as usize) - base,
+ (as_ptr(&z.d_reclen) as usize) - base,
+ (as_ptr(&z.d_type) as usize) - base,
+ (as_ptr(&z.d_namlen) as usize) - base,
+ (as_ptr(&z.d_name) as usize) - base,
+ )
+ },
+ {
+ let z = dirent;
+ let base = as_ptr(z) as usize;
+ (
+ (as_ptr(&z.d_fileno) as usize) - base,
+ (as_ptr(&z.d_off) as usize) - base,
+ (as_ptr(&z.d_reclen) as usize) - base,
+ (as_ptr(&z.d_type) as usize) - base,
+ (as_ptr(&z.d_namlen) as usize) - base,
+ (as_ptr(&z.d_name) as usize) - base,
+ )
+ }
+ );
+}
diff --git a/vendor/rustix/src/imp/libc/fs/makedev.rs b/vendor/rustix/src/imp/libc/fs/makedev.rs
new file mode 100644
index 000000000..d9089e7f4
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/fs/makedev.rs
@@ -0,0 +1,90 @@
+#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
+use super::super::c;
+use crate::fs::Dev;
+
+#[cfg(not(any(target_os = "android", target_os = "emscripten")))]
+#[inline]
+pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
+ unsafe { c::makedev(maj, min) }
+}
+
+#[cfg(all(target_os = "android", not(target_pointer_width = "32")))]
+#[inline]
+pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
+ // Android's `makedev` oddly has signed argument types.
+ unsafe { c::makedev(maj as i32, min as i32) }
+}
+
+#[cfg(all(target_os = "android", target_pointer_width = "32"))]
+#[inline]
+pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
+ // 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit,
+ // so we do it ourselves.
+ ((u64::from(maj) & 0xffff_f000_u64) << 32)
+ | ((u64::from(maj) & 0x0000_0fff_u64) << 8)
+ | ((u64::from(min) & 0xffff_ff00_u64) << 12)
+ | (u64::from(min) & 0x0000_00ff_u64)
+}
+
+#[cfg(target_os = "emscripten")]
+#[inline]
+pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
+ // Emscripten's `makedev` has a 32-bit return value.
+ Dev::from(unsafe { c::makedev(maj, min) })
+}
+
+#[cfg(not(any(target_os = "android", target_os = "emscripten")))]
+#[inline]
+pub(crate) fn major(dev: Dev) -> u32 {
+ unsafe { c::major(dev) }
+}
+
+#[cfg(all(target_os = "android", not(target_pointer_width = "32")))]
+#[inline]
+pub(crate) fn major(dev: Dev) -> u32 {
+ // Android's `major` oddly has signed return types.
+ (unsafe { c::major(dev) }) as u32
+}
+
+#[cfg(all(target_os = "android", target_pointer_width = "32"))]
+#[inline]
+pub(crate) fn major(dev: Dev) -> u32 {
+ // 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit,
+ // so we do it ourselves.
+ (((dev >> 31 >> 1) & 0xffff_f000) | ((dev >> 8) & 0x0000_0fff)) as u32
+}
+
+#[cfg(target_os = "emscripten")]
+#[inline]
+pub(crate) fn major(dev: Dev) -> u32 {
+ // Emscripten's `major` has a 32-bit argument value.
+ unsafe { c::major(dev as u32) }
+}
+
+#[cfg(not(any(target_os = "android", target_os = "emscripten")))]
+#[inline]
+pub(crate) fn minor(dev: Dev) -> u32 {
+ unsafe { c::minor(dev) }
+}
+
+#[cfg(all(target_os = "android", not(target_pointer_width = "32")))]
+#[inline]
+pub(crate) fn minor(dev: Dev) -> u32 {
+ // Android's `minor` oddly has signed return types.
+ (unsafe { c::minor(dev) }) as u32
+}
+
+#[cfg(all(target_os = "android", target_pointer_width = "32"))]
+#[inline]
+pub(crate) fn minor(dev: Dev) -> u32 {
+ // 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit,
+ // so we do it ourselves.
+ (((dev >> 12) & 0xffff_ff00) | (dev & 0x0000_00ff)) as u32
+}
+
+#[cfg(target_os = "emscripten")]
+#[inline]
+pub(crate) fn minor(dev: Dev) -> u32 {
+ // Emscripten's `minor` has a 32-bit argument value.
+ unsafe { c::minor(dev as u32) }
+}
diff --git a/vendor/rustix/src/imp/libc/fs/mod.rs b/vendor/rustix/src/imp/libc/fs/mod.rs
new file mode 100644
index 000000000..02b7b2d6a
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/fs/mod.rs
@@ -0,0 +1,18 @@
+#[cfg(not(target_os = "redox"))]
+#[cfg(any(feature = "fs", feature = "procfs"))]
+pub(crate) mod dir;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub(crate) mod makedev;
+#[cfg(not(windows))]
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/libc/fs/syscalls.rs b/vendor/rustix/src/imp/libc/fs/syscalls.rs
new file mode 100644
index 000000000..0317367ab
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/fs/syscalls.rs
@@ -0,0 +1,1670 @@
+//! libc syscalls supporting `rustix::fs`.
+
+use super::super::c;
+use super::super::conv::{
+ borrowed_fd, c_str, ret, ret_c_int, ret_off_t, ret_owned_fd, ret_ssize_t,
+};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use super::super::conv::{syscall_ret, syscall_ret_owned_fd, syscall_ret_ssize_t};
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+use super::super::offset::libc_fallocate;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+use super::super::offset::libc_posix_fadvise;
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+use super::super::offset::libc_posix_fallocate;
+use super::super::offset::{libc_fstat, libc_fstatat, libc_ftruncate, libc_lseek, libc_off_t};
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+use super::super::offset::{libc_fstatfs, libc_statfs};
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+use super::super::time::types::LibcTimespec;
+use crate::fd::BorrowedFd;
+#[cfg(not(target_os = "wasi"))]
+use crate::fd::RawFd;
+use crate::ffi::CStr;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+use crate::ffi::CString;
+#[cfg(not(target_os = "illumos"))]
+use crate::fs::Access;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+use crate::fs::Advice;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+use crate::fs::FallocateFlags;
+#[cfg(not(target_os = "wasi"))]
+use crate::fs::FlockOperation;
+#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+use crate::fs::MemfdFlags;
+#[cfg(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+use crate::fs::SealFlags;
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+// not implemented in libc for netbsd yet
+use crate::fs::StatFs;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::fs::{cwd, RenameFlags, ResolveFlags, Statx, StatxFlags};
+#[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+use crate::fs::{Dev, FileType};
+use crate::fs::{FdFlags, Mode, OFlags, Stat, Timestamps};
+use crate::io::{self, OwnedFd, SeekFrom};
+#[cfg(not(target_os = "wasi"))]
+use crate::process::{Gid, Uid};
+#[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+)))]
+use crate::utils::as_ptr;
+use core::convert::TryInto;
+#[cfg(any(
+ target_os = "android",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+))]
+use core::mem::size_of;
+use core::mem::MaybeUninit;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use core::ptr::null;
+#[cfg(any(
+ target_os = "android",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+))]
+use core::ptr::null_mut;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+use {
+ super::super::conv::nonnegative_ret,
+ crate::fs::{copyfile_state_t, CloneFlags, CopyfileFlags},
+};
+#[cfg(not(target_os = "redox"))]
+use {super::super::offset::libc_openat, crate::fs::AtFlags};
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+weak!(fn __utimensat64(c::c_int, *const c::c_char, *const LibcTimespec, c::c_int) -> c::c_int);
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+weak!(fn __futimens64(c::c_int, *const LibcTimespec) -> c::c_int);
+
+/// Use a direct syscall (via libc) for `openat`.
+///
+/// This is only currently necessary as a workaround for old glibc; see below.
+#[cfg(all(unix, target_env = "gnu"))]
+fn openat_via_syscall(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ oflags: OFlags,
+ mode: Mode,
+) -> io::Result<OwnedFd> {
+ unsafe {
+ let dirfd = borrowed_fd(dirfd);
+ let path = c_str(path);
+ let oflags = oflags.bits();
+ let mode = c::c_uint::from(mode.bits());
+ ret_owned_fd(c::syscall(
+ c::SYS_openat,
+ c::c_long::from(dirfd),
+ path,
+ c::c_long::from(oflags),
+ mode as c::c_long,
+ ) as c::c_int)
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn openat(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ oflags: OFlags,
+ mode: Mode,
+) -> io::Result<OwnedFd> {
+ // Work around <https://sourceware.org/bugzilla/show_bug.cgi?id=17523>.
+ // Basically old glibc versions don't handle O_TMPFILE correctly.
+ #[cfg(all(unix, target_env = "gnu"))]
+ if oflags.contains(OFlags::TMPFILE) && crate::imp::if_glibc_is_less_than_2_25() {
+ return openat_via_syscall(dirfd, path, oflags, mode);
+ }
+ unsafe {
+ // Pass `mode` as a `c_uint` even if `mode_t` is narrower, since
+ // `libc_openat` is declared as a variadic function and narrower
+ // arguments are promoted.
+ ret_owned_fd(libc_openat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ oflags.bits(),
+ c::c_uint::from(mode.bits()),
+ ))
+ }
+}
+
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[inline]
+pub(crate) fn statfs(filename: &CStr) -> io::Result<StatFs> {
+ unsafe {
+ let mut result = MaybeUninit::<StatFs>::uninit();
+ ret(libc_statfs(c_str(filename), result.as_mut_ptr()))?;
+ Ok(result.assume_init())
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+#[inline]
+pub(crate) fn readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, buf: &mut [u8]) -> io::Result<usize> {
+ unsafe {
+ ret_ssize_t(c::readlinkat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ buf.as_mut_ptr().cast::<c::c_char>(),
+ buf.len(),
+ ))
+ .map(|nread| nread as usize)
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn mkdirat(dirfd: BorrowedFd<'_>, path: &CStr, mode: Mode) -> io::Result<()> {
+ unsafe {
+ ret(c::mkdirat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ mode.bits() as c::mode_t,
+ ))
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn linkat(
+ old_dirfd: BorrowedFd<'_>,
+ old_path: &CStr,
+ new_dirfd: BorrowedFd<'_>,
+ new_path: &CStr,
+ flags: AtFlags,
+) -> io::Result<()> {
+ unsafe {
+ ret(c::linkat(
+ borrowed_fd(old_dirfd),
+ c_str(old_path),
+ borrowed_fd(new_dirfd),
+ c_str(new_path),
+ flags.bits(),
+ ))
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn unlinkat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result<()> {
+ unsafe { ret(c::unlinkat(borrowed_fd(dirfd), c_str(path), flags.bits())) }
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn renameat(
+ old_dirfd: BorrowedFd<'_>,
+ old_path: &CStr,
+ new_dirfd: BorrowedFd<'_>,
+ new_path: &CStr,
+) -> io::Result<()> {
+ unsafe {
+ ret(c::renameat(
+ borrowed_fd(old_dirfd),
+ c_str(old_path),
+ borrowed_fd(new_dirfd),
+ c_str(new_path),
+ ))
+ }
+}
+
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+pub(crate) fn renameat2(
+ old_dirfd: BorrowedFd<'_>,
+ old_path: &CStr,
+ new_dirfd: BorrowedFd<'_>,
+ new_path: &CStr,
+ flags: RenameFlags,
+) -> io::Result<()> {
+ // `getrandom` wasn't supported in glibc until 2.28.
+ weak_or_syscall! {
+ fn renameat2(
+ olddirfd: c::c_int,
+ oldpath: *const c::c_char,
+ newdirfd: c::c_int,
+ newpath: *const c::c_char,
+ flags: c::c_uint
+ ) via SYS_renameat2 -> c::c_int
+ }
+
+ unsafe {
+ ret(renameat2(
+ borrowed_fd(old_dirfd),
+ c_str(old_path),
+ borrowed_fd(new_dirfd),
+ c_str(new_path),
+ flags.bits(),
+ ))
+ }
+}
+
+/// At present, `libc` only has `renameat2` defined for glibc. On other
+/// ABIs, `RenameFlags` has no flags defined, and we use plain `renameat`.
+#[cfg(any(
+ target_os = "android",
+ all(target_os = "linux", not(target_env = "gnu")),
+))]
+#[inline]
+pub(crate) fn renameat2(
+ old_dirfd: BorrowedFd<'_>,
+ old_path: &CStr,
+ new_dirfd: BorrowedFd<'_>,
+ new_path: &CStr,
+ flags: RenameFlags,
+) -> io::Result<()> {
+ assert!(flags.is_empty());
+ renameat(old_dirfd, old_path, new_dirfd, new_path)
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn symlinkat(
+ old_path: &CStr,
+ new_dirfd: BorrowedFd<'_>,
+ new_path: &CStr,
+) -> io::Result<()> {
+ unsafe {
+ ret(c::symlinkat(
+ c_str(old_path),
+ borrowed_fd(new_dirfd),
+ c_str(new_path),
+ ))
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn statat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result<Stat> {
+ // 32-bit and mips64 Linux: `struct stat64` is not y2038 compatible; use
+ // `statx`.
+ #[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_pointer_width = "32", target_arch = "mips64"),
+ ))]
+ {
+ match statx(dirfd, path, flags, StatxFlags::BASIC_STATS) {
+ Ok(x) => return statx_to_stat(x),
+ Err(io::Errno::NOSYS) => statat_old(dirfd, path, flags),
+ Err(e) => return Err(e),
+ }
+ }
+
+ // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and
+ // there's nothing practical we can do.
+ #[cfg(not(all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_pointer_width = "32", target_arch = "mips64"),
+ )))]
+ unsafe {
+ let mut stat = MaybeUninit::<Stat>::uninit();
+ ret(libc_fstatat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ stat.as_mut_ptr(),
+ flags.bits(),
+ ))?;
+ Ok(stat.assume_init())
+ }
+}
+
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_pointer_width = "32", target_arch = "mips64"),
+))]
+fn statat_old(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result<Stat> {
+ unsafe {
+ let mut result = MaybeUninit::<c::stat64>::uninit();
+ ret(libc_fstatat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ result.as_mut_ptr(),
+ flags.bits(),
+ ))?;
+ stat64_to_stat(result.assume_init())
+ }
+}
+
+#[cfg(not(any(target_os = "emscripten", target_os = "illumos", target_os = "redox")))]
+pub(crate) fn accessat(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ access: Access,
+ flags: AtFlags,
+) -> io::Result<()> {
+ unsafe {
+ ret(c::faccessat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ access.bits(),
+ flags.bits(),
+ ))
+ }
+}
+
+#[cfg(target_os = "emscripten")]
+pub(crate) fn accessat(
+ _dirfd: BorrowedFd<'_>,
+ _path: &CStr,
+ _access: Access,
+ _flags: AtFlags,
+) -> io::Result<()> {
+ Ok(())
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn utimensat(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ times: &Timestamps,
+ flags: AtFlags,
+) -> io::Result<()> {
+ // 32-bit gnu version: libc has `utimensat` but it is not y2038 safe by
+ // default.
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ unsafe {
+ if let Some(libc_utimensat) = __utimensat64.get() {
+ let libc_times: [LibcTimespec; 2] = [
+ times.last_access.clone().into(),
+ times.last_modification.clone().into(),
+ ];
+
+ ret(libc_utimensat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ libc_times.as_ptr(),
+ flags.bits(),
+ ))
+ } else {
+ utimensat_old(dirfd, path, times, flags)
+ }
+ }
+
+ // Main version: libc is y2038 safe and has `utimensat`. Or, the platform
+ // is not y2038 safe and there's nothing practical we can do.
+ #[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )
+ )))]
+ unsafe {
+ // Assert that `Timestamps` has the expected layout.
+ let _ = core::mem::transmute::<Timestamps, [c::timespec; 2]>(times.clone());
+
+ ret(c::utimensat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ as_ptr(times).cast(),
+ flags.bits(),
+ ))
+ }
+
+ // `utimensat` was introduced in macOS 10.13.
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ unsafe {
+ // ABI details
+ weak! {
+ fn utimensat(
+ c::c_int,
+ *const c::c_char,
+ *const c::timespec,
+ c::c_int
+ ) -> c::c_int
+ }
+ extern "C" {
+ fn setattrlist(
+ path: *const c::c_char,
+ attr_list: *const Attrlist,
+ attr_buf: *const c::c_void,
+ attr_buf_size: c::size_t,
+ options: c::c_ulong,
+ ) -> c::c_int;
+ }
+ const FSOPT_NOFOLLOW: c::c_ulong = 0x0000_0001;
+
+ // If we have `utimensat`, use it.
+ if let Some(have_utimensat) = utimensat.get() {
+ // Assert that `Timestamps` has the expected layout.
+ let _ = core::mem::transmute::<Timestamps, [c::timespec; 2]>(times.clone());
+
+ return ret(have_utimensat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ as_ptr(times).cast(),
+ flags.bits(),
+ ));
+ }
+
+ // `setattrlistat` was introduced in 10.13 along with `utimensat`, so if
+ // we don't have `utimensat`, we don't have `setattrlistat` either.
+ // Emulate it using `fork`, and `fchdir` and [`setattrlist`].
+ //
+ // [`setattrlist`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setattrlist.2.html
+ match c::fork() {
+ -1 => Err(io::Errno::IO),
+ 0 => {
+ if c::fchdir(borrowed_fd(dirfd)) != 0 {
+ let code = match libc_errno::errno().0 {
+ c::EACCES => 2,
+ c::ENOTDIR => 3,
+ _ => 1,
+ };
+ c::_exit(code);
+ }
+
+ let mut flags_arg = 0;
+ if flags.contains(AtFlags::SYMLINK_NOFOLLOW) {
+ flags_arg |= FSOPT_NOFOLLOW;
+ }
+
+ let (attrbuf_size, times, attrs) = times_to_attrlist(times);
+
+ if setattrlist(
+ c_str(path),
+ &attrs,
+ as_ptr(&times).cast(),
+ attrbuf_size,
+ flags_arg,
+ ) != 0
+ {
+ // Translate expected errno codes into ad-hoc integer
+ // values suitable for exit statuses.
+ let code = match libc_errno::errno().0 {
+ c::EACCES => 2,
+ c::ENOTDIR => 3,
+ c::EPERM => 4,
+ c::EROFS => 5,
+ c::ELOOP => 6,
+ c::ENOENT => 7,
+ c::ENAMETOOLONG => 8,
+ c::EINVAL => 9,
+ c::ESRCH => 10,
+ c::ENOTSUP => 11,
+ _ => 1,
+ };
+ c::_exit(code);
+ }
+
+ c::_exit(0);
+ }
+ child_pid => {
+ let mut wstatus = 0;
+ let _ = ret_c_int(c::waitpid(child_pid, &mut wstatus, 0))?;
+ if c::WIFEXITED(wstatus) {
+ // Translate our ad-hoc exit statuses back to errno codes.
+ match c::WEXITSTATUS(wstatus) {
+ 0 => Ok(()),
+ 2 => Err(io::Errno::ACCESS),
+ 3 => Err(io::Errno::NOTDIR),
+ 4 => Err(io::Errno::PERM),
+ 5 => Err(io::Errno::ROFS),
+ 6 => Err(io::Errno::LOOP),
+ 7 => Err(io::Errno::NOENT),
+ 8 => Err(io::Errno::NAMETOOLONG),
+ 9 => Err(io::Errno::INVAL),
+ 10 => Err(io::Errno::SRCH),
+ 11 => Err(io::Errno::NOTSUP),
+ _ => Err(io::Errno::IO),
+ }
+ } else {
+ Err(io::Errno::IO)
+ }
+ }
+ }
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+unsafe fn utimensat_old(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ times: &Timestamps,
+ flags: AtFlags,
+) -> io::Result<()> {
+ let old_times = [
+ c::timespec {
+ tv_sec: times
+ .last_access
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: times.last_access.tv_nsec,
+ },
+ c::timespec {
+ tv_sec: times
+ .last_modification
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: times.last_modification.tv_nsec,
+ },
+ ];
+ ret(c::utimensat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ old_times.as_ptr(),
+ flags.bits(),
+ ))
+}
+
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub(crate) fn chmodat(dirfd: BorrowedFd<'_>, path: &CStr, mode: Mode) -> io::Result<()> {
+ unsafe { ret(c::fchmodat(borrowed_fd(dirfd), c_str(path), mode.bits(), 0)) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn chmodat(dirfd: BorrowedFd<'_>, path: &CStr, mode: Mode) -> io::Result<()> {
+ // Linux's `fchmodat` does not have a flags argument.
+ unsafe {
+ // Pass `mode` as a `c_uint` even if `mode_t` is narrower, since
+ // `libc_openat` is declared as a variadic function and narrower
+ // arguments are promoted.
+ syscall_ret(c::syscall(
+ c::SYS_fchmodat,
+ borrowed_fd(dirfd),
+ c_str(path),
+ c::c_uint::from(mode.bits()),
+ ))
+ }
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) fn fclonefileat(
+ srcfd: BorrowedFd<'_>,
+ dst_dirfd: BorrowedFd<'_>,
+ dst: &CStr,
+ flags: CloneFlags,
+) -> io::Result<()> {
+ syscall! {
+ fn fclonefileat(
+ srcfd: BorrowedFd<'_>,
+ dst_dirfd: BorrowedFd<'_>,
+ dst: *const c::c_char,
+ flags: c::c_int
+ ) via SYS_fclonefileat -> c::c_int
+ }
+
+ unsafe { ret(fclonefileat(srcfd, dst_dirfd, c_str(dst), flags.bits())) }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn chownat(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ owner: Option<Uid>,
+ group: Option<Gid>,
+ flags: AtFlags,
+) -> io::Result<()> {
+ unsafe {
+ let (ow, gr) = crate::process::translate_fchown_args(owner, group);
+ ret(c::fchownat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ ow,
+ gr,
+ flags.bits(),
+ ))
+ }
+}
+
+#[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub(crate) fn mknodat(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ file_type: FileType,
+ mode: Mode,
+ dev: Dev,
+) -> io::Result<()> {
+ unsafe {
+ ret(c::mknodat(
+ borrowed_fd(dirfd),
+ c_str(path),
+ (mode.bits() | file_type.as_raw_mode()) as c::mode_t,
+ dev.try_into().map_err(|_e| io::Errno::PERM)?,
+ ))
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn copy_file_range(
+ fd_in: BorrowedFd<'_>,
+ off_in: Option<&mut u64>,
+ fd_out: BorrowedFd<'_>,
+ off_out: Option<&mut u64>,
+ len: u64,
+) -> io::Result<u64> {
+ assert_eq!(size_of::<c::loff_t>(), size_of::<u64>());
+
+ let mut off_in_val: c::loff_t = 0;
+ let mut off_out_val: c::loff_t = 0;
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ let off_in_ptr = if let Some(off_in) = &off_in {
+ off_in_val = (**off_in) as i64;
+ &mut off_in_val
+ } else {
+ null_mut()
+ };
+ let off_out_ptr = if let Some(off_out) = &off_out {
+ off_out_val = (**off_out) as i64;
+ &mut off_out_val
+ } else {
+ null_mut()
+ };
+ let len: usize = len.try_into().unwrap_or(usize::MAX);
+ let copied = unsafe {
+ syscall_ret_ssize_t(c::syscall(
+ c::SYS_copy_file_range,
+ borrowed_fd(fd_in),
+ off_in_ptr,
+ borrowed_fd(fd_out),
+ off_out_ptr,
+ len,
+ 0, // no flags are defined yet
+ ))?
+ };
+ if let Some(off_in) = off_in {
+ *off_in = off_in_val as u64;
+ }
+ if let Some(off_out) = off_out {
+ *off_out = off_out_val as u64;
+ }
+ Ok(copied as u64)
+}
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub(crate) fn fadvise(fd: BorrowedFd<'_>, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
+ let offset = offset as i64;
+ let len = len as i64;
+
+ // FreeBSD returns `EINVAL` on invalid offsets; emulate the POSIX behavior.
+ #[cfg(target_os = "freebsd")]
+ let offset = if (offset as i64) < 0 {
+ i64::MAX
+ } else {
+ offset
+ };
+
+ // FreeBSD returns `EINVAL` on overflow; emulate the POSIX behavior.
+ #[cfg(target_os = "freebsd")]
+ let len = if len > 0 && offset.checked_add(len).is_none() {
+ i64::MAX - offset
+ } else {
+ len
+ };
+
+ let err = unsafe { libc_posix_fadvise(borrowed_fd(fd), offset, len, advice as c::c_int) };
+
+ // `posix_fadvise` returns its error status rather than using `errno`.
+ if err == 0 {
+ Ok(())
+ } else {
+ Err(io::Errno(err))
+ }
+}
+
+pub(crate) fn fcntl_getfd(fd: BorrowedFd<'_>) -> io::Result<FdFlags> {
+ unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFD)).map(FdFlags::from_bits_truncate) }
+}
+
+pub(crate) fn fcntl_setfd(fd: BorrowedFd<'_>, flags: FdFlags) -> io::Result<()> {
+ unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETFD, flags.bits())) }
+}
+
+pub(crate) fn fcntl_getfl(fd: BorrowedFd<'_>) -> io::Result<OFlags> {
+ unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFL)).map(OFlags::from_bits_truncate) }
+}
+
+pub(crate) fn fcntl_setfl(fd: BorrowedFd<'_>, flags: OFlags) -> io::Result<()> {
+ unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETFL, flags.bits())) }
+}
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+pub(crate) fn fcntl_get_seals(fd: BorrowedFd<'_>) -> io::Result<SealFlags> {
+ unsafe {
+ ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GET_SEALS))
+ .map(|flags| SealFlags::from_bits_unchecked(flags))
+ }
+}
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+pub(crate) fn fcntl_add_seals(fd: BorrowedFd<'_>, seals: SealFlags) -> io::Result<()> {
+ unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_ADD_SEALS, seals.bits())) }
+}
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) fn fcntl_dupfd_cloexec(fd: BorrowedFd<'_>, min: RawFd) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(c::fcntl(borrowed_fd(fd), c::F_DUPFD_CLOEXEC, min)) }
+}
+
+pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result<u64> {
+ let (whence, offset): (c::c_int, libc_off_t) = match pos {
+ SeekFrom::Start(pos) => {
+ let pos: u64 = pos;
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ (c::SEEK_SET, pos as i64)
+ }
+ SeekFrom::End(offset) => (c::SEEK_END, offset),
+ SeekFrom::Current(offset) => (c::SEEK_CUR, offset),
+ };
+ let offset = unsafe { ret_off_t(libc_lseek(borrowed_fd(fd), offset, whence))? };
+ Ok(offset as u64)
+}
+
+pub(crate) fn tell(fd: BorrowedFd<'_>) -> io::Result<u64> {
+ let offset = unsafe { ret_off_t(libc_lseek(borrowed_fd(fd), 0, c::SEEK_CUR))? };
+ Ok(offset as u64)
+}
+
+#[cfg(not(any(target_os = "android", target_os = "linux", target_os = "wasi")))]
+pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> {
+ unsafe { ret(c::fchmod(borrowed_fd(fd), mode.bits())) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> {
+ // Use `c::syscall` rather than `c::fchmod` because some libc
+ // implementations, such as musl, add extra logic to `fchmod` to emulate
+ // support for `O_PATH`, which uses `/proc` outside our control and
+ // interferes with our own use of `O_PATH`.
+ unsafe {
+ syscall_ret(c::syscall(
+ c::SYS_fchmod,
+ borrowed_fd(fd),
+ c::c_uint::from(mode.bits()),
+ ))
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
+ // Use `c::syscall` rather than `c::fchown` because some libc
+ // implementations, such as musl, add extra logic to `fchown` to emulate
+ // support for `O_PATH`, which uses `/proc` outside our control and
+ // interferes with our own use of `O_PATH`.
+ unsafe {
+ let (ow, gr) = crate::process::translate_fchown_args(owner, group);
+ syscall_ret(c::syscall(c::SYS_fchown, borrowed_fd(fd), ow, gr))
+ }
+}
+
+#[cfg(not(any(target_os = "android", target_os = "linux", target_os = "wasi")))]
+pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
+ unsafe {
+ let (ow, gr) = crate::process::translate_fchown_args(owner, group);
+ ret(c::fchown(borrowed_fd(fd), ow, gr))
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) fn flock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::Result<()> {
+ unsafe { ret(c::flock(borrowed_fd(fd), operation as c::c_int)) }
+}
+
+pub(crate) fn fstat(fd: BorrowedFd<'_>) -> io::Result<Stat> {
+ // 32-bit and mips64 Linux: `struct stat64` is not y2038 compatible; use
+ // `statx`.
+ #[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_pointer_width = "32", target_arch = "mips64"),
+ ))]
+ {
+ match statx(fd, cstr!(""), AtFlags::EMPTY_PATH, StatxFlags::BASIC_STATS) {
+ Ok(x) => return statx_to_stat(x),
+ Err(io::Errno::NOSYS) => fstat_old(fd),
+ Err(e) => return Err(e),
+ }
+ }
+
+ // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and
+ // there's nothing practical we can do.
+ #[cfg(not(all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_pointer_width = "32", target_arch = "mips64"),
+ )))]
+ unsafe {
+ let mut stat = MaybeUninit::<Stat>::uninit();
+ ret(libc_fstat(borrowed_fd(fd), stat.as_mut_ptr()))?;
+ Ok(stat.assume_init())
+ }
+}
+
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_pointer_width = "32", target_arch = "mips64"),
+))]
+fn fstat_old(fd: BorrowedFd<'_>) -> io::Result<Stat> {
+ unsafe {
+ let mut result = MaybeUninit::<c::stat64>::uninit();
+ ret(libc_fstat(borrowed_fd(fd), result.as_mut_ptr()))?;
+ stat64_to_stat(result.assume_init())
+ }
+}
+
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))] // not implemented in libc for netbsd yet
+pub(crate) fn fstatfs(fd: BorrowedFd<'_>) -> io::Result<StatFs> {
+ let mut statfs = MaybeUninit::<StatFs>::uninit();
+ unsafe {
+ ret(libc_fstatfs(borrowed_fd(fd), statfs.as_mut_ptr()))?;
+ Ok(statfs.assume_init())
+ }
+}
+
+pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> {
+ // 32-bit gnu version: libc has `futimens` but it is not y2038 safe by default.
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ unsafe {
+ if let Some(libc_futimens) = __futimens64.get() {
+ let libc_times: [LibcTimespec; 2] = [
+ times.last_access.clone().into(),
+ times.last_modification.clone().into(),
+ ];
+
+ ret(libc_futimens(borrowed_fd(fd), libc_times.as_ptr()))
+ } else {
+ futimens_old(fd, times)
+ }
+ }
+
+ // Main version: libc is y2038 safe and has `futimens`. Or, the platform
+ // is not y2038 safe and there's nothing practical we can do.
+ #[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )
+ )))]
+ unsafe {
+ // Assert that `Timestamps` has the expected layout.
+ let _ = core::mem::transmute::<Timestamps, [c::timespec; 2]>(times.clone());
+
+ ret(c::futimens(borrowed_fd(fd), as_ptr(times).cast()))
+ }
+
+ // `futimens` was introduced in macOS 10.13.
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ unsafe {
+ // ABI details.
+ weak! {
+ fn futimens(c::c_int, *const c::timespec) -> c::c_int
+ }
+ extern "C" {
+ fn fsetattrlist(
+ fd: c::c_int,
+ attr_list: *const Attrlist,
+ attr_buf: *const c::c_void,
+ attr_buf_size: c::size_t,
+ options: c::c_ulong,
+ ) -> c::c_int;
+ }
+
+ // If we have `futimens`, use it.
+ if let Some(have_futimens) = futimens.get() {
+ // Assert that `Timestamps` has the expected layout.
+ let _ = core::mem::transmute::<Timestamps, [c::timespec; 2]>(times.clone());
+
+ return ret(have_futimens(borrowed_fd(fd), as_ptr(times).cast()));
+ }
+
+ // Otherwise use `fsetattrlist`.
+ let (attrbuf_size, times, attrs) = times_to_attrlist(times);
+
+ ret(fsetattrlist(
+ borrowed_fd(fd),
+ &attrs,
+ as_ptr(&times).cast(),
+ attrbuf_size,
+ 0,
+ ))
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+unsafe fn futimens_old(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> {
+ let old_times = [
+ c::timespec {
+ tv_sec: times
+ .last_access
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: times.last_access.tv_nsec,
+ },
+ c::timespec {
+ tv_sec: times
+ .last_modification
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: times.last_modification.tv_nsec,
+ },
+ ];
+
+ ret(c::futimens(borrowed_fd(fd), old_times.as_ptr()))
+}
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub(crate) fn fallocate(
+ fd: BorrowedFd<'_>,
+ mode: FallocateFlags,
+ offset: u64,
+ len: u64,
+) -> io::Result<()> {
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ let offset = offset as i64;
+ let len = len as i64;
+
+ #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ unsafe {
+ ret(libc_fallocate(borrowed_fd(fd), mode.bits(), offset, len))
+ }
+
+ #[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
+ {
+ assert!(mode.is_empty());
+ let err = unsafe { libc_posix_fallocate(borrowed_fd(fd), offset, len) };
+
+ // `posix_fallocate` returns its error status rather than using `errno`.
+ if err == 0 {
+ Ok(())
+ } else {
+ Err(io::Errno(err))
+ }
+ }
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) fn fallocate(
+ fd: BorrowedFd<'_>,
+ mode: FallocateFlags,
+ offset: u64,
+ len: u64,
+) -> io::Result<()> {
+ let offset: i64 = offset.try_into().map_err(|_e| io::Errno::INVAL)?;
+ let len = len as i64;
+
+ assert!(mode.is_empty());
+
+ let new_len = offset.checked_add(len).ok_or_else(|| io::Errno::FBIG)?;
+ let mut store = c::fstore_t {
+ fst_flags: c::F_ALLOCATECONTIG,
+ fst_posmode: c::F_PEOFPOSMODE,
+ fst_offset: 0,
+ fst_length: new_len,
+ fst_bytesalloc: 0,
+ };
+ unsafe {
+ if c::fcntl(borrowed_fd(fd), c::F_PREALLOCATE, &store) == -1 {
+ store.fst_flags = c::F_ALLOCATEALL;
+ let _ = ret_c_int(c::fcntl(borrowed_fd(fd), c::F_PREALLOCATE, &store))?;
+ }
+ ret(c::ftruncate(borrowed_fd(fd), new_len))
+ }
+}
+
+pub(crate) fn fsync(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(c::fsync(borrowed_fd(fd))) }
+}
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub(crate) fn fdatasync(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(c::fdatasync(borrowed_fd(fd))) }
+}
+
+pub(crate) fn ftruncate(fd: BorrowedFd<'_>, length: u64) -> io::Result<()> {
+ let length = length.try_into().map_err(|_overflow_err| io::Errno::FBIG)?;
+ unsafe { ret(libc_ftruncate(borrowed_fd(fd), length)) }
+}
+
+#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+pub(crate) fn memfd_create(path: &CStr, flags: MemfdFlags) -> io::Result<OwnedFd> {
+ #[cfg(target_os = "freebsd")]
+ weakcall! {
+ fn memfd_create(
+ name: *const c::c_char,
+ flags: c::c_uint
+ ) -> c::c_int
+ }
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ weak_or_syscall! {
+ fn memfd_create(
+ name: *const c::c_char,
+ flags: c::c_uint
+ ) via SYS_memfd_create -> c::c_int
+ }
+
+ unsafe { ret_owned_fd(memfd_create(c_str(path), flags.bits())) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn openat2(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ oflags: OFlags,
+ mode: Mode,
+ resolve: ResolveFlags,
+) -> io::Result<OwnedFd> {
+ let oflags: i32 = oflags.bits();
+ let open_how = OpenHow {
+ oflag: u64::from(oflags as u32),
+ mode: u64::from(mode.bits()),
+ resolve: resolve.bits(),
+ };
+
+ unsafe {
+ syscall_ret_owned_fd(c::syscall(
+ SYS_OPENAT2,
+ borrowed_fd(dirfd),
+ c_str(path),
+ &open_how,
+ SIZEOF_OPEN_HOW,
+ ))
+ }
+}
+#[cfg(all(
+ target_pointer_width = "32",
+ any(target_os = "android", target_os = "linux"),
+))]
+const SYS_OPENAT2: i32 = 437;
+#[cfg(all(
+ target_pointer_width = "64",
+ any(target_os = "android", target_os = "linux"),
+))]
+const SYS_OPENAT2: i64 = 437;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[repr(C)]
+#[derive(Debug)]
+struct OpenHow {
+ oflag: u64,
+ mode: u64,
+ resolve: u64,
+}
+#[cfg(any(target_os = "android", target_os = "linux"))]
+const SIZEOF_OPEN_HOW: usize = size_of::<OpenHow>();
+
+#[cfg(target_os = "linux")]
+pub(crate) fn sendfile(
+ out_fd: BorrowedFd<'_>,
+ in_fd: BorrowedFd<'_>,
+ offset: Option<&mut u64>,
+ count: usize,
+) -> io::Result<usize> {
+ unsafe {
+ let nsent = ret_ssize_t(c::sendfile64(
+ borrowed_fd(out_fd),
+ borrowed_fd(in_fd),
+ offset.map_or(null_mut(), crate::utils::as_mut_ptr).cast(),
+ count,
+ ))?;
+ Ok(nsent as usize)
+ }
+}
+
+/// Convert from a Linux `statx` value to rustix's `Stat`.
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ target_pointer_width = "32",
+))]
+fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
+ Ok(Stat {
+ st_dev: crate::fs::makedev(x.stx_dev_major, x.stx_dev_minor).into(),
+ st_mode: x.stx_mode.into(),
+ st_nlink: x.stx_nlink.into(),
+ st_uid: x.stx_uid.into(),
+ st_gid: x.stx_gid.into(),
+ st_rdev: crate::fs::makedev(x.stx_rdev_major, x.stx_rdev_minor).into(),
+ st_size: x.stx_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_blksize: x.stx_blksize.into(),
+ st_blocks: x.stx_blocks.into(),
+ st_atime: x
+ .stx_atime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_atime_nsec: x.stx_atime.tv_nsec as _,
+ st_mtime: x
+ .stx_mtime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_mtime_nsec: x.stx_mtime.tv_nsec as _,
+ st_ctime: x
+ .stx_ctime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_ctime_nsec: x.stx_ctime.tv_nsec as _,
+ st_ino: x.stx_ino.into(),
+ })
+}
+
+/// Convert from a Linux `statx` value to rustix's `Stat`.
+///
+/// mips64' `struct stat64` in libc has private fields, and `stx_blocks`
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ target_arch = "mips64",
+))]
+fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
+ let mut result: Stat = unsafe { core::mem::zeroed() };
+
+ result.st_dev = crate::fs::makedev(x.stx_dev_major, x.stx_dev_minor);
+ result.st_mode = x.stx_mode.into();
+ result.st_nlink = x.stx_nlink.into();
+ result.st_uid = x.stx_uid.into();
+ result.st_gid = x.stx_gid.into();
+ result.st_rdev = crate::fs::makedev(x.stx_rdev_major, x.stx_rdev_minor);
+ result.st_size = x.stx_size.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_blksize = x.stx_blksize.into();
+ result.st_blocks = x.stx_blocks.try_into().map_err(|_e| io::Errno::OVERFLOW)?;
+ result.st_atime = x
+ .stx_atime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_atime_nsec = x.stx_atime.tv_nsec as _;
+ result.st_mtime = x
+ .stx_mtime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_mtime_nsec = x.stx_mtime.tv_nsec as _;
+ result.st_ctime = x
+ .stx_ctime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_ctime_nsec = x.stx_ctime.tv_nsec as _;
+ result.st_ino = x.stx_ino.into();
+
+ Ok(result)
+}
+
+/// Convert from a Linux `stat64` value to rustix's `Stat`.
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ target_pointer_width = "32",
+))]
+fn stat64_to_stat(s64: c::stat64) -> io::Result<Stat> {
+ Ok(Stat {
+ st_dev: s64.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_mode: s64.st_mode.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_nlink: s64.st_nlink.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_uid: s64.st_uid.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_gid: s64.st_gid.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_rdev: s64.st_rdev.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_size: s64.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_blksize: s64.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_blocks: s64.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_atime: s64.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_atime_nsec: s64
+ .st_atime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_mtime: s64.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_mtime_nsec: s64
+ .st_mtime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_ctime: s64.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_ctime_nsec: s64
+ .st_ctime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_ino: s64.st_ino.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ })
+}
+
+/// Convert from a Linux `stat64` value to rustix's `Stat`.
+///
+/// mips64' `struct stat64` in libc has private fields, and `st_blocks` has
+/// type `i64`.
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ target_arch = "mips64",
+))]
+fn stat64_to_stat(s64: c::stat64) -> io::Result<Stat> {
+ let mut result: Stat = unsafe { core::mem::zeroed() };
+
+ result.st_dev = s64.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_mode = s64.st_mode.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_nlink = s64.st_nlink.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_uid = s64.st_uid.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_gid = s64.st_gid.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_rdev = s64.st_rdev.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_size = s64.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_blksize = s64.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_blocks = s64.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_atime = s64.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_atime_nsec = s64
+ .st_atime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_mtime = s64.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_mtime_nsec = s64
+ .st_mtime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_ctime = s64.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_ctime_nsec = s64
+ .st_ctime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?;
+ result.st_ino = s64.st_ino.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+
+ Ok(result)
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(non_upper_case_globals)]
+mod sys {
+ use super::{c, BorrowedFd, Statx};
+
+ #[cfg(all(target_os = "android", target_arch = "arm"))]
+ const SYS_statx: c::c_long = 397;
+ #[cfg(all(target_os = "android", target_arch = "x86"))]
+ const SYS_statx: c::c_long = 383;
+ #[cfg(all(target_os = "android", target_arch = "aarch64"))]
+ const SYS_statx: c::c_long = 291;
+ #[cfg(all(target_os = "android", target_arch = "x86_64"))]
+ const SYS_statx: c::c_long = 332;
+
+ weak_or_syscall! {
+ pub(super) fn statx(
+ pirfd: BorrowedFd<'_>,
+ path: *const c::c_char,
+ flags: c::c_int,
+ mask: c::c_uint,
+ buf: *mut Statx
+ ) via SYS_statx -> c::c_int
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(non_upper_case_globals)]
+pub(crate) fn statx(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ flags: AtFlags,
+ mask: StatxFlags,
+) -> io::Result<Statx> {
+ let mut statx_buf = MaybeUninit::<Statx>::uninit();
+ unsafe {
+ ret(sys::statx(
+ dirfd,
+ c_str(path),
+ flags.bits(),
+ mask.bits(),
+ statx_buf.as_mut_ptr(),
+ ))?;
+ Ok(statx_buf.assume_init())
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub(crate) fn is_statx_available() -> bool {
+ unsafe {
+ // Call `statx` with null pointers so that if it fails for any reason
+ // other than `EFAULT`, we know it's not supported.
+ matches!(
+ ret(sys::statx(cwd(), null(), 0, 0, null_mut())),
+ Err(io::Errno::FAULT)
+ )
+ }
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) unsafe fn fcopyfile(
+ from: BorrowedFd<'_>,
+ to: BorrowedFd<'_>,
+ state: copyfile_state_t,
+ flags: CopyfileFlags,
+) -> io::Result<()> {
+ extern "C" {
+ fn fcopyfile(
+ from: c::c_int,
+ to: c::c_int,
+ state: copyfile_state_t,
+ flags: c::c_uint,
+ ) -> c::c_int;
+ }
+
+ nonnegative_ret(fcopyfile(
+ borrowed_fd(from),
+ borrowed_fd(to),
+ state,
+ flags.bits(),
+ ))
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) fn copyfile_state_alloc() -> io::Result<copyfile_state_t> {
+ extern "C" {
+ fn copyfile_state_alloc() -> copyfile_state_t;
+ }
+
+ let result = unsafe { copyfile_state_alloc() };
+ if result.0.is_null() {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(result)
+ }
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) unsafe fn copyfile_state_free(state: copyfile_state_t) -> io::Result<()> {
+ extern "C" {
+ fn copyfile_state_free(state: copyfile_state_t) -> c::c_int;
+ }
+
+ nonnegative_ret(copyfile_state_free(state))
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+const COPYFILE_STATE_COPIED: u32 = 8;
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) unsafe fn copyfile_state_get_copied(state: copyfile_state_t) -> io::Result<u64> {
+ let mut copied = MaybeUninit::<u64>::uninit();
+ copyfile_state_get(state, COPYFILE_STATE_COPIED, copied.as_mut_ptr().cast())?;
+ Ok(copied.assume_init())
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) unsafe fn copyfile_state_get(
+ state: copyfile_state_t,
+ flag: u32,
+ dst: *mut c::c_void,
+) -> io::Result<()> {
+ extern "C" {
+ fn copyfile_state_get(state: copyfile_state_t, flag: u32, dst: *mut c::c_void) -> c::c_int;
+ }
+
+ nonnegative_ret(copyfile_state_get(state, flag, dst))
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) fn getpath(fd: BorrowedFd<'_>) -> io::Result<CString> {
+ // The use of PATH_MAX is generally not encouraged, but it
+ // is inevitable in this case because macOS defines `fcntl` with
+ // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no
+ // alternatives. If a better method is invented, it should be used
+ // instead.
+ let mut buf = vec![0; c::PATH_MAX as usize];
+
+ // From the [macOS `fcntl` man page]:
+ // `F_GETPATH` - Get the path of the file descriptor `Fildes`. The argument
+ // must be a buffer of size `MAXPATHLEN` or greater.
+ //
+ // [macOS `fcntl` man page]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+ unsafe {
+ ret(c::fcntl(borrowed_fd(fd), c::F_GETPATH, buf.as_mut_ptr()))?;
+ }
+
+ let l = buf.iter().position(|&c| c == 0).unwrap();
+ buf.truncate(l);
+
+ // TODO: On Rust 1.56, we can use `shrink_to` here.
+ //buf.shrink_to(l + 1);
+ buf.shrink_to_fit();
+
+ Ok(CString::new(buf).unwrap())
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) fn fcntl_rdadvise(fd: BorrowedFd<'_>, offset: u64, len: u64) -> io::Result<()> {
+ // From the [macOS `fcntl` man page]:
+ // `F_RDADVISE` - Issue an advisory read async with no copy to user.
+ //
+ // The `F_RDADVISE` command operates on the following structure which holds
+ // information passed from the user to the system:
+ //
+ // ```c
+ // struct radvisory {
+ // off_t ra_offset; /* offset into the file */
+ // int ra_count; /* size of the read */
+ // };
+ // ```
+ //
+ // [macOS `fcntl` man page]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
+ let ra_offset = match offset.try_into() {
+ Ok(len) => len,
+ // If this conversion fails, the user is providing an offset outside
+ // any possible file extent, so just ignore it.
+ Err(_) => return Ok(()),
+ };
+ let ra_count = match len.try_into() {
+ Ok(len) => len,
+ // If this conversion fails, the user is providing a dubiously large
+ // hint which is unlikely to improve performance.
+ Err(_) => return Ok(()),
+ };
+ unsafe {
+ let radvisory = c::radvisory {
+ ra_offset,
+ ra_count,
+ };
+ ret(c::fcntl(borrowed_fd(fd), c::F_RDADVISE, &radvisory))
+ }
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) fn fcntl_fullfsync(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_FULLFSYNC)) }
+}
+
+/// Convert `times` from a `futimens`/`utimensat` argument into `setattrlist`
+/// arguments.
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+fn times_to_attrlist(times: &Timestamps) -> (c::size_t, [c::timespec; 2], Attrlist) {
+ // ABI details.
+ const ATTR_CMN_MODTIME: u32 = 0x0000_0400;
+ const ATTR_CMN_ACCTIME: u32 = 0x0000_1000;
+ const ATTR_BIT_MAP_COUNT: u16 = 5;
+
+ let mut times = times.clone();
+
+ // If we have any `UTIME_NOW` elements, replace them with the current time.
+ if times.last_access.tv_nsec == c::UTIME_NOW || times.last_modification.tv_nsec == c::UTIME_NOW
+ {
+ let now = {
+ let mut tv = c::timeval {
+ tv_sec: 0,
+ tv_usec: 0,
+ };
+ unsafe {
+ let r = c::gettimeofday(&mut tv, null_mut());
+ assert_eq!(r, 0);
+ }
+ c::timespec {
+ tv_sec: tv.tv_sec,
+ tv_nsec: (tv.tv_usec * 1000) as _,
+ }
+ };
+ if times.last_access.tv_nsec == c::UTIME_NOW {
+ times.last_access = now;
+ }
+ if times.last_modification.tv_nsec == c::UTIME_NOW {
+ times.last_modification = now;
+ }
+ }
+
+ // Pack the return values following the rules for [`getattrlist`].
+ //
+ // [`getattrlist`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getattrlist.2.html
+ let mut times_size = 0;
+ let mut attrs = Attrlist {
+ bitmapcount: ATTR_BIT_MAP_COUNT,
+ reserved: 0,
+ commonattr: 0,
+ volattr: 0,
+ dirattr: 0,
+ fileattr: 0,
+ forkattr: 0,
+ };
+ let mut return_times = [c::timespec {
+ tv_sec: 0,
+ tv_nsec: 0,
+ }; 2];
+ let mut times_index = 0;
+ if times.last_modification.tv_nsec != c::UTIME_OMIT {
+ attrs.commonattr |= ATTR_CMN_MODTIME;
+ return_times[times_index] = times.last_modification;
+ times_index += 1;
+ times_size += size_of::<c::timespec>();
+ }
+ if times.last_access.tv_nsec != c::UTIME_OMIT {
+ attrs.commonattr |= ATTR_CMN_ACCTIME;
+ return_times[times_index] = times.last_access;
+ times_size += size_of::<c::timespec>();
+ }
+
+ (times_size, return_times, attrs)
+}
+
+/// Support type for `Attrlist`.
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+type Attrgroup = u32;
+
+/// Attribute list for use with `setattrlist`.
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[repr(C)]
+struct Attrlist {
+ bitmapcount: u16,
+ reserved: u16,
+ commonattr: Attrgroup,
+ volattr: Attrgroup,
+ dirattr: Attrgroup,
+ fileattr: Attrgroup,
+ forkattr: Attrgroup,
+}
diff --git a/vendor/rustix/src/imp/libc/fs/types.rs b/vendor/rustix/src/imp/libc/fs/types.rs
new file mode 100644
index 000000000..9d892daf0
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/fs/types.rs
@@ -0,0 +1,1028 @@
+use super::super::c;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `FD_*` constants for use with [`fcntl_getfd`] and [`fcntl_setfd`].
+ ///
+ /// [`fcntl_getfd`]: crate::fs::fcntl_getfd
+ /// [`fcntl_setfd`]: crate::fs::fcntl_setfd
+ pub struct FdFlags: c::c_int {
+ /// `FD_CLOEXEC`
+ const CLOEXEC = c::FD_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `*_OK` constants for use with [`accessat`].
+ ///
+ /// [`accessat`]: fn.accessat.html
+ pub struct Access: c::c_int {
+ /// `R_OK`
+ const READ_OK = c::R_OK;
+
+ /// `W_OK`
+ const WRITE_OK = c::W_OK;
+
+ /// `X_OK`
+ const EXEC_OK = c::X_OK;
+
+ /// `F_OK`
+ const EXISTS = c::F_OK;
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+bitflags! {
+ /// `AT_*` constants for use with [`openat`], [`statat`], and other `*at`
+ /// functions.
+ ///
+ /// [`openat`]: crate::fs::openat
+ /// [`statat`]: crate::fs::statat
+ pub struct AtFlags: c::c_int {
+ /// `AT_REMOVEDIR`
+ const REMOVEDIR = c::AT_REMOVEDIR;
+
+ /// `AT_SYMLINK_FOLLOW`
+ const SYMLINK_FOLLOW = c::AT_SYMLINK_FOLLOW;
+
+ /// `AT_SYMLINK_NOFOLLOW`
+ const SYMLINK_NOFOLLOW = c::AT_SYMLINK_NOFOLLOW;
+
+ /// `AT_EMPTY_PATH`
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux",
+ ))]
+ const EMPTY_PATH = c::AT_EMPTY_PATH;
+
+ /// `AT_EACCESS`
+ #[cfg(not(any(target_os = "emscripten", target_os = "android")))]
+ const EACCESS = c::AT_EACCESS;
+
+ /// `AT_STATX_SYNC_AS_STAT`
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ const STATX_SYNC_AS_STAT = c::AT_STATX_SYNC_AS_STAT;
+
+ /// `AT_STATX_FORCE_SYNC`
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ const STATX_FORCE_SYNC = c::AT_STATX_FORCE_SYNC;
+
+ /// `AT_STATX_DONT_SYNC`
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ const STATX_DONT_SYNC = c::AT_STATX_DONT_SYNC;
+ }
+}
+
+bitflags! {
+ /// `S_I*` constants for use with [`openat`], [`chmodat`], and [`fchmod`].
+ ///
+ /// [`openat`]: crate::fs::openat
+ /// [`chmodat`]: crate::fs::chmodat
+ /// [`fchmod`]: crate::fs::fchmod
+ pub struct Mode: RawMode {
+ /// `S_IRWXU`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const RWXU = c::S_IRWXU as RawMode;
+
+ /// `S_IRUSR`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const RUSR = c::S_IRUSR as RawMode;
+
+ /// `S_IWUSR`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const WUSR = c::S_IWUSR as RawMode;
+
+ /// `S_IXUSR`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const XUSR = c::S_IXUSR as RawMode;
+
+ /// `S_IRWXG`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const RWXG = c::S_IRWXG as RawMode;
+
+ /// `S_IRGRP`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const RGRP = c::S_IRGRP as RawMode;
+
+ /// `S_IWGRP`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const WGRP = c::S_IWGRP as RawMode;
+
+ /// `S_IXGRP`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const XGRP = c::S_IXGRP as RawMode;
+
+ /// `S_IRWXO`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const RWXO = c::S_IRWXO as RawMode;
+
+ /// `S_IROTH`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const ROTH = c::S_IROTH as RawMode;
+
+ /// `S_IWOTH`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const WOTH = c::S_IWOTH as RawMode;
+
+ /// `S_IXOTH`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const XOTH = c::S_IXOTH as RawMode;
+
+ /// `S_ISUID`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const SUID = c::S_ISUID as RawMode;
+
+ /// `S_ISGID`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const SGID = c::S_ISGID as RawMode;
+
+ /// `S_ISVTX`
+ #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags.
+ const SVTX = c::S_ISVTX as RawMode;
+ }
+}
+
+impl Mode {
+ /// Construct a `Mode` from the mode bits of the `st_mode` field of
+ /// a `Stat`.
+ #[inline]
+ pub const fn from_raw_mode(st_mode: RawMode) -> Self {
+ Self::from_bits_truncate(st_mode)
+ }
+
+ /// Construct an `st_mode` value from `Stat`.
+ #[inline]
+ pub const fn as_raw_mode(self) -> RawMode {
+ self.bits()
+ }
+}
+
+bitflags! {
+ /// `O_*` constants for use with [`openat`].
+ ///
+ /// [`openat`]: crate::fs::openat
+ pub struct OFlags: c::c_int {
+ /// `O_ACCMODE`
+ const ACCMODE = c::O_ACCMODE;
+
+ /// Similar to `ACCMODE`, but just includes the read/write flags, and
+ /// no other flags.
+ ///
+ /// Some implementations include `O_PATH` in `O_ACCMODE`, when
+ /// sometimes we really just want the read/write bits. Caution is
+ /// indicated, as the presence of `O_PATH` may mean that the read/write
+ /// bits don't have their usual meaning.
+ const RWMODE = c::O_RDONLY | c::O_WRONLY | c::O_RDWR;
+
+ /// `O_APPEND`
+ const APPEND = c::O_APPEND;
+
+ /// `O_CREAT`
+ #[doc(alias = "CREAT")]
+ const CREATE = c::O_CREAT;
+
+ /// `O_DIRECTORY`
+ const DIRECTORY = c::O_DIRECTORY;
+
+ /// `O_DSYNC`
+ #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "redox")))]
+ const DSYNC = c::O_DSYNC;
+
+ /// `O_EXCL`
+ const EXCL = c::O_EXCL;
+
+ /// `O_FSYNC`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ all(target_os = "linux", not(target_env = "musl")),
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ const FSYNC = c::O_FSYNC;
+
+ /// `O_NOFOLLOW`
+ const NOFOLLOW = c::O_NOFOLLOW;
+
+ /// `O_NONBLOCK`
+ const NONBLOCK = c::O_NONBLOCK;
+
+ /// `O_RDONLY`
+ const RDONLY = c::O_RDONLY;
+
+ /// `O_WRONLY`
+ const WRONLY = c::O_WRONLY;
+
+ /// `O_RDWR`
+ const RDWR = c::O_RDWR;
+
+ /// `O_NOCTTY`
+ #[cfg(not(target_os = "redox"))]
+ const NOCTTY = c::O_NOCTTY;
+
+ /// `O_RSYNC`
+ #[cfg(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ ))]
+ const RSYNC = c::O_RSYNC;
+
+ /// `O_SYNC`
+ #[cfg(not(target_os = "redox"))]
+ const SYNC = c::O_SYNC;
+
+ /// `O_TRUNC`
+ const TRUNC = c::O_TRUNC;
+
+ /// `O_PATH`
+ #[cfg(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux",
+ target_os = "redox",
+ ))]
+ const PATH = c::O_PATH;
+
+ /// `O_CLOEXEC`
+ const CLOEXEC = c::O_CLOEXEC;
+
+ /// `O_TMPFILE`
+ #[cfg(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux",
+ ))]
+ const TMPFILE = c::O_TMPFILE;
+
+ /// `O_NOATIME`
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux",
+ ))]
+ const NOATIME = c::O_NOATIME;
+ }
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+bitflags! {
+ /// `CLONE_*` constants for use with [`fclonefileat`].
+ ///
+ /// [`fclonefileat`]: crate::fs::fclonefileat
+ pub struct CloneFlags: c::c_int {
+ /// `CLONE_NOFOLLOW`
+ const NOFOLLOW = 1;
+
+ /// `CLONE_NOOWNERCOPY`
+ const NOOWNERCOPY = 2;
+ }
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+mod copyfile {
+ pub(super) const ACL: u32 = 1 << 0;
+ pub(super) const STAT: u32 = 1 << 1;
+ pub(super) const XATTR: u32 = 1 << 2;
+ pub(super) const DATA: u32 = 1 << 3;
+ pub(super) const SECURITY: u32 = STAT | ACL;
+ pub(super) const METADATA: u32 = SECURITY | XATTR;
+ pub(super) const ALL: u32 = METADATA | DATA;
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+bitflags! {
+ /// `COPYFILE_*` constants.
+ pub struct CopyfileFlags: c::c_uint {
+ /// `COPYFILE_ACL`
+ const ACL = copyfile::ACL;
+
+ /// `COPYFILE_STAT`
+ const STAT = copyfile::STAT;
+
+ /// `COPYFILE_XATTR`
+ const XATTR = copyfile::XATTR;
+
+ /// `COPYFILE_DATA`
+ const DATA = copyfile::DATA;
+
+ /// `COPYFILE_SECURITY`
+ const SECURITY = copyfile::SECURITY;
+
+ /// `COPYFILE_METADATA`
+ const METADATA = copyfile::METADATA;
+
+ /// `COPYFILE_ALL`
+ const ALL = copyfile::ALL;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `RESOLVE_*` constants for use with [`openat2`].
+ ///
+ /// [`openat2`]: crate::fs::openat2
+ #[derive(Default)]
+ pub struct ResolveFlags: u64 {
+ /// `RESOLVE_NO_XDEV`
+ const NO_XDEV = 0x01;
+
+ /// `RESOLVE_NO_MAGICLINKS`
+ const NO_MAGICLINKS = 0x02;
+
+ /// `RESOLVE_NO_SYMLINKS`
+ const NO_SYMLINKS = 0x04;
+
+ /// `RESOLVE_BENEATH`
+ const BENEATH = 0x08;
+
+ /// `RESOLVE_IN_ROOT`
+ const IN_ROOT = 0x10;
+
+ /// `RESOLVE_CACHED` (since Linux 5.12)
+ const CACHED = 0x20;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `RENAME_*` constants for use with [`renameat_with`].
+ ///
+ /// [`renameat_with`]: crate::fs::renameat_with
+ pub struct RenameFlags: c::c_uint {
+ /// `RENAME_EXCHANGE`
+ const EXCHANGE = c::RENAME_EXCHANGE as _;
+
+ /// `RENAME_NOREPLACE`
+ const NOREPLACE = c::RENAME_NOREPLACE as _;
+
+ /// `RENAME_WHITEOUT`
+ const WHITEOUT = c::RENAME_WHITEOUT as _;
+ }
+}
+
+/// `S_IF*` constants for use with [`mknodat`] and [`Stat`]'s `st_mode` field.
+///
+/// [`mknodat`]: crate::fs::mknodat
+/// [`Stat`]: crate::fs::Stat
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum FileType {
+ /// `S_IFREG`
+ RegularFile = c::S_IFREG as isize,
+
+ /// `S_IFDIR`
+ Directory = c::S_IFDIR as isize,
+
+ /// `S_IFLNK`
+ Symlink = c::S_IFLNK as isize,
+
+ /// `S_IFIFO`
+ #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`.
+ #[doc(alias = "IFO")]
+ Fifo = c::S_IFIFO as isize,
+
+ /// `S_IFSOCK`
+ #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`.
+ Socket = c::S_IFSOCK as isize,
+
+ /// `S_IFCHR`
+ CharacterDevice = c::S_IFCHR as isize,
+
+ /// `S_IFBLK`
+ BlockDevice = c::S_IFBLK as isize,
+
+ /// An unknown filesystem object.
+ Unknown,
+}
+
+impl FileType {
+ /// Construct a `FileType` from the `S_IFMT` bits of the `st_mode` field of
+ /// a `Stat`.
+ pub const fn from_raw_mode(st_mode: RawMode) -> Self {
+ match (st_mode as c::mode_t) & c::S_IFMT {
+ c::S_IFREG => Self::RegularFile,
+ c::S_IFDIR => Self::Directory,
+ c::S_IFLNK => Self::Symlink,
+ #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`.
+ c::S_IFIFO => Self::Fifo,
+ #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`.
+ c::S_IFSOCK => Self::Socket,
+ c::S_IFCHR => Self::CharacterDevice,
+ c::S_IFBLK => Self::BlockDevice,
+ _ => Self::Unknown,
+ }
+ }
+
+ /// Construct an `st_mode` value from `Stat`.
+ pub const fn as_raw_mode(self) -> RawMode {
+ match self {
+ Self::RegularFile => c::S_IFREG as RawMode,
+ Self::Directory => c::S_IFDIR as RawMode,
+ Self::Symlink => c::S_IFLNK as RawMode,
+ #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`.
+ Self::Fifo => c::S_IFIFO as RawMode,
+ #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`.
+ Self::Socket => c::S_IFSOCK as RawMode,
+ Self::CharacterDevice => c::S_IFCHR as RawMode,
+ Self::BlockDevice => c::S_IFBLK as RawMode,
+ Self::Unknown => c::S_IFMT as RawMode,
+ }
+ }
+
+ /// Construct a `FileType` from the `d_type` field of a `c::dirent`.
+ #[cfg(not(any(target_os = "illumos", target_os = "redox")))]
+ pub(crate) const fn from_dirent_d_type(d_type: u8) -> Self {
+ match d_type {
+ c::DT_REG => Self::RegularFile,
+ c::DT_DIR => Self::Directory,
+ c::DT_LNK => Self::Symlink,
+ #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `DT_SOCK`.
+ c::DT_SOCK => Self::Socket,
+ #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `DT_FIFO`.
+ c::DT_FIFO => Self::Fifo,
+ c::DT_CHR => Self::CharacterDevice,
+ c::DT_BLK => Self::BlockDevice,
+ // c::DT_UNKNOWN |
+ _ => Self::Unknown,
+ }
+ }
+}
+
+/// `POSIX_FADV_*` constants for use with [`fadvise`].
+///
+/// [`fadvise`]: crate::fs::fadvise
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[repr(u32)]
+pub enum Advice {
+ /// `POSIX_FADV_NORMAL`
+ Normal = c::POSIX_FADV_NORMAL as c::c_uint,
+
+ /// `POSIX_FADV_SEQUENTIAL`
+ Sequential = c::POSIX_FADV_SEQUENTIAL as c::c_uint,
+
+ /// `POSIX_FADV_RANDOM`
+ Random = c::POSIX_FADV_RANDOM as c::c_uint,
+
+ /// `POSIX_FADV_NOREUSE`
+ NoReuse = c::POSIX_FADV_NOREUSE as c::c_uint,
+
+ /// `POSIX_FADV_WILLNEED`
+ WillNeed = c::POSIX_FADV_WILLNEED as c::c_uint,
+
+ /// `POSIX_FADV_DONTNEED`
+ DontNeed = c::POSIX_FADV_DONTNEED as c::c_uint,
+}
+
+#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+bitflags! {
+ /// `MFD_*` constants for use with [`memfd_create`].
+ ///
+ /// [`memfd_create`]: crate::fs::memfd_create
+ pub struct MemfdFlags: c::c_uint {
+ /// `MFD_CLOEXEC`
+ const CLOEXEC = c::MFD_CLOEXEC;
+
+ /// `MFD_ALLOW_SEALING`
+ const ALLOW_SEALING = c::MFD_ALLOW_SEALING;
+
+ /// `MFD_HUGETLB` (since Linux 4.14)
+ const HUGETLB = c::MFD_HUGETLB;
+
+ /// `MFD_HUGE_64KB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_64KB = c::MFD_HUGE_64KB;
+ /// `MFD_HUGE_512JB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_512KB = c::MFD_HUGE_512KB;
+ /// `MFD_HUGE_1MB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_1MB = c::MFD_HUGE_1MB;
+ /// `MFD_HUGE_2MB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_2MB = c::MFD_HUGE_2MB;
+ /// `MFD_HUGE_8MB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_8MB = c::MFD_HUGE_8MB;
+ /// `MFD_HUGE_16MB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_16MB = c::MFD_HUGE_16MB;
+ /// `MFD_HUGE_32MB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_32MB = c::MFD_HUGE_32MB;
+ /// `MFD_HUGE_256MB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_256MB = c::MFD_HUGE_256MB;
+ /// `MFD_HUGE_512MB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_512MB = c::MFD_HUGE_512MB;
+ /// `MFD_HUGE_1GB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_1GB = c::MFD_HUGE_1GB;
+ /// `MFD_HUGE_2GB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_2GB = c::MFD_HUGE_2GB;
+ /// `MFD_HUGE_16GB`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const HUGE_16GB = c::MFD_HUGE_16GB;
+ }
+}
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+bitflags! {
+ /// `F_SEAL_*` constants for use with [`fcntl_add_seals`] and
+ /// [`fcntl_get_seals`].
+ ///
+ /// [`fcntl_add_seals`]: crate::fs::fcntl_add_seals
+ /// [`fcntl_get_seals`]: crate::fs::fcntl_get_seals
+ pub struct SealFlags: i32 {
+ /// `F_SEAL_SEAL`.
+ const SEAL = c::F_SEAL_SEAL;
+ /// `F_SEAL_SHRINK`.
+ const SHRINK = c::F_SEAL_SHRINK;
+ /// `F_SEAL_GROW`.
+ const GROW = c::F_SEAL_GROW;
+ /// `F_SEAL_WRITE`.
+ const WRITE = c::F_SEAL_WRITE;
+ /// `F_SEAL_FUTURE_WRITE` (since Linux 5.1)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const FUTURE_WRITE = c::F_SEAL_FUTURE_WRITE;
+ }
+}
+
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+bitflags! {
+ /// `STATX_*` constants for use with [`statx`].
+ ///
+ /// [`statx`]: crate::fs::statx
+ pub struct StatxFlags: u32 {
+ /// `STATX_TYPE`
+ const TYPE = c::STATX_TYPE;
+
+ /// `STATX_MODE`
+ const MODE = c::STATX_MODE;
+
+ /// `STATX_NLINK`
+ const NLINK = c::STATX_NLINK;
+
+ /// `STATX_UID`
+ const UID = c::STATX_UID;
+
+ /// `STATX_GID`
+ const GID = c::STATX_GID;
+
+ /// `STATX_ATIME`
+ const ATIME = c::STATX_ATIME;
+
+ /// `STATX_MTIME`
+ const MTIME = c::STATX_MTIME;
+
+ /// `STATX_CTIME`
+ const CTIME = c::STATX_CTIME;
+
+ /// `STATX_INO`
+ const INO = c::STATX_INO;
+
+ /// `STATX_SIZE`
+ const SIZE = c::STATX_SIZE;
+
+ /// `STATX_BLOCKS`
+ const BLOCKS = c::STATX_BLOCKS;
+
+ /// `STATX_BASIC_STATS`
+ const BASIC_STATS = c::STATX_BASIC_STATS;
+
+ /// `STATX_BTIME`
+ const BTIME = c::STATX_BTIME;
+
+ /// `STATX_MNT_ID` (since Linux 5.8)
+ const MNT_ID = c::STATX_MNT_ID;
+
+ /// `STATX_ALL`
+ const ALL = c::STATX_ALL;
+ }
+}
+
+#[cfg(any(
+ target_os = "android",
+ all(target_os = "linux", not(target_env = "gnu")),
+))]
+bitflags! {
+ /// `STATX_*` constants for use with [`statx`].
+ ///
+ /// [`statx`]: crate::fs::statx
+ pub struct StatxFlags: u32 {
+ /// `STATX_TYPE`
+ const TYPE = 0x0001;
+
+ /// `STATX_MODE`
+ const MODE = 0x0002;
+
+ /// `STATX_NLINK`
+ const NLINK = 0x0004;
+
+ /// `STATX_UID`
+ const UID = 0x0008;
+
+ /// `STATX_GID`
+ const GID = 0x0010;
+
+ /// `STATX_ATIME`
+ const ATIME = 0x0020;
+
+ /// `STATX_MTIME`
+ const MTIME = 0x0040;
+
+ /// `STATX_CTIME`
+ const CTIME = 0x0080;
+
+ /// `STATX_INO`
+ const INO = 0x0100;
+
+ /// `STATX_SIZE`
+ const SIZE = 0x0200;
+
+ /// `STATX_BLOCKS`
+ const BLOCKS = 0x0400;
+
+ /// `STATX_BASIC_STATS`
+ const BASIC_STATS = 0x07ff;
+
+ /// `STATX_BTIME`
+ const BTIME = 0x800;
+
+ /// `STATX_MNT_ID` (since Linux 5.8)
+ const MNT_ID = 0x1000;
+
+ /// `STATX_ALL`
+ const ALL = 0xfff;
+ }
+}
+
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+bitflags! {
+ /// `FALLOC_FL_*` constants for use with [`fallocate`].
+ ///
+ /// [`fallocate`]: crate::fs::fallocate
+ pub struct FallocateFlags: i32 {
+ /// `FALLOC_FL_KEEP_SIZE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ const KEEP_SIZE = c::FALLOC_FL_KEEP_SIZE;
+ /// `FALLOC_FL_PUNCH_HOLE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ const PUNCH_HOLE = c::FALLOC_FL_PUNCH_HOLE;
+ /// `FALLOC_FL_NO_HIDE_STALE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "wasi",
+ )))]
+ const NO_HIDE_STALE = c::FALLOC_FL_NO_HIDE_STALE;
+ /// `FALLOC_FL_COLLAPSE_RANGE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "emscripten",
+ target_os = "wasi",
+ )))]
+ const COLLAPSE_RANGE = c::FALLOC_FL_COLLAPSE_RANGE;
+ /// `FALLOC_FL_ZERO_RANGE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "emscripten",
+ target_os = "wasi",
+ )))]
+ const ZERO_RANGE = c::FALLOC_FL_ZERO_RANGE;
+ /// `FALLOC_FL_INSERT_RANGE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "emscripten",
+ target_os = "wasi",
+ )))]
+ const INSERT_RANGE = c::FALLOC_FL_INSERT_RANGE;
+ /// `FALLOC_FL_UNSHARE_RANGE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "emscripten",
+ target_os = "wasi",
+ )))]
+ const UNSHARE_RANGE = c::FALLOC_FL_UNSHARE_RANGE;
+ }
+}
+
+/// `LOCK_*` constants for use with [`flock`]
+///
+/// [`flock`]: crate::fs::flock
+#[cfg(not(target_os = "wasi"))]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[repr(i32)]
+pub enum FlockOperation {
+ /// `LOCK_SH`
+ LockShared = c::LOCK_SH,
+ /// `LOCK_EX`
+ LockExclusive = c::LOCK_EX,
+ /// `LOCK_UN`
+ Unlock = c::LOCK_UN,
+ /// `LOCK_SH | LOCK_NB`
+ NonBlockingLockShared = c::LOCK_SH | c::LOCK_NB,
+ /// `LOCK_EX | LOCK_NB`
+ NonBlockingLockExclusive = c::LOCK_EX | c::LOCK_NB,
+ /// `LOCK_UN | LOCK_NB`
+ NonBlockingUnlock = c::LOCK_UN | c::LOCK_NB,
+}
+
+/// `struct stat` for use with [`statat`] and [`fstat`].
+///
+/// [`statat`]: crate::fs::statat
+/// [`fstat`]: crate::fs::fstat
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+)))]
+pub type Stat = c::stat;
+
+/// `struct stat` for use with [`statat`] and [`fstat`].
+///
+/// [`statat`]: crate::fs::statat
+/// [`fstat`]: crate::fs::fstat
+#[cfg(any(
+ all(
+ any(target_os = "android", target_os = "linux"),
+ target_pointer_width = "64",
+ ),
+ target_os = "emscripten",
+ target_os = "l4re",
+))]
+pub type Stat = c::stat64;
+
+/// `struct stat` for use with [`statat`] and [`fstat`].
+///
+/// [`statat`]: crate::fs::statat
+/// [`fstat`]: crate::fs::fstat
+// On 32-bit, Linux's `struct stat64` has a 32-bit `st_mtime` and friends, so
+// we use our own struct, populated from `statx` where possible, to avoid the
+// y2038 bug.
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ target_pointer_width = "32",
+))]
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+#[allow(missing_docs)]
+pub struct Stat {
+ pub st_dev: u64,
+ pub st_mode: u32,
+ pub st_nlink: u32,
+ pub st_uid: u32,
+ pub st_gid: u32,
+ pub st_rdev: u64,
+ pub st_size: i64,
+ pub st_blksize: u32,
+ pub st_blocks: u64,
+ pub st_atime: u64,
+ pub st_atime_nsec: u32,
+ pub st_mtime: u64,
+ pub st_mtime_nsec: u32,
+ pub st_ctime: u64,
+ pub st_ctime_nsec: u32,
+ pub st_ino: u64,
+}
+
+/// `struct statfs` for use with [`fstatfs`].
+///
+/// [`fstatfs`]: crate::fs::fstatfs
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "linux",
+ target_os = "l4re",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[allow(clippy::module_name_repetitions)]
+pub type StatFs = c::statfs;
+
+/// `struct statfs` for use with [`fstatfs`].
+///
+/// [`fstatfs`]: crate::fs::fstatfs
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+))]
+pub type StatFs = c::statfs64;
+
+/// `struct statx` for use with [`statx`].
+///
+/// [`statx`]: crate::fs::statx
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+// Use the glibc `struct statx`.
+pub type Statx = c::statx;
+
+/// `struct statx_timestamp` for use with [`Statx`].
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+// Use the glibc `struct statx_timestamp`.
+pub type StatxTimestamp = c::statx;
+
+/// `struct statx` for use with [`statx`].
+///
+/// [`statx`]: crate::fs::statx
+// Non-glibc ABIs don't currently declare a `struct statx`, so we declare it
+// ourselves.
+#[cfg(any(
+ target_os = "android",
+ all(target_os = "linux", not(target_env = "gnu")),
+))]
+#[repr(C)]
+#[allow(missing_docs)]
+pub struct Statx {
+ pub stx_mask: u32,
+ pub stx_blksize: u32,
+ pub stx_attributes: u64,
+ pub stx_nlink: u32,
+ pub stx_uid: u32,
+ pub stx_gid: u32,
+ pub stx_mode: u16,
+ __statx_pad1: [u16; 1],
+ pub stx_ino: u64,
+ pub stx_size: u64,
+ pub stx_blocks: u64,
+ pub stx_attributes_mask: u64,
+ pub stx_atime: StatxTimestamp,
+ pub stx_btime: StatxTimestamp,
+ pub stx_ctime: StatxTimestamp,
+ pub stx_mtime: StatxTimestamp,
+ pub stx_rdev_major: u32,
+ pub stx_rdev_minor: u32,
+ pub stx_dev_major: u32,
+ pub stx_dev_minor: u32,
+ pub stx_mnt_id: u64,
+ __statx_pad2: u64,
+ __statx_pad3: [u64; 12],
+}
+
+/// `struct statx_timestamp` for use with [`Statx`].
+// Non-glibc ABIs don't currently declare a `struct statx_timestamp`, so we
+// declare it ourselves.
+#[cfg(any(
+ target_os = "android",
+ all(target_os = "linux", not(target_env = "gnu")),
+))]
+#[repr(C)]
+#[allow(missing_docs)]
+pub struct StatxTimestamp {
+ pub tv_sec: i64,
+ pub tv_nsec: u32,
+ pub __statx_timestamp_pad1: [i32; 1],
+}
+
+/// `mode_t`
+#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
+pub type RawMode = c::mode_t;
+
+/// `mode_t`
+#[cfg(all(target_os = "android", target_pointer_width = "32"))]
+pub type RawMode = c::c_uint;
+
+/// `dev_t`
+#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
+pub type Dev = c::dev_t;
+
+/// `dev_t`
+#[cfg(all(target_os = "android", target_pointer_width = "32"))]
+pub type Dev = c::c_ulonglong;
+
+/// `__fsword_t`
+#[cfg(all(
+ target_os = "linux",
+ not(target_env = "musl"),
+ not(target_arch = "s390x"),
+))]
+pub type FsWord = c::__fsword_t;
+
+/// `__fsword_t`
+#[cfg(all(
+ any(target_os = "android", all(target_os = "linux", target_env = "musl")),
+ target_pointer_width = "32",
+))]
+pub type FsWord = u32;
+
+/// `__fsword_t`
+#[cfg(all(
+ any(target_os = "android", all(target_os = "linux", target_env = "musl")),
+ not(target_arch = "s390x"),
+ target_pointer_width = "64",
+))]
+pub type FsWord = u64;
+
+/// `__fsword_t`
+// s390x uses `u32` for `statfs` entries, even though `__fsword_t` is `u64`.
+#[cfg(all(target_os = "linux", target_arch = "s390x"))]
+pub type FsWord = u32;
+
+#[cfg(not(target_os = "redox"))]
+pub use c::{UTIME_NOW, UTIME_OMIT};
+
+/// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem.
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ not(target_env = "musl"),
+))]
+pub const PROC_SUPER_MAGIC: FsWord = c::PROC_SUPER_MAGIC as FsWord;
+
+/// `NFS_SUPER_MAGIC`—The magic number for the NFS filesystem.
+#[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ not(target_env = "musl"),
+))]
+pub const NFS_SUPER_MAGIC: FsWord = c::NFS_SUPER_MAGIC as FsWord;
+
+/// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem.
+#[cfg(all(any(target_os = "android", target_os = "linux"), target_env = "musl"))]
+pub const PROC_SUPER_MAGIC: FsWord = 0x0000_9fa0;
+
+/// `NFS_SUPER_MAGIC`—The magic number for the NFS filesystem.
+#[cfg(all(any(target_os = "android", target_os = "linux"), target_env = "musl"))]
+pub const NFS_SUPER_MAGIC: FsWord = 0x0000_6969;
+
+/// `copyfile_state_t`—State for use with [`fcopyfile`].
+///
+/// [`fcopyfile`]: crate::fs::fcopyfile
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[allow(non_camel_case_types)]
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+pub struct copyfile_state_t(pub(crate) *mut c::c_void);
diff --git a/vendor/rustix/src/imp/libc/io/epoll.rs b/vendor/rustix/src/imp/libc/io/epoll.rs
new file mode 100644
index 000000000..a95e6b5cd
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io/epoll.rs
@@ -0,0 +1,568 @@
+//! epoll support.
+//!
+//! This is an experiment, and it isn't yet clear whether epoll is the right
+//! level of abstraction at which to introduce safety. But it works fairly well
+//! in simple examples 🙂.
+//!
+//! # Examples
+//!
+//! ```rust,no_run
+//! # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+//! # #[cfg(feature = "net")]
+//! # fn main() -> std::io::Result<()> {
+//! use io_lifetimes::AsFd;
+//! use rustix::io::epoll::{self, Epoll};
+//! use rustix::io::{ioctl_fionbio, read, write};
+//! use rustix::net::{
+//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4,
+//! SocketType,
+//! };
+//! use std::os::unix::io::AsRawFd;
+//!
+//! // Create a socket and listen on it.
+//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?;
+//! listen(&listen_sock, 1)?;
+//!
+//! // Create an epoll object. Using `Owning` here means the epoll object will
+//! // take ownership of the file descriptors registered with it.
+//! let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC, epoll::Owning::new())?;
+//!
+//! // Remember the socket raw fd, which we use for comparisons only.
+//! let raw_listen_sock = listen_sock.as_fd().as_raw_fd();
+//!
+//! // Register the socket with the epoll object.
+//! epoll.add(listen_sock, epoll::EventFlags::IN)?;
+//!
+//! // Process events.
+//! let mut event_list = epoll::EventVec::with_capacity(4);
+//! loop {
+//! epoll.wait(&mut event_list, -1)?;
+//! for (_event_flags, target) in &event_list {
+//! if target.as_raw_fd() == raw_listen_sock {
+//! // Accept a new connection, set it to non-blocking, and
+//! // register to be notified when it's ready to write to.
+//! let conn_sock = accept(&*target)?;
+//! ioctl_fionbio(&conn_sock, true)?;
+//! epoll.add(conn_sock, epoll::EventFlags::OUT | epoll::EventFlags::ET)?;
+//! } else {
+//! // Write a message to the stream and then unregister it.
+//! write(&*target, b"hello\n")?;
+//! let _ = epoll.del(target)?;
+//! }
+//! }
+//! }
+//! # }
+//! # #[cfg(not(feature = "net"))]
+//! # fn main() {}
+//! ```
+
+use super::super::c;
+use super::super::conv::{ret, ret_owned_fd, ret_u32};
+use crate::fd::{AsFd, AsRawFd, BorrowedFd, RawFd};
+#[cfg(not(feature = "rustc-dep-of-std"))]
+use crate::fd::{FromFd, FromRawFd, IntoFd, IntoRawFd};
+use crate::io::{self, OwnedFd};
+use alloc::vec::Vec;
+use bitflags::bitflags;
+use core::convert::TryInto;
+use core::fmt;
+use core::marker::PhantomData;
+use core::ops::Deref;
+use core::ptr::{null, null_mut};
+
+bitflags! {
+ /// `EPOLL_*` for use with [`Epoll::new`].
+ pub struct CreateFlags: c::c_int {
+ /// `EPOLL_CLOEXEC`
+ const CLOEXEC = c::EPOLL_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `EPOLL*` for use with [`Epoll::add`].
+ #[derive(Default)]
+ pub struct EventFlags: u32 {
+ /// `EPOLLIN`
+ const IN = c::EPOLLIN as u32;
+
+ /// `EPOLLOUT`
+ const OUT = c::EPOLLOUT as u32;
+
+ /// `EPOLLPRI`
+ const PRI = c::EPOLLPRI as u32;
+
+ /// `EPOLLERR`
+ const ERR = c::EPOLLERR as u32;
+
+ /// `EPOLLHUP`
+ const HUP = c::EPOLLHUP as u32;
+
+ /// `EPOLLET`
+ const ET = c::EPOLLET as u32;
+
+ /// `EPOLLONESHOT`
+ const ONESHOT = c::EPOLLONESHOT as u32;
+
+ /// `EPOLLWAKEUP`
+ const WAKEUP = c::EPOLLWAKEUP as u32;
+
+ /// `EPOLLEXCLUSIVE`
+ #[cfg(not(target_os = "android"))]
+ const EXCLUSIVE = c::EPOLLEXCLUSIVE as u32;
+ }
+}
+
+/// A reference to a `T`.
+pub struct Ref<'a, T> {
+ t: T,
+ _phantom: PhantomData<&'a T>,
+}
+
+impl<'a, T> Ref<'a, T> {
+ #[inline]
+ fn new(t: T) -> Self {
+ Self {
+ t,
+ _phantom: PhantomData,
+ }
+ }
+
+ #[inline]
+ fn consume(self) -> T {
+ self.t
+ }
+}
+
+impl<'a, T> Deref for Ref<'a, T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ &self.t
+ }
+}
+
+impl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.t.fmt(fmt)
+ }
+}
+
+/// A trait for data stored within an [`Epoll`] instance.
+pub trait Context {
+ /// The type of an element owned by this context.
+ type Data;
+
+ /// The type of a value used to refer to an element owned by this context.
+ type Target: AsFd;
+
+ /// Assume ownership of `data`, and returning a `Target`.
+ fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target>;
+
+ /// Encode `target` as a `u64`. The only requirement on this value is that
+ /// it be decodable by `decode`.
+ fn encode(&self, target: Ref<'_, Self::Target>) -> u64;
+
+ /// Decode `raw`, which is a value encoded by `encode`, into a `Target`.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be a `u64` value returned from `encode`, from the same
+ /// context, and within the context's lifetime.
+ unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target>;
+
+ /// Release ownership of the value referred to by `target` and return it.
+ fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data;
+}
+
+/// A type implementing [`Context`] where the `Data` type is `BorrowedFd<'a>`.
+pub struct Borrowing<'a> {
+ _phantom: PhantomData<BorrowedFd<'a>>,
+}
+
+impl<'a> Context for Borrowing<'a> {
+ type Data = BorrowedFd<'a>;
+ type Target = BorrowedFd<'a>;
+
+ #[inline]
+ fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
+ Ref::new(data)
+ }
+
+ #[inline]
+ fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
+ target.as_raw_fd() as u64
+ }
+
+ #[inline]
+ unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
+ Ref::new(BorrowedFd::<'a>::borrow_raw(raw as RawFd))
+ }
+
+ #[inline]
+ fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
+ target.consume()
+ }
+}
+
+/// A type implementing [`Context`] where the `Data` type is `T`, a type
+/// implementing `IntoFd` and `FromFd`.
+///
+/// This may be used with [`OwnedFd`], or higher-level types like
+/// [`std::fs::File`] or [`std::net::TcpStream`].
+#[cfg(not(feature = "rustc-dep-of-std"))]
+pub struct Owning<'context, T: IntoFd + FromFd> {
+ _phantom: PhantomData<&'context T>,
+}
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+impl<'context, T: IntoFd + FromFd> Owning<'context, T> {
+ /// Creates a new empty `Owning`.
+ #[allow(clippy::new_without_default)] // This is a specialized type that doesn't need to be generically constructible.
+ #[inline]
+ pub fn new() -> Self {
+ Self {
+ _phantom: PhantomData,
+ }
+ }
+}
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+impl<'context, T: AsFd + IntoFd + FromFd> Context for Owning<'context, T> {
+ type Data = T;
+ type Target = BorrowedFd<'context>;
+
+ #[inline]
+ fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
+ let raw_fd = data.into_fd().into_raw_fd();
+ // Safety: `epoll` will assign ownership of the file descriptor to the
+ // kernel epoll object. We use `IntoFd`+`IntoRawFd` to consume the
+ // `Data` and extract the raw file descriptor and then "borrow" it
+ // with `borrow_raw` knowing that the borrow won't outlive the
+ // kernel epoll object.
+ unsafe { Ref::new(BorrowedFd::<'context>::borrow_raw(raw_fd)) }
+ }
+
+ #[inline]
+ fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
+ target.as_fd().as_raw_fd() as u64
+ }
+
+ #[inline]
+ unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
+ Ref::new(BorrowedFd::<'context>::borrow_raw(raw as RawFd))
+ }
+
+ #[inline]
+ fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
+ // The file descriptor was held by the kernel epoll object and is now
+ // being released, so we can create a new `OwnedFd` that assumes
+ // ownership.
+ let raw_fd = target.consume().as_raw_fd();
+ unsafe { T::from_fd(io_lifetimes::OwnedFd::from_raw_fd(raw_fd)) }
+ }
+}
+
+/// An "epoll", an interface to an OS object allowing one to repeatedly wait
+/// for events from a set of file descriptors efficiently.
+pub struct Epoll<Context: self::Context> {
+ epoll_fd: OwnedFd,
+ context: Context,
+}
+
+impl<Context: self::Context> Epoll<Context> {
+ /// `epoll_create1(flags)`—Creates a new `Epoll`.
+ ///
+ /// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
+ /// descriptor from being implicitly passed across `exec` boundaries.
+ #[inline]
+ #[doc(alias = "epoll_create1")]
+ pub fn new(flags: CreateFlags, context: Context) -> io::Result<Self> {
+ // Safety: We're calling `epoll_create1` via FFI and we know how it
+ // behaves.
+ unsafe {
+ Ok(Self {
+ epoll_fd: ret_owned_fd(c::epoll_create1(flags.bits()))?,
+ context,
+ })
+ }
+ }
+
+ /// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an
+ /// `Epoll`.
+ ///
+ /// This registers interest in any of the events set in `events` occurring
+ /// on the file descriptor associated with `data`.
+ #[doc(alias = "epoll_ctl")]
+ pub fn add(
+ &self,
+ data: Context::Data,
+ event_flags: EventFlags,
+ ) -> io::Result<Ref<'_, Context::Target>> {
+ // Safety: We're calling `epoll_ctl` via FFI and we know how it
+ // behaves.
+ unsafe {
+ let target = self.context.acquire(data);
+ let raw_fd = target.as_fd().as_raw_fd();
+ let encoded = self.context.encode(target);
+ ret(c::epoll_ctl(
+ self.epoll_fd.as_fd().as_raw_fd(),
+ c::EPOLL_CTL_ADD,
+ raw_fd,
+ &mut c::epoll_event {
+ events: event_flags.bits(),
+ r#u64: encoded,
+ },
+ ))?;
+ Ok(self.context.decode(encoded))
+ }
+ }
+
+ /// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in
+ /// this `Epoll`.
+ ///
+ /// This sets the events of interest with `target` to `events`.
+ #[doc(alias = "epoll_ctl")]
+ pub fn mod_(
+ &self,
+ target: Ref<'_, Context::Target>,
+ event_flags: EventFlags,
+ ) -> io::Result<()> {
+ let raw_fd = target.as_fd().as_raw_fd();
+ let encoded = self.context.encode(target);
+ // Safety: We're calling `epoll_ctl` via FFI and we know how it
+ // behaves.
+ unsafe {
+ ret(c::epoll_ctl(
+ self.epoll_fd.as_fd().as_raw_fd(),
+ c::EPOLL_CTL_MOD,
+ raw_fd,
+ &mut c::epoll_event {
+ events: event_flags.bits(),
+ r#u64: encoded,
+ },
+ ))
+ }
+ }
+
+ /// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in
+ /// this `Epoll`.
+ ///
+ /// This also returns the owning `Data`.
+ #[doc(alias = "epoll_ctl")]
+ pub fn del(&self, target: Ref<'_, Context::Target>) -> io::Result<Context::Data> {
+ // Safety: We're calling `epoll_ctl` via FFI and we know how it
+ // behaves.
+ unsafe {
+ let raw_fd = target.as_fd().as_raw_fd();
+ ret(c::epoll_ctl(
+ self.epoll_fd.as_fd().as_raw_fd(),
+ c::EPOLL_CTL_DEL,
+ raw_fd,
+ null_mut(),
+ ))?;
+ }
+ Ok(self.context.release(target))
+ }
+
+ /// `epoll_wait(self, events, timeout)`—Waits for registered events of
+ /// interest.
+ ///
+ /// For each event of interest, an element is written to `events`. On
+ /// success, this returns the number of written elements.
+ #[doc(alias = "epoll_wait")]
+ pub fn wait<'context>(
+ &'context self,
+ event_list: &mut EventVec<'context, Context>,
+ timeout: c::c_int,
+ ) -> io::Result<()> {
+ // Safety: We're calling `epoll_wait` via FFI and we know how it
+ // behaves.
+ unsafe {
+ event_list.events.set_len(0);
+ let nfds = ret_u32(c::epoll_wait(
+ self.epoll_fd.as_fd().as_raw_fd(),
+ event_list.events.as_mut_ptr().cast::<c::epoll_event>(),
+ event_list.events.capacity().try_into().unwrap_or(i32::MAX),
+ timeout,
+ ))?;
+ event_list.events.set_len(nfds as usize);
+ event_list.context = &self.context;
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+impl<'context, T: AsFd + IntoFd + FromFd> AsRawFd for Epoll<Owning<'context, T>> {
+ fn as_raw_fd(&self) -> RawFd {
+ self.epoll_fd.as_raw_fd()
+ }
+}
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+impl<'context, T: AsFd + IntoFd + FromFd> IntoRawFd for Epoll<Owning<'context, T>> {
+ fn into_raw_fd(self) -> RawFd {
+ self.epoll_fd.into_raw_fd()
+ }
+}
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+impl<'context, T: AsFd + IntoFd + FromFd> FromRawFd for Epoll<Owning<'context, T>> {
+ unsafe fn from_raw_fd(fd: RawFd) -> Self {
+ Self {
+ epoll_fd: OwnedFd::from_raw_fd(fd),
+ context: Owning::new(),
+ }
+ }
+}
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+impl<'context, T: AsFd + IntoFd + FromFd> AsFd for Epoll<Owning<'context, T>> {
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.epoll_fd.as_fd()
+ }
+}
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+impl<'context, T: AsFd + IntoFd + FromFd> From<Epoll<Owning<'context, T>>> for OwnedFd {
+ fn from(epoll: Epoll<Owning<'context, T>>) -> Self {
+ epoll.epoll_fd
+ }
+}
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+impl<'context, T: AsFd + IntoFd + FromFd> From<OwnedFd> for Epoll<Owning<'context, T>> {
+ fn from(fd: OwnedFd) -> Self {
+ Self {
+ epoll_fd: fd,
+ context: Owning::new(),
+ }
+ }
+}
+
+/// An iterator over the `Event`s in an `EventVec`.
+pub struct Iter<'context, Context: self::Context> {
+ iter: core::slice::Iter<'context, Event>,
+ context: *const Context,
+ _phantom: PhantomData<&'context Context>,
+}
+
+impl<'context, Context: self::Context> Iterator for Iter<'context, Context> {
+ type Item = (EventFlags, Ref<'context, Context::Target>);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // Safety: `self.context` is guaranteed to be valid because we hold
+ // `'context` for it. And we know this event is associated with this
+ // context because `wait` sets both.
+ self.iter.next().map(|event| {
+ (event.event_flags, unsafe {
+ (*self.context).decode(event.encoded)
+ })
+ })
+ }
+}
+
+/// A record of an event that occurred.
+#[repr(C)]
+#[cfg_attr(
+ any(
+ all(
+ target_arch = "x86",
+ not(target_env = "musl"),
+ not(target_os = "android"),
+ ),
+ target_arch = "x86_64",
+ ),
+ repr(packed)
+)]
+struct Event {
+ // Match the layout of `c::epoll_event`. We just use a `u64` instead of
+ // the full union; `Context` implementations will simply need to deal with
+ // casting the value into and out of the `u64` themselves.
+ event_flags: EventFlags,
+ encoded: u64,
+}
+
+/// A vector of `Event`s, plus context for interpreting them.
+pub struct EventVec<'context, Context: self::Context> {
+ events: Vec<Event>,
+ context: *const Context,
+ _phantom: PhantomData<&'context Context>,
+}
+
+impl<'context, Context: self::Context> EventVec<'context, Context> {
+ /// Constructs an `EventVec` with memory for `capacity` `Event`s.
+ #[inline]
+ pub fn with_capacity(capacity: usize) -> Self {
+ Self {
+ events: Vec::with_capacity(capacity),
+ context: null(),
+ _phantom: PhantomData,
+ }
+ }
+
+ /// Returns the current `Event` capacity of this `EventVec`.
+ #[inline]
+ pub fn capacity(&self) -> usize {
+ self.events.capacity()
+ }
+
+ /// Reserves enough memory for at least `additional` more `Event`s.
+ #[inline]
+ pub fn reserve(&mut self, additional: usize) {
+ self.events.reserve(additional);
+ }
+
+ /// Reserves enough memory for exactly `additional` more `Event`s.
+ #[inline]
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.events.reserve_exact(additional);
+ }
+
+ /// Clears all the `Events` out of this `EventVec`.
+ #[inline]
+ pub fn clear(&mut self) {
+ self.events.clear();
+ }
+
+ /// Shrinks the capacity of this `EventVec` as much as possible.
+ #[inline]
+ pub fn shrink_to_fit(&mut self) {
+ self.events.shrink_to_fit();
+ }
+
+ /// Returns an iterator over the `Event`s in this `EventVec`.
+ #[inline]
+ pub fn iter(&self) -> Iter<'_, Context> {
+ Iter {
+ iter: self.events.iter(),
+ context: self.context,
+ _phantom: PhantomData,
+ }
+ }
+
+ /// Returns the number of `Event`s logically contained in this `EventVec`.
+ #[inline]
+ pub fn len(&mut self) -> usize {
+ self.events.len()
+ }
+
+ /// Tests whether this `EventVec` is logically empty.
+ #[inline]
+ pub fn is_empty(&mut self) -> bool {
+ self.events.is_empty()
+ }
+}
+
+impl<'context, Context: self::Context> IntoIterator for &'context EventVec<'context, Context> {
+ type IntoIter = Iter<'context, Context>;
+ type Item = (EventFlags, Ref<'context, Context::Target>);
+
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/io/errno.rs b/vendor/rustix/src/imp/libc/io/errno.rs
new file mode 100644
index 000000000..470cf205c
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io/errno.rs
@@ -0,0 +1,997 @@
+//! The `rustix` `Errno` type.
+//!
+//! This type holds an OS error code, which conceptually corresponds to an
+//! `errno` value.
+
+use super::super::c;
+use libc_errno::errno;
+
+/// The error type for `rustix` APIs.
+///
+/// This is similar to `std::io::Error`, but only holds an OS error code,
+/// and no extra error value.
+#[repr(transparent)]
+#[doc(alias = "errno")]
+#[derive(Eq, PartialEq, Hash, Copy, Clone)]
+pub struct Errno(pub(crate) c::c_int);
+
+impl Errno {
+ /// `EACCES`
+ #[doc(alias = "ACCES")]
+ pub const ACCESS: Self = Self(c::EACCES);
+ /// `EADDRINUSE`
+ pub const ADDRINUSE: Self = Self(c::EADDRINUSE);
+ /// `EADDRNOTAVAIL`
+ pub const ADDRNOTAVAIL: Self = Self(c::EADDRNOTAVAIL);
+ /// `EADV`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const ADV: Self = Self(c::EADV);
+ /// `EAFNOSUPPORT`
+ pub const AFNOSUPPORT: Self = Self(c::EAFNOSUPPORT);
+ /// `EAGAIN`
+ pub const AGAIN: Self = Self(c::EAGAIN);
+ /// `EALREADY`
+ pub const ALREADY: Self = Self(c::EALREADY);
+ /// `EAUTH`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const AUTH: Self = Self(c::EAUTH);
+ /// `EBADE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const BADE: Self = Self(c::EBADE);
+ /// `EBADF`
+ pub const BADF: Self = Self(c::EBADF);
+ /// `EBADFD`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const BADFD: Self = Self(c::EBADFD);
+ /// `EBADMSG`
+ #[cfg(not(windows))]
+ pub const BADMSG: Self = Self(c::EBADMSG);
+ /// `EBADR`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const BADR: Self = Self(c::EBADR);
+ /// `EBADRPC`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const BADRPC: Self = Self(c::EBADRPC);
+ /// `EBADRQC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const BADRQC: Self = Self(c::EBADRQC);
+ /// `EBADSLT`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const BADSLT: Self = Self(c::EBADSLT);
+ /// `EBFONT`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const BFONT: Self = Self(c::EBFONT);
+ /// `EBUSY`
+ #[cfg(not(windows))]
+ pub const BUSY: Self = Self(c::EBUSY);
+ /// `ECANCELED`
+ pub const CANCELED: Self = Self(c::ECANCELED);
+ /// `ECAPMODE`
+ #[cfg(any(target_os = "freebsd"))]
+ pub const CAPMODE: Self = Self(c::ECAPMODE);
+ /// `ECHILD`
+ #[cfg(not(windows))]
+ pub const CHILD: Self = Self(c::ECHILD);
+ /// `ECHRNG`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const CHRNG: Self = Self(c::ECHRNG);
+ /// `ECOMM`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const COMM: Self = Self(c::ECOMM);
+ /// `ECONNABORTED`
+ pub const CONNABORTED: Self = Self(c::ECONNABORTED);
+ /// `ECONNREFUSED`
+ pub const CONNREFUSED: Self = Self(c::ECONNREFUSED);
+ /// `ECONNRESET`
+ pub const CONNRESET: Self = Self(c::ECONNRESET);
+ /// `EDEADLK`
+ #[cfg(not(windows))]
+ pub const DEADLK: Self = Self(c::EDEADLK);
+ /// `EDEADLOCK`
+ #[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const DEADLOCK: Self = Self(c::EDEADLOCK);
+ /// `EDESTADDRREQ`
+ pub const DESTADDRREQ: Self = Self(c::EDESTADDRREQ);
+ /// `EDISCON`
+ #[cfg(windows)]
+ pub const DISCON: Self = Self(c::EDISCON);
+ /// `EDOM`
+ #[cfg(not(windows))]
+ pub const DOM: Self = Self(c::EDOM);
+ /// `EDOOFUS`
+ #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+ pub const DOOFUS: Self = Self(c::EDOOFUS);
+ /// `EDOTDOT`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const DOTDOT: Self = Self(c::EDOTDOT);
+ /// `EDQUOT`
+ pub const DQUOT: Self = Self(c::EDQUOT);
+ /// `EEXIST`
+ #[cfg(not(windows))]
+ pub const EXIST: Self = Self(c::EEXIST);
+ /// `EFAULT`
+ pub const FAULT: Self = Self(c::EFAULT);
+ /// `EFBIG`
+ #[cfg(not(windows))]
+ pub const FBIG: Self = Self(c::EFBIG);
+ /// `EFTYPE`
+ #[cfg(any(
+ target_env = "newlib",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const FTYPE: Self = Self(c::EFTYPE);
+ /// `EHOSTDOWN`
+ #[cfg(not(target_os = "wasi"))]
+ pub const HOSTDOWN: Self = Self(c::EHOSTDOWN);
+ /// `EHOSTUNREACH`
+ pub const HOSTUNREACH: Self = Self(c::EHOSTUNREACH);
+ /// `EHWPOISON`
+ #[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+ )))]
+ pub const HWPOISON: Self = Self(c::EHWPOISON);
+ /// `EIDRM`
+ #[cfg(not(windows))]
+ pub const IDRM: Self = Self(c::EIDRM);
+ /// `EILSEQ`
+ #[cfg(not(windows))]
+ pub const ILSEQ: Self = Self(c::EILSEQ);
+ /// `EINPROGRESS`
+ pub const INPROGRESS: Self = Self(c::EINPROGRESS);
+ /// `EINTR`
+ ///
+ /// For a convenient way to retry system calls that exit with `INTR`, use
+ /// [`retry_on_intr`].
+ ///
+ /// [`retry_on_intr`]: crate::io::retry_on_intr
+ pub const INTR: Self = Self(c::EINTR);
+ /// `EINVAL`
+ pub const INVAL: Self = Self(c::EINVAL);
+ /// `EINVALIDPROCTABLE`
+ #[cfg(windows)]
+ pub const INVALIDPROCTABLE: Self = Self(c::EINVALIDPROCTABLE);
+ /// `EINVALIDPROVIDER`
+ #[cfg(windows)]
+ pub const INVALIDPROVIDER: Self = Self(c::EINVALIDPROVIDER);
+ /// `EIO`
+ #[cfg(not(windows))]
+ pub const IO: Self = Self(c::EIO);
+ /// `EISCONN`
+ pub const ISCONN: Self = Self(c::EISCONN);
+ /// `EISDIR`
+ #[cfg(not(windows))]
+ pub const ISDIR: Self = Self(c::EISDIR);
+ /// `EISNAM`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const ISNAM: Self = Self(c::EISNAM);
+ /// `EKEYEXPIRED`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const KEYEXPIRED: Self = Self(c::EKEYEXPIRED);
+ /// `EKEYREJECTED`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const KEYREJECTED: Self = Self(c::EKEYREJECTED);
+ /// `EKEYREVOKED`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const KEYREVOKED: Self = Self(c::EKEYREVOKED);
+ /// `EL2HLT`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const L2HLT: Self = Self(c::EL2HLT);
+ /// `EL2NSYNC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const L2NSYNC: Self = Self(c::EL2NSYNC);
+ /// `EL3HLT`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const L3HLT: Self = Self(c::EL3HLT);
+ /// `EL3RST`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const L3RST: Self = Self(c::EL3RST);
+ /// `ELIBACC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const LIBACC: Self = Self(c::ELIBACC);
+ /// `ELIBBAD`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const LIBBAD: Self = Self(c::ELIBBAD);
+ /// `ELIBEXEC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const LIBEXEC: Self = Self(c::ELIBEXEC);
+ /// `ELIBMAX`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const LIBMAX: Self = Self(c::ELIBMAX);
+ /// `ELIBSCN`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const LIBSCN: Self = Self(c::ELIBSCN);
+ /// `ELNRNG`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const LNRNG: Self = Self(c::ELNRNG);
+ /// `ELOOP`
+ pub const LOOP: Self = Self(c::ELOOP);
+ /// `EMEDIUMTYPE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const MEDIUMTYPE: Self = Self(c::EMEDIUMTYPE);
+ /// `EMFILE`
+ pub const MFILE: Self = Self(c::EMFILE);
+ /// `EMLINK`
+ #[cfg(not(windows))]
+ pub const MLINK: Self = Self(c::EMLINK);
+ /// `EMSGSIZE`
+ pub const MSGSIZE: Self = Self(c::EMSGSIZE);
+ /// `EMULTIHOP`
+ #[cfg(not(any(windows, target_os = "openbsd")))]
+ pub const MULTIHOP: Self = Self(c::EMULTIHOP);
+ /// `ENAMETOOLONG`
+ pub const NAMETOOLONG: Self = Self(c::ENAMETOOLONG);
+ /// `ENAVAIL`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NAVAIL: Self = Self(c::ENAVAIL);
+ /// `ENEEDAUTH`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const NEEDAUTH: Self = Self(c::ENEEDAUTH);
+ /// `ENETDOWN`
+ pub const NETDOWN: Self = Self(c::ENETDOWN);
+ /// `ENETRESET`
+ pub const NETRESET: Self = Self(c::ENETRESET);
+ /// `ENETUNREACH`
+ pub const NETUNREACH: Self = Self(c::ENETUNREACH);
+ /// `ENFILE`
+ #[cfg(not(windows))]
+ pub const NFILE: Self = Self(c::ENFILE);
+ /// `ENOANO`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOANO: Self = Self(c::ENOANO);
+ /// `ENOATTR`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const NOATTR: Self = Self(c::ENOATTR);
+ /// `ENOBUFS`
+ pub const NOBUFS: Self = Self(c::ENOBUFS);
+ /// `ENOCSI`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOCSI: Self = Self(c::ENOCSI);
+ /// `ENODATA`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NODATA: Self = Self(c::ENODATA);
+ /// `ENODEV`
+ #[cfg(not(windows))]
+ pub const NODEV: Self = Self(c::ENODEV);
+ /// `ENOENT`
+ #[cfg(not(windows))]
+ pub const NOENT: Self = Self(c::ENOENT);
+ /// `ENOEXEC`
+ #[cfg(not(windows))]
+ pub const NOEXEC: Self = Self(c::ENOEXEC);
+ /// `ENOKEY`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOKEY: Self = Self(c::ENOKEY);
+ /// `ENOLCK`
+ #[cfg(not(windows))]
+ pub const NOLCK: Self = Self(c::ENOLCK);
+ /// `ENOLINK`
+ #[cfg(not(any(windows, target_os = "openbsd")))]
+ pub const NOLINK: Self = Self(c::ENOLINK);
+ /// `ENOMEDIUM`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOMEDIUM: Self = Self(c::ENOMEDIUM);
+ /// `ENOMEM`
+ #[cfg(not(windows))]
+ pub const NOMEM: Self = Self(c::ENOMEM);
+ /// `ENOMORE`
+ #[cfg(windows)]
+ pub const NOMORE: Self = Self(c::ENOMORE);
+ /// `ENOMSG`
+ #[cfg(not(windows))]
+ pub const NOMSG: Self = Self(c::ENOMSG);
+ /// `ENONET`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NONET: Self = Self(c::ENONET);
+ /// `ENOPKG`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOPKG: Self = Self(c::ENOPKG);
+ /// `ENOPROTOOPT`
+ pub const NOPROTOOPT: Self = Self(c::ENOPROTOOPT);
+ /// `ENOSPC`
+ #[cfg(not(windows))]
+ pub const NOSPC: Self = Self(c::ENOSPC);
+ /// `ENOSR`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOSR: Self = Self(c::ENOSR);
+ /// `ENOSTR`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOSTR: Self = Self(c::ENOSTR);
+ /// `ENOSYS`
+ #[cfg(not(windows))]
+ pub const NOSYS: Self = Self(c::ENOSYS);
+ /// `ENOTBLK`
+ #[cfg(not(any(windows, target_os = "wasi")))]
+ pub const NOTBLK: Self = Self(c::ENOTBLK);
+ /// `ENOTCAPABLE`
+ #[cfg(any(target_os = "freebsd", target_os = "wasi"))]
+ pub const NOTCAPABLE: Self = Self(c::ENOTCAPABLE);
+ /// `ENOTCONN`
+ pub const NOTCONN: Self = Self(c::ENOTCONN);
+ /// `ENOTDIR`
+ #[cfg(not(windows))]
+ pub const NOTDIR: Self = Self(c::ENOTDIR);
+ /// `ENOTEMPTY`
+ pub const NOTEMPTY: Self = Self(c::ENOTEMPTY);
+ /// `ENOTNAM`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOTNAM: Self = Self(c::ENOTNAM);
+ /// `ENOTRECOVERABLE`
+ #[cfg(not(any(windows, target_os = "dragonfly", target_os = "netbsd")))]
+ pub const NOTRECOVERABLE: Self = Self(c::ENOTRECOVERABLE);
+ /// `ENOTSOCK`
+ pub const NOTSOCK: Self = Self(c::ENOTSOCK);
+ /// `ENOTSUP`
+ #[cfg(not(any(windows, target_os = "redox")))]
+ pub const NOTSUP: Self = Self(c::ENOTSUP);
+ /// `ENOTTY`
+ #[cfg(not(windows))]
+ pub const NOTTY: Self = Self(c::ENOTTY);
+ /// `ENOTUNIQ`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const NOTUNIQ: Self = Self(c::ENOTUNIQ);
+ /// `ENXIO`
+ #[cfg(not(windows))]
+ pub const NXIO: Self = Self(c::ENXIO);
+ /// `EOPNOTSUPP`
+ pub const OPNOTSUPP: Self = Self(c::EOPNOTSUPP);
+ /// `EOVERFLOW`
+ #[cfg(not(windows))]
+ pub const OVERFLOW: Self = Self(c::EOVERFLOW);
+ /// `EOWNERDEAD`
+ #[cfg(not(any(windows, target_os = "dragonfly", target_os = "netbsd")))]
+ pub const OWNERDEAD: Self = Self(c::EOWNERDEAD);
+ /// `EPERM`
+ #[cfg(not(windows))]
+ pub const PERM: Self = Self(c::EPERM);
+ /// `EPFNOSUPPORT`
+ #[cfg(not(target_os = "wasi"))]
+ pub const PFNOSUPPORT: Self = Self(c::EPFNOSUPPORT);
+ /// `EPIPE`
+ #[cfg(not(windows))]
+ pub const PIPE: Self = Self(c::EPIPE);
+ /// `EPROCLIM`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const PROCLIM: Self = Self(c::EPROCLIM);
+ /// `EPROCUNAVAIL`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const PROCUNAVAIL: Self = Self(c::EPROCUNAVAIL);
+ /// `EPROGMISMATCH`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const PROGMISMATCH: Self = Self(c::EPROGMISMATCH);
+ /// `EPROGUNAVAIL`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const PROGUNAVAIL: Self = Self(c::EPROGUNAVAIL);
+ /// `EPROTO`
+ #[cfg(not(windows))]
+ pub const PROTO: Self = Self(c::EPROTO);
+ /// `EPROTONOSUPPORT`
+ pub const PROTONOSUPPORT: Self = Self(c::EPROTONOSUPPORT);
+ /// `EPROTOTYPE`
+ pub const PROTOTYPE: Self = Self(c::EPROTOTYPE);
+ /// `EPROVIDERFAILEDINIT`
+ #[cfg(windows)]
+ pub const PROVIDERFAILEDINIT: Self = Self(c::EPROVIDERFAILEDINIT);
+ /// `ERANGE`
+ #[cfg(not(windows))]
+ pub const RANGE: Self = Self(c::ERANGE);
+ /// `EREFUSED`
+ #[cfg(windows)]
+ pub const REFUSED: Self = Self(c::EREFUSED);
+ /// `EREMCHG`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const REMCHG: Self = Self(c::EREMCHG);
+ /// `EREMOTE`
+ #[cfg(not(target_os = "wasi"))]
+ pub const REMOTE: Self = Self(c::EREMOTE);
+ /// `EREMOTEIO`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const REMOTEIO: Self = Self(c::EREMOTEIO);
+ /// `ERESTART`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const RESTART: Self = Self(c::ERESTART);
+ /// `ERFKILL`
+ #[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+ )))]
+ pub const RFKILL: Self = Self(c::ERFKILL);
+ /// `EROFS`
+ #[cfg(not(windows))]
+ pub const ROFS: Self = Self(c::EROFS);
+ /// `ERPCMISMATCH`
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ pub const RPCMISMATCH: Self = Self(c::ERPCMISMATCH);
+ /// `ESHUTDOWN`
+ #[cfg(not(target_os = "wasi"))]
+ pub const SHUTDOWN: Self = Self(c::ESHUTDOWN);
+ /// `ESOCKTNOSUPPORT`
+ #[cfg(not(target_os = "wasi"))]
+ pub const SOCKTNOSUPPORT: Self = Self(c::ESOCKTNOSUPPORT);
+ /// `ESPIPE`
+ #[cfg(not(windows))]
+ pub const SPIPE: Self = Self(c::ESPIPE);
+ /// `ESRCH`
+ #[cfg(not(windows))]
+ pub const SRCH: Self = Self(c::ESRCH);
+ /// `ESRMNT`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const SRMNT: Self = Self(c::ESRMNT);
+ /// `ESTALE`
+ pub const STALE: Self = Self(c::ESTALE);
+ /// `ESTRPIPE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const STRPIPE: Self = Self(c::ESTRPIPE);
+ /// `ETIME`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const TIME: Self = Self(c::ETIME);
+ /// `ETIMEDOUT`
+ pub const TIMEDOUT: Self = Self(c::ETIMEDOUT);
+ /// `E2BIG`
+ #[cfg(not(windows))]
+ #[doc(alias = "2BIG")]
+ pub const TOOBIG: Self = Self(c::E2BIG);
+ /// `ETOOMANYREFS`
+ #[cfg(not(target_os = "wasi"))]
+ pub const TOOMANYREFS: Self = Self(c::ETOOMANYREFS);
+ /// `ETXTBSY`
+ #[cfg(not(windows))]
+ pub const TXTBSY: Self = Self(c::ETXTBSY);
+ /// `EUCLEAN`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const UCLEAN: Self = Self(c::EUCLEAN);
+ /// `EUNATCH`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const UNATCH: Self = Self(c::EUNATCH);
+ /// `EUSERS`
+ #[cfg(not(target_os = "wasi"))]
+ pub const USERS: Self = Self(c::EUSERS);
+ /// `EWOULDBLOCK`
+ pub const WOULDBLOCK: Self = Self(c::EWOULDBLOCK);
+ /// `EXDEV`
+ #[cfg(not(windows))]
+ pub const XDEV: Self = Self(c::EXDEV);
+ /// `EXFULL`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "wasi",
+ )))]
+ pub const XFULL: Self = Self(c::EXFULL);
+}
+
+impl Errno {
+ /// Extract an `Errno` value from a `std::io::Error`.
+ ///
+ /// This isn't a `From` conversion because it's expected to be relatively
+ /// uncommon.
+ #[cfg(feature = "std")]
+ #[inline]
+ pub fn from_io_error(io_err: &std::io::Error) -> Option<Self> {
+ io_err
+ .raw_os_error()
+ .and_then(|raw| if raw != 0 { Some(Self(raw)) } else { None })
+ }
+
+ /// Extract the raw OS error number from this error.
+ #[inline]
+ pub const fn raw_os_error(self) -> i32 {
+ self.0
+ }
+
+ /// Construct an `Errno` from a raw OS error number.
+ #[inline]
+ pub const fn from_raw_os_error(raw: i32) -> Self {
+ Self(raw)
+ }
+
+ pub(crate) fn last_os_error() -> Self {
+ Self(errno().0)
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/io/io_slice.rs b/vendor/rustix/src/imp/libc/io/io_slice.rs
new file mode 100644
index 000000000..81c504d25
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io/io_slice.rs
@@ -0,0 +1,85 @@
+//! The following is derived from Rust's
+//! library/std/src/sys/unix/io.rs
+//! dca3f1b786efd27be3b325ed1e01e247aa589c3b.
+
+use super::super::c;
+use core::marker::PhantomData;
+use core::slice;
+
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub struct IoSlice<'a> {
+ vec: c::iovec,
+ _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+ #[inline]
+ pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+ IoSlice {
+ vec: c::iovec {
+ iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void,
+ iov_len: buf.len(),
+ },
+ _p: PhantomData,
+ }
+ }
+
+ #[inline]
+ pub fn advance(&mut self, n: usize) {
+ if self.vec.iov_len < n {
+ panic!("advancing IoSlice beyond its length");
+ }
+
+ unsafe {
+ self.vec.iov_len -= n;
+ self.vec.iov_base = self.vec.iov_base.add(n);
+ }
+ }
+
+ #[inline]
+ pub fn as_slice(&self) -> &[u8] {
+ unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+ }
+}
+
+#[repr(transparent)]
+pub struct IoSliceMut<'a> {
+ vec: c::iovec,
+ _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+ #[inline]
+ pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+ IoSliceMut {
+ vec: c::iovec {
+ iov_base: buf.as_mut_ptr() as *mut c::c_void,
+ iov_len: buf.len(),
+ },
+ _p: PhantomData,
+ }
+ }
+
+ #[inline]
+ pub fn advance(&mut self, n: usize) {
+ if self.vec.iov_len < n {
+ panic!("advancing IoSliceMut beyond its length");
+ }
+
+ unsafe {
+ self.vec.iov_len -= n;
+ self.vec.iov_base = self.vec.iov_base.add(n);
+ }
+ }
+
+ #[inline]
+ pub fn as_slice(&self) -> &[u8] {
+ unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+ }
+
+ #[inline]
+ pub fn as_mut_slice(&mut self) -> &mut [u8] {
+ unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/io/mod.rs b/vendor/rustix/src/imp/libc/io/mod.rs
new file mode 100644
index 000000000..1378adf3d
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io/mod.rs
@@ -0,0 +1,13 @@
+pub(crate) mod errno;
+#[cfg(not(windows))]
+#[cfg(not(feature = "std"))]
+pub(crate) mod io_slice;
+pub(crate) mod poll_fd;
+#[cfg(not(windows))]
+pub(crate) mod types;
+
+#[cfg_attr(windows, path = "windows_syscalls.rs")]
+pub(crate) mod syscalls;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub mod epoll;
diff --git a/vendor/rustix/src/imp/libc/io/poll_fd.rs b/vendor/rustix/src/imp/libc/io/poll_fd.rs
new file mode 100644
index 000000000..c516a9309
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io/poll_fd.rs
@@ -0,0 +1,136 @@
+use super::super::c;
+use super::super::conv::borrowed_fd;
+#[cfg(windows)]
+use super::super::fd::RawFd;
+use super::super::fd::{AsFd, AsRawFd, BorrowedFd, LibcFd};
+use bitflags::bitflags;
+use core::marker::PhantomData;
+#[cfg(windows)]
+use std::fmt;
+
+bitflags! {
+ /// `POLL*` flags for use with [`poll`].
+ ///
+ /// [`poll`]: crate::io::poll
+ pub struct PollFlags: c::c_short {
+ /// `POLLIN`
+ const IN = c::POLLIN;
+ /// `POLLPRI`
+ #[cfg(not(target_os = "wasi"))]
+ const PRI = c::POLLPRI;
+ /// `POLLOUT`
+ const OUT = c::POLLOUT;
+ /// `POLLRDNORM`
+ #[cfg(not(target_os = "redox"))]
+ const RDNORM = c::POLLRDNORM;
+ /// `POLLWRNORM`
+ #[cfg(not(target_os = "redox"))]
+ const WRNORM = c::POLLWRNORM;
+ /// `POLLRDBAND`
+ #[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+ const RDBAND = c::POLLRDBAND;
+ /// `POLLWRBAND`
+ #[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+ const WRBAND = c::POLLWRBAND;
+ /// `POLLERR`
+ const ERR = c::POLLERR;
+ /// `POLLHUP`
+ const HUP = c::POLLHUP;
+ /// `POLLNVAL`
+ const NVAL = c::POLLNVAL;
+ /// `POLLRDHUP`
+ #[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ not(any(target_arch = "sparc", target_arch = "sparc64"))),
+ )]
+ const RDHUP = c::POLLRDHUP;
+ }
+}
+
+/// `struct pollfd`—File descriptor and flags for use with [`poll`].
+///
+/// [`poll`]: crate::io::poll
+#[doc(alias = "pollfd")]
+#[derive(Clone)]
+#[cfg_attr(not(windows), derive(Debug))]
+#[repr(transparent)]
+pub struct PollFd<'fd> {
+ pollfd: c::pollfd,
+ _phantom: PhantomData<BorrowedFd<'fd>>,
+}
+
+#[cfg(windows)]
+impl<'fd> fmt::Debug for PollFd<'fd> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt.debug_struct("pollfd")
+ .field("fd", &self.pollfd.fd)
+ .field("events", &self.pollfd.events)
+ .field("revents", &self.pollfd.revents)
+ .finish()
+ }
+}
+
+impl<'fd> PollFd<'fd> {
+ /// Constructs a new `PollFd` holding `fd` and `events`.
+ #[inline]
+ pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> Self {
+ Self::from_borrowed_fd(fd.as_fd(), events)
+ }
+
+ /// Sets the contained file descriptor to `fd`.
+ #[inline]
+ pub fn set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd) {
+ self.pollfd.fd = fd.as_fd().as_raw_fd() as LibcFd;
+ }
+
+ /// Clears the ready events.
+ #[inline]
+ pub fn clear_revents(&mut self) {
+ self.pollfd.revents = 0;
+ }
+
+ /// Constructs a new `PollFd` holding `fd` and `events`.
+ ///
+ /// This is the same as `new`, but can be used to avoid borrowing the
+ /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd`
+ /// is a temporary.
+ #[inline]
+ pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self {
+ Self {
+ pollfd: c::pollfd {
+ fd: borrowed_fd(fd),
+ events: events.bits(),
+ revents: 0,
+ },
+ _phantom: PhantomData,
+ }
+ }
+
+ /// Returns the ready events.
+ #[inline]
+ pub fn revents(&self) -> PollFlags {
+ // Use `unwrap()` here because in theory we know we know all the bits
+ // the OS might set here, but OS's have added extensions in the past.
+ PollFlags::from_bits(self.pollfd.revents).unwrap()
+ }
+}
+
+#[cfg(not(windows))]
+impl<'fd> AsFd for PollFd<'fd> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ // Safety: Our constructors and `set_fd` require `pollfd.fd` to be
+ // valid for the `fd lifetime.
+ unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) }
+ }
+}
+
+#[cfg(windows)]
+impl<'fd> io_lifetimes::AsSocket for PollFd<'fd> {
+ #[inline]
+ fn as_socket(&self) -> BorrowedFd<'_> {
+ // Safety: Our constructors and `set_fd` require `pollfd.fd` to be
+ // valid for the `fd lifetime.
+ unsafe { BorrowedFd::borrow_raw(self.pollfd.fd as RawFd) }
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/io/syscalls.rs b/vendor/rustix/src/imp/libc/io/syscalls.rs
new file mode 100644
index 000000000..4fafbfd66
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io/syscalls.rs
@@ -0,0 +1,456 @@
+//! libc syscalls supporting `rustix::io`.
+
+use super::super::c;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use super::super::conv::syscall_ret_owned_fd;
+use super::super::conv::{
+ borrowed_fd, ret, ret_c_int, ret_discarded_fd, ret_owned_fd, ret_ssize_t,
+};
+use super::super::offset::{libc_pread, libc_pwrite};
+#[cfg(not(target_os = "redox"))]
+use super::super::offset::{libc_preadv, libc_pwritev};
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+use super::super::offset::{libc_preadv2, libc_pwritev2};
+use crate::fd::{AsFd, BorrowedFd, RawFd};
+#[cfg(not(target_os = "wasi"))]
+use crate::io::DupFlags;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
+use crate::io::PipeFlags;
+use crate::io::{self, IoSlice, IoSliceMut, OwnedFd, PollFd};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::io::{EventfdFlags, ReadWriteFlags};
+use core::cmp::min;
+use core::convert::TryInto;
+use core::mem::MaybeUninit;
+#[cfg(feature = "net")]
+use libc_errno::errno;
+
+pub(crate) fn read(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize> {
+ let nread = unsafe {
+ ret_ssize_t(c::read(
+ borrowed_fd(fd),
+ buf.as_mut_ptr().cast(),
+ min(buf.len(), READ_LIMIT),
+ ))?
+ };
+ Ok(nread as usize)
+}
+
+pub(crate) fn write(fd: BorrowedFd<'_>, buf: &[u8]) -> io::Result<usize> {
+ let nwritten = unsafe {
+ ret_ssize_t(c::write(
+ borrowed_fd(fd),
+ buf.as_ptr().cast(),
+ min(buf.len(), READ_LIMIT),
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+ let len = min(buf.len(), READ_LIMIT);
+
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ let offset = offset as i64;
+
+ let nread = unsafe {
+ ret_ssize_t(libc_pread(
+ borrowed_fd(fd),
+ buf.as_mut_ptr().cast(),
+ len,
+ offset,
+ ))?
+ };
+ Ok(nread as usize)
+}
+
+pub(crate) fn pwrite(fd: BorrowedFd<'_>, buf: &[u8], offset: u64) -> io::Result<usize> {
+ let len = min(buf.len(), READ_LIMIT);
+
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ let offset = offset as i64;
+
+ let nwritten = unsafe {
+ ret_ssize_t(libc_pwrite(
+ borrowed_fd(fd),
+ buf.as_ptr().cast(),
+ len,
+ offset,
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
+ let nread = unsafe {
+ ret_ssize_t(c::readv(
+ borrowed_fd(fd),
+ bufs.as_ptr().cast::<c::iovec>(),
+ min(bufs.len(), max_iov()) as c::c_int,
+ ))?
+ };
+ Ok(nread as usize)
+}
+
+pub(crate) fn writev(fd: BorrowedFd<'_>, bufs: &[IoSlice]) -> io::Result<usize> {
+ let nwritten = unsafe {
+ ret_ssize_t(c::writev(
+ borrowed_fd(fd),
+ bufs.as_ptr().cast::<c::iovec>(),
+ min(bufs.len(), max_iov()) as c::c_int,
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn preadv(
+ fd: BorrowedFd<'_>,
+ bufs: &mut [IoSliceMut],
+ offset: u64,
+) -> io::Result<usize> {
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ let offset = offset as i64;
+ let nread = unsafe {
+ ret_ssize_t(libc_preadv(
+ borrowed_fd(fd),
+ bufs.as_ptr().cast::<c::iovec>(),
+ min(bufs.len(), max_iov()) as c::c_int,
+ offset,
+ ))?
+ };
+ Ok(nread as usize)
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn pwritev(fd: BorrowedFd<'_>, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ let offset = offset as i64;
+ let nwritten = unsafe {
+ ret_ssize_t(libc_pwritev(
+ borrowed_fd(fd),
+ bufs.as_ptr().cast::<c::iovec>(),
+ min(bufs.len(), max_iov()) as c::c_int,
+ offset,
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+pub(crate) fn preadv2(
+ fd: BorrowedFd<'_>,
+ bufs: &mut [IoSliceMut],
+ offset: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ let offset = offset as i64;
+ let nread = unsafe {
+ ret_ssize_t(libc_preadv2(
+ borrowed_fd(fd),
+ bufs.as_ptr().cast::<c::iovec>(),
+ min(bufs.len(), max_iov()) as c::c_int,
+ offset,
+ flags.bits(),
+ ))?
+ };
+ Ok(nread as usize)
+}
+
+/// At present, `libc` only has `preadv2` defined for glibc. On other
+/// ABIs, `ReadWriteFlags` has no flags defined, and we use plain `preadv`.
+#[cfg(any(
+ target_os = "android",
+ all(target_os = "linux", not(target_env = "gnu")),
+))]
+#[inline]
+pub(crate) fn preadv2(
+ fd: BorrowedFd<'_>,
+ bufs: &mut [IoSliceMut],
+ offset: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ assert!(flags.is_empty());
+ preadv(fd, bufs, offset)
+}
+
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+pub(crate) fn pwritev2(
+ fd: BorrowedFd<'_>,
+ bufs: &[IoSlice],
+ offset: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ let offset = offset as i64;
+ let nwritten = unsafe {
+ ret_ssize_t(libc_pwritev2(
+ borrowed_fd(fd),
+ bufs.as_ptr().cast::<c::iovec>(),
+ min(bufs.len(), max_iov()) as c::c_int,
+ offset,
+ flags.bits(),
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+/// At present, `libc` only has `pwritev2` defined for glibc. On other
+/// ABIs, `ReadWriteFlags` has no flags defined, and we use plain `pwritev`.
+#[cfg(any(
+ target_os = "android",
+ all(target_os = "linux", not(target_env = "gnu")),
+))]
+#[inline]
+pub(crate) fn pwritev2(
+ fd: BorrowedFd<'_>,
+ bufs: &[IoSlice],
+ offset: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ assert!(flags.is_empty());
+ pwritev(fd, bufs, offset)
+}
+
+// These functions are derived from Rust's library/std/src/sys/unix/fd.rs at
+// revision a77da2d454e6caa227a85b16410b95f93495e7e0.
+
+// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, with the
+// man page quoting that if the count of bytes to read is greater than
+// `SSIZE_MAX` the result is "unspecified".
+//
+// On macOS, however, apparently the 64-bit libc is either buggy or
+// intentionally showing odd behavior by rejecting any read with a size larger
+// than or equal to `INT_MAX`. To handle both of these the read size is capped
+// on both platforms.
+#[cfg(target_os = "macos")]
+const READ_LIMIT: usize = c::c_int::MAX as usize - 1;
+#[cfg(not(target_os = "macos"))]
+const READ_LIMIT: usize = c::ssize_t::MAX as usize;
+
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+))]
+const fn max_iov() -> usize {
+ c::IOV_MAX as usize
+}
+
+#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
+const fn max_iov() -> usize {
+ c::UIO_MAXIOV as usize
+}
+
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+const fn max_iov() -> usize {
+ 16 // The minimum value required by POSIX.
+}
+
+pub(crate) unsafe fn close(raw_fd: RawFd) {
+ let _ = c::close(raw_fd as c::c_int);
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
+ unsafe { syscall_ret_owned_fd(c::syscall(c::SYS_eventfd2, initval, flags.bits())) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub(crate) fn ioctl_blksszget(fd: BorrowedFd) -> io::Result<u32> {
+ let mut result = MaybeUninit::<c::c_uint>::uninit();
+ unsafe {
+ ret(c::ioctl(borrowed_fd(fd), c::BLKSSZGET, result.as_mut_ptr()))?;
+ Ok(result.assume_init() as u32)
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result<u32> {
+ let mut result = MaybeUninit::<c::c_uint>::uninit();
+ unsafe {
+ ret(c::ioctl(
+ borrowed_fd(fd),
+ c::BLKPBSZGET,
+ result.as_mut_ptr(),
+ ))?;
+ Ok(result.assume_init() as u32)
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn ioctl_fionread(fd: BorrowedFd<'_>) -> io::Result<u64> {
+ let mut nread = MaybeUninit::<c::c_int>::uninit();
+ unsafe {
+ ret(c::ioctl(borrowed_fd(fd), c::FIONREAD, nread.as_mut_ptr()))?;
+ // `FIONREAD` returns the number of bytes silently casted to a `c_int`,
+ // even when this is lossy. The best we can do is convert it back to a
+ // `u64` without sign-extending it back first.
+ Ok(u64::from(nread.assume_init() as c::c_uint))
+ }
+}
+
+pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ unsafe {
+ let data = value as c::c_int;
+ ret(c::ioctl(borrowed_fd(fd), c::FIONBIO, &data))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[cfg(feature = "net")]
+pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
+ let (mut read, mut write) = crate::fs::fd::_is_file_read_write(fd)?;
+ let mut not_socket = false;
+ if read {
+ // Do a `recv` with `PEEK` and `DONTWAIT` for 1 byte. A 0 indicates
+ // the read side is shut down; an `EWOULDBLOCK` indicates the read
+ // side is still open.
+ match unsafe {
+ c::recv(
+ borrowed_fd(fd),
+ MaybeUninit::<[u8; 1]>::uninit()
+ .as_mut_ptr()
+ .cast::<c::c_void>(),
+ 1,
+ c::MSG_PEEK | c::MSG_DONTWAIT,
+ )
+ } {
+ 0 => read = false,
+ -1 => {
+ #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK`
+ match errno().0 {
+ c::EAGAIN | c::EWOULDBLOCK => (),
+ c::ENOTSOCK => not_socket = true,
+ err => return Err(io::Errno(err)),
+ }
+ }
+ _ => (),
+ }
+ }
+ if write && !not_socket {
+ // Do a `send` with `DONTWAIT` for 0 bytes. An `EPIPE` indicates
+ // the write side is shut down.
+ if unsafe { c::send(borrowed_fd(fd), [].as_ptr(), 0, c::MSG_DONTWAIT) } == -1 {
+ #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK`
+ match errno().0 {
+ c::EAGAIN | c::EWOULDBLOCK => (),
+ c::ENOTSOCK => (),
+ c::EPIPE => write = false,
+ err => return Err(io::Errno(err)),
+ }
+ }
+ }
+ Ok((read, write))
+}
+
+#[cfg(target_os = "wasi")]
+#[cfg(feature = "net")]
+pub(crate) fn is_read_write(_fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
+ todo!("Implement is_read_write for WASI in terms of fd_fdstat_get");
+}
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) fn dup(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(c::dup(borrowed_fd(fd))) }
+}
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) fn dup2(fd: BorrowedFd<'_>, new: &mut OwnedFd) -> io::Result<()> {
+ unsafe { ret_discarded_fd(c::dup2(borrowed_fd(fd), borrowed_fd(new.as_fd()))) }
+}
+
+#[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()> {
+ unsafe {
+ ret_discarded_fd(c::dup3(
+ borrowed_fd(fd),
+ borrowed_fd(new.as_fd()),
+ flags.bits(),
+ ))
+ }
+}
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+))]
+pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, _flags: DupFlags) -> io::Result<()> {
+ // Android 5.0 has `dup3`, but libc doesn't have bindings. Emulate it
+ // using `dup2`. We don't need to worry about the difference between
+ // `dup2` and `dup3` when the file descriptors are equal because we
+ // have an `&mut OwnedFd` which means `fd` doesn't alias it.
+ dup2(fd, new)
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(crate) fn ioctl_fioclex(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(c::ioctl(borrowed_fd(fd), c::FIOCLEX)) }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn ioctl_tiocexcl(fd: BorrowedFd) -> io::Result<()> {
+ unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCEXCL as _)) }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd) -> io::Result<()> {
+ unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCNXCL as _)) }
+}
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> {
+ unsafe {
+ let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(c::pipe(result.as_mut_ptr().cast::<i32>()))?;
+ let [p0, p1] = result.assume_init();
+ Ok((p0, p1))
+ }
+}
+
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
+pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> {
+ unsafe {
+ let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(c::pipe2(result.as_mut_ptr().cast::<i32>(), flags.bits()))?;
+ let [p0, p1] = result.assume_init();
+ Ok((p0, p1))
+ }
+}
+
+#[inline]
+pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
+ let nfds = fds
+ .len()
+ .try_into()
+ .map_err(|_convert_err| io::Errno::INVAL)?;
+
+ ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) })
+ .map(|nready| nready as usize)
+}
diff --git a/vendor/rustix/src/imp/libc/io/types.rs b/vendor/rustix/src/imp/libc/io/types.rs
new file mode 100644
index 000000000..483f3a6af
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io/types.rs
@@ -0,0 +1,89 @@
+use super::super::c;
+#[cfg(not(target_os = "wasi"))]
+use bitflags::bitflags;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `RWF_*` constants for use with [`preadv2`] and [`pwritev2`].
+ ///
+ /// [`preadv2`]: crate::io::preadv2
+ /// [`pwritev2`]: crate::io::pwritev
+ pub struct ReadWriteFlags: c::c_int {
+ /// `RWF_DSYNC` (since Linux 4.7)
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ const DSYNC = c::RWF_DSYNC;
+ /// `RWF_HIPRI` (since Linux 4.6)
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ const HIPRI = c::RWF_HIPRI;
+ /// `RWF_SYNC` (since Linux 4.7)
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ const SYNC = c::RWF_SYNC;
+ /// `RWF_NOWAIT` (since Linux 4.14)
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ const NOWAIT = c::RWF_NOWAIT;
+ /// `RWF_APPEND` (since Linux 4.16)
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ const APPEND = c::RWF_APPEND;
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+bitflags! {
+ /// `O_*` constants for use with [`dup2`].
+ ///
+ /// [`dup2`]: crate::io::dup2
+ pub struct DupFlags: c::c_int {
+ /// `O_CLOEXEC`
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ )))] // Android 5.0 has dup3, but libc doesn't have bindings
+ const CLOEXEC = c::O_CLOEXEC;
+ }
+}
+
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
+bitflags! {
+ /// `O_*` constants for use with [`pipe_with`].
+ ///
+ /// [`pipe_with`]: crate::io::pipe_with
+ pub struct PipeFlags: c::c_int {
+ /// `O_CLOEXEC`
+ const CLOEXEC = c::O_CLOEXEC;
+ /// `O_DIRECT`
+ #[cfg(not(any(target_os = "illumos", target_os = "openbsd", target_os = "redox")))]
+ const DIRECT = c::O_DIRECT;
+ /// `O_NONBLOCK`
+ const NONBLOCK = c::O_NONBLOCK;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `EFD_*` flags for use with [`eventfd`].
+ ///
+ /// [`eventfd`]: crate::io::eventfd
+ pub struct EventfdFlags: c::c_int {
+ /// `EFD_CLOEXEC`
+ const CLOEXEC = c::EFD_CLOEXEC;
+ /// `EFD_NONBLOCK`
+ const NONBLOCK = c::EFD_NONBLOCK;
+ /// `EFD_SEMAPHORE`
+ const SEMAPHORE = c::EFD_SEMAPHORE;
+ }
+}
+
+/// `PIPE_BUF`—The maximum size of a write to a pipe guaranteed to be atomic.
+#[cfg(not(any(target_os = "illumos", target_os = "redox", target_os = "wasi")))]
+pub const PIPE_BUF: usize = c::PIPE_BUF;
+
+#[cfg(not(any(windows, target_os = "redox")))]
+pub(crate) const AT_FDCWD: c::c_int = c::AT_FDCWD;
+#[cfg(not(windows))]
+pub(crate) const STDIN_FILENO: c::c_int = c::STDIN_FILENO;
+#[cfg(not(windows))]
+pub(crate) const STDOUT_FILENO: c::c_int = c::STDOUT_FILENO;
+#[cfg(not(windows))]
+pub(crate) const STDERR_FILENO: c::c_int = c::STDERR_FILENO;
diff --git a/vendor/rustix/src/imp/libc/io/windows_syscalls.rs b/vendor/rustix/src/imp/libc/io/windows_syscalls.rs
new file mode 100644
index 000000000..4c6e86f94
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io/windows_syscalls.rs
@@ -0,0 +1,39 @@
+//! Windows system calls in the `io` module.
+
+use super::super::c;
+use super::super::conv::{borrowed_fd, ret, ret_c_int};
+use super::super::fd::LibcFd;
+use crate::fd::{BorrowedFd, RawFd};
+use crate::io;
+use crate::io::PollFd;
+use core::convert::TryInto;
+use core::mem::MaybeUninit;
+
+pub(crate) unsafe fn close(raw_fd: RawFd) {
+ let _ = c::close(raw_fd as LibcFd);
+}
+
+pub(crate) fn ioctl_fionread(fd: BorrowedFd<'_>) -> io::Result<u64> {
+ let mut nread = MaybeUninit::<c::c_ulong>::uninit();
+ unsafe {
+ ret(c::ioctl(borrowed_fd(fd), c::FIONREAD, nread.as_mut_ptr()))?;
+ Ok(u64::from(nread.assume_init()))
+ }
+}
+
+pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ unsafe {
+ let mut data = value as c::c_uint;
+ ret(c::ioctl(borrowed_fd(fd), c::FIONBIO, &mut data))
+ }
+}
+
+pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
+ let nfds = fds
+ .len()
+ .try_into()
+ .map_err(|_convert_err| io::Errno::INVAL)?;
+
+ ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) })
+ .map(|nready| nready as usize)
+}
diff --git a/vendor/rustix/src/imp/libc/io_lifetimes.rs b/vendor/rustix/src/imp/libc/io_lifetimes.rs
new file mode 100644
index 000000000..b0b14b7c8
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io_lifetimes.rs
@@ -0,0 +1,109 @@
+//! `io_lifetimes` types for Windows assuming that Fd is Socket.
+//!
+//! We can make this assumption since `rustix` supports only `rustix::net` on
+//! Windows.
+
+pub use io_lifetimes::{BorrowedSocket as BorrowedFd, OwnedSocket as OwnedFd};
+#[cfg(feature = "std")]
+pub use std::os::windows::io::RawSocket as RawFd;
+pub(crate) use windows_sys::Win32::Networking::WinSock::SOCKET as LibcFd;
+
+// Re-export the `Socket` traits so that users can implement them.
+pub use io_lifetimes::{AsSocket, FromSocket, IntoSocket};
+
+/// A version of [`AsRawFd`] for use with Winsock2 API.
+///
+/// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsRawFd.html
+pub trait AsRawFd {
+ /// A version of [`as_raw_fd`] for use with Winsock2 API.
+ ///
+ /// [`as_raw_fd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html#tymethod.as_raw_fd
+ fn as_raw_fd(&self) -> RawFd;
+}
+#[cfg(feature = "std")]
+impl<T: std::os::windows::io::AsRawSocket> AsRawFd for T {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ self.as_raw_socket()
+ }
+}
+
+/// A version of [`IntoRawFd`] for use with Winsock2 API.
+///
+/// [`IntoRawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.IntoRawFd.html
+pub trait IntoRawFd {
+ /// A version of [`into_raw_fd`] for use with Winsock2 API.
+ ///
+ /// [`into_raw_fd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html#tymethod.into_raw_fd
+ fn into_raw_fd(self) -> RawFd;
+}
+#[cfg(feature = "std")]
+impl<T: std::os::windows::io::IntoRawSocket> IntoRawFd for T {
+ #[inline]
+ fn into_raw_fd(self) -> RawFd {
+ self.into_raw_socket()
+ }
+}
+
+/// A version of [`FromRawFd`] for use with Winsock2 API.
+///
+/// [`FromRawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html
+pub trait FromRawFd {
+ /// A version of [`from_raw_fd`] for use with Winsock2 API.
+ ///
+ /// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html#tymethod.from_raw_fd
+ unsafe fn from_raw_fd(raw_fd: RawFd) -> Self;
+}
+#[cfg(feature = "std")]
+impl<T: std::os::windows::io::FromRawSocket> FromRawFd for T {
+ #[inline]
+ unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
+ Self::from_raw_socket(raw_fd)
+ }
+}
+
+/// A version of [`AsFd`] for use with Winsock2 API.
+///
+/// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsFd.html
+pub trait AsFd {
+ /// An `as_fd` function for Winsock2, where a `Fd` is a `Socket`.
+ fn as_fd(&self) -> BorrowedFd;
+}
+impl<T: AsSocket> AsFd for T {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd {
+ self.as_socket()
+ }
+}
+
+/// A version of [`IntoFd`] for use with Winsock2 API.
+///
+/// [`IntoFd`]: https://docs.rs/io-lifetimes/latest/io_lifetimes/trait.IntoFd.html
+pub trait IntoFd {
+ /// A version of [`into_fd`] for use with Winsock2 API.
+ ///
+ /// [`into_fd`]: https://docs.rs/io-lifetimes/latest/io_lifetimes/trait.IntoFd.html#tymethod.into_fd
+ fn into_fd(self) -> OwnedFd;
+}
+impl<T: IntoSocket> IntoFd for T {
+ #[inline]
+ fn into_fd(self) -> OwnedFd {
+ self.into_socket()
+ }
+}
+
+/// A version of [`FromFd`] for use with Winsock2 API.
+///
+/// [`FromFd`]: https://docs.rs/io-lifetimes/latest/io_lifetimes/trait.FromFd.html
+pub trait FromFd {
+ /// A version of [`from_fd`] for use with Winsock2 API.
+ ///
+ /// [`from_fd`]: https://docs.rs/io-lifetimes/latest/io_lifetimes/trait.FromFd.html#tymethod.from_fd
+ fn from_fd(fd: OwnedFd) -> Self;
+}
+impl<T: FromSocket> FromFd for T {
+ #[inline]
+ fn from_fd(fd: OwnedFd) -> Self {
+ Self::from_socket(fd)
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/io_uring/mod.rs b/vendor/rustix/src/imp/libc/io_uring/mod.rs
new file mode 100644
index 000000000..ef944f04d
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io_uring/mod.rs
@@ -0,0 +1 @@
+pub(crate) mod syscalls;
diff --git a/vendor/rustix/src/imp/libc/io_uring/syscalls.rs b/vendor/rustix/src/imp/libc/io_uring/syscalls.rs
new file mode 100644
index 000000000..d1e68363c
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/io_uring/syscalls.rs
@@ -0,0 +1,55 @@
+//! libc syscalls supporting `rustix::io_uring`.
+
+use super::super::c;
+use super::super::conv::{borrowed_fd, syscall_ret, syscall_ret_owned_fd, syscall_ret_u32};
+use crate::fd::BorrowedFd;
+use crate::io::{self, OwnedFd};
+use crate::io_uring::{io_uring_params, IoringEnterFlags, IoringRegisterOp};
+use linux_raw_sys::general::{__NR_io_uring_enter, __NR_io_uring_register, __NR_io_uring_setup};
+
+#[inline]
+pub(crate) fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd> {
+ unsafe {
+ syscall_ret_owned_fd(c::syscall(
+ __NR_io_uring_setup as _,
+ entries as usize,
+ params,
+ ))
+ }
+}
+
+#[inline]
+pub(crate) unsafe fn io_uring_register(
+ fd: BorrowedFd<'_>,
+ opcode: IoringRegisterOp,
+ arg: *const c::c_void,
+ nr_args: u32,
+) -> io::Result<()> {
+ syscall_ret(c::syscall(
+ __NR_io_uring_register as _,
+ borrowed_fd(fd),
+ opcode as u32 as usize,
+ arg,
+ nr_args as usize,
+ ))
+}
+
+#[inline]
+pub(crate) unsafe fn io_uring_enter(
+ fd: BorrowedFd<'_>,
+ to_submit: u32,
+ min_complete: u32,
+ flags: IoringEnterFlags,
+ arg: *const c::c_void,
+ size: usize,
+) -> io::Result<u32> {
+ syscall_ret_u32(c::syscall(
+ __NR_io_uring_enter as _,
+ borrowed_fd(fd),
+ to_submit as usize,
+ min_complete as usize,
+ flags.bits() as usize,
+ arg,
+ size,
+ ))
+}
diff --git a/vendor/rustix/src/imp/libc/mm/mod.rs b/vendor/rustix/src/imp/libc/mm/mod.rs
new file mode 100644
index 000000000..1e0181a99
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/mm/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/libc/mm/syscalls.rs b/vendor/rustix/src/imp/libc/mm/syscalls.rs
new file mode 100644
index 000000000..ee670b5bf
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/mm/syscalls.rs
@@ -0,0 +1,218 @@
+//! libc syscalls supporting `rustix::mm`.
+
+use super::super::c;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use super::super::conv::syscall_ret_owned_fd;
+use super::super::conv::{borrowed_fd, no_fd, ret};
+use super::super::offset::libc_mmap;
+#[cfg(not(target_os = "redox"))]
+use super::types::Advice;
+#[cfg(target_os = "linux")]
+use super::types::MremapFlags;
+use super::types::{MapFlags, MprotectFlags, MsyncFlags, ProtFlags};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use super::types::{MlockFlags, UserfaultfdFlags};
+use crate::fd::BorrowedFd;
+use crate::io;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::io::OwnedFd;
+
+#[cfg(not(target_os = "redox"))]
+pub(crate) fn madvise(addr: *mut c::c_void, len: usize, advice: Advice) -> io::Result<()> {
+ // On Linux platforms, `MADV_DONTNEED` has the same value as
+ // `POSIX_MADV_DONTNEED` but different behavior. We remap it to a different
+ // value, and check for it here.
+ #[cfg(target_os = "linux")]
+ if let Advice::LinuxDontNeed = advice {
+ return unsafe { ret(c::madvise(addr, len, c::MADV_DONTNEED)) };
+ }
+
+ #[cfg(not(target_os = "android"))]
+ {
+ let err = unsafe { c::posix_madvise(addr, len, advice as c::c_int) };
+
+ // `posix_madvise` returns its error status rather than using `errno`.
+ if err == 0 {
+ Ok(())
+ } else {
+ Err(io::Errno(err))
+ }
+ }
+
+ #[cfg(target_os = "android")]
+ {
+ if let Advice::DontNeed = advice {
+ // Do nothing. Linux's `MADV_DONTNEED` isn't the same as
+ // `POSIX_MADV_DONTNEED`, so just discard `MADV_DONTNEED`.
+ Ok(())
+ } else {
+ unsafe { ret(c::madvise(addr, len, advice as c::c_int)) }
+ }
+ }
+}
+
+pub(crate) unsafe fn msync(addr: *mut c::c_void, len: usize, flags: MsyncFlags) -> io::Result<()> {
+ let err = c::msync(addr, len, flags.bits());
+
+ // `msync` returns its error status rather than using `errno`.
+ if err == 0 {
+ Ok(())
+ } else {
+ Err(io::Errno(err))
+ }
+}
+
+/// # Safety
+///
+/// `mmap` is primarily unsafe due to the `addr` parameter, as anything working
+/// with memory pointed to by raw pointers is unsafe.
+pub(crate) unsafe fn mmap(
+ ptr: *mut c::c_void,
+ len: usize,
+ prot: ProtFlags,
+ flags: MapFlags,
+ fd: BorrowedFd<'_>,
+ offset: u64,
+) -> io::Result<*mut c::c_void> {
+ let res = libc_mmap(
+ ptr,
+ len,
+ prot.bits(),
+ flags.bits(),
+ borrowed_fd(fd),
+ offset as i64,
+ );
+ if res == c::MAP_FAILED {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(res)
+ }
+}
+
+/// # Safety
+///
+/// `mmap` is primarily unsafe due to the `addr` parameter, as anything working
+/// with memory pointed to by raw pointers is unsafe.
+pub(crate) unsafe fn mmap_anonymous(
+ ptr: *mut c::c_void,
+ len: usize,
+ prot: ProtFlags,
+ flags: MapFlags,
+) -> io::Result<*mut c::c_void> {
+ let res = libc_mmap(
+ ptr,
+ len,
+ prot.bits(),
+ flags.bits() | c::MAP_ANONYMOUS,
+ no_fd(),
+ 0,
+ );
+ if res == c::MAP_FAILED {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(res)
+ }
+}
+
+pub(crate) unsafe fn mprotect(
+ ptr: *mut c::c_void,
+ len: usize,
+ flags: MprotectFlags,
+) -> io::Result<()> {
+ ret(c::mprotect(ptr, len, flags.bits()))
+}
+
+pub(crate) unsafe fn munmap(ptr: *mut c::c_void, len: usize) -> io::Result<()> {
+ ret(c::munmap(ptr, len))
+}
+
+/// # Safety
+///
+/// `mremap` is primarily unsafe due to the `old_address` parameter, as
+/// anything working with memory pointed to by raw pointers is unsafe.
+#[cfg(target_os = "linux")]
+pub(crate) unsafe fn mremap(
+ old_address: *mut c::c_void,
+ old_size: usize,
+ new_size: usize,
+ flags: MremapFlags,
+) -> io::Result<*mut c::c_void> {
+ let res = c::mremap(old_address, old_size, new_size, flags.bits());
+ if res == c::MAP_FAILED {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(res)
+ }
+}
+
+/// # Safety
+///
+/// `mremap_fixed` is primarily unsafe due to the `old_address` and
+/// `new_address` parameters, as anything working with memory pointed to by raw
+/// pointers is unsafe.
+#[cfg(target_os = "linux")]
+pub(crate) unsafe fn mremap_fixed(
+ old_address: *mut c::c_void,
+ old_size: usize,
+ new_size: usize,
+ flags: MremapFlags,
+ new_address: *mut c::c_void,
+) -> io::Result<*mut c::c_void> {
+ let res = c::mremap(
+ old_address,
+ old_size,
+ new_size,
+ flags.bits() | c::MAP_FIXED,
+ new_address,
+ );
+ if res == c::MAP_FAILED {
+ Err(io::Errno::last_os_error())
+ } else {
+ Ok(res)
+ }
+}
+
+/// # Safety
+///
+/// `mlock` operates on raw pointers and may round out to the nearest page
+/// boundaries.
+#[inline]
+pub(crate) unsafe fn mlock(addr: *mut c::c_void, length: usize) -> io::Result<()> {
+ ret(c::mlock(addr, length))
+}
+
+/// # Safety
+///
+/// `mlock_with` operates on raw pointers and may round out to the nearest page
+/// boundaries.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub(crate) unsafe fn mlock_with(
+ addr: *mut c::c_void,
+ length: usize,
+ flags: MlockFlags,
+) -> io::Result<()> {
+ weak_or_syscall! {
+ fn mlock2(
+ addr: *const c::c_void,
+ len: c::size_t,
+ flags: c::c_int
+ ) via SYS_mlock2 -> c::c_int
+ }
+
+ ret(mlock2(addr, length, flags.bits()))
+}
+
+/// # Safety
+///
+/// `munlock` operates on raw pointers and may round out to the nearest page
+/// boundaries.
+#[inline]
+pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result<()> {
+ ret(c::munlock(addr, length))
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> {
+ syscall_ret_owned_fd(c::syscall(c::SYS_userfaultfd, flags.bits()))
+}
diff --git a/vendor/rustix/src/imp/libc/mm/types.rs b/vendor/rustix/src/imp/libc/mm/types.rs
new file mode 100644
index 000000000..385b6c0e6
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/mm/types.rs
@@ -0,0 +1,397 @@
+use super::super::c;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `PROT_*` flags for use with [`mmap`].
+ ///
+ /// For `PROT_NONE`, use `ProtFlags::empty()`.
+ ///
+ /// [`mmap`]: crate::io::mmap
+ pub struct ProtFlags: c::c_int {
+ /// `PROT_READ`
+ const READ = c::PROT_READ;
+ /// `PROT_WRITE`
+ const WRITE = c::PROT_WRITE;
+ /// `PROT_EXEC`
+ const EXEC = c::PROT_EXEC;
+ }
+}
+
+bitflags! {
+ /// `PROT_*` flags for use with [`mprotect`].
+ ///
+ /// For `PROT_NONE`, use `MprotectFlags::empty()`.
+ ///
+ /// [`mprotect`]: crate::io::mprotect
+ pub struct MprotectFlags: c::c_int {
+ /// `PROT_READ`
+ const READ = c::PROT_READ;
+ /// `PROT_WRITE`
+ const WRITE = c::PROT_WRITE;
+ /// `PROT_EXEC`
+ const EXEC = c::PROT_EXEC;
+ /// `PROT_GROWSUP`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const GROWSUP = c::PROT_GROWSUP;
+ /// `PROT_GROWSDOWN`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const GROWSDOWN = c::PROT_GROWSDOWN;
+ }
+}
+
+bitflags! {
+ /// `MAP_*` flags for use with [`mmap`].
+ ///
+ /// For `MAP_ANONYMOUS` (aka `MAP_ANON`), see [`mmap_anonymous`].
+ ///
+ /// [`mmap`]: crate::io::mmap
+ /// [`mmap_anonymous`]: crates::io::mmap_anonymous
+ pub struct MapFlags: c::c_int {
+ /// `MAP_SHARED`
+ const SHARED = c::MAP_SHARED;
+ /// `MAP_SHARED_VALIDATE`
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const SHARED_VALIDATE = c::MAP_SHARED_VALIDATE;
+ /// `MAP_PRIVATE`
+ const PRIVATE = c::MAP_PRIVATE;
+ /// `MAP_DENYWRITE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const DENYWRITE = c::MAP_DENYWRITE;
+ /// `MAP_FIXED`
+ const FIXED = c::MAP_FIXED;
+ /// `MAP_FIXED_NOREPLACE`
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const FIXED_NOREPLACE = c::MAP_FIXED_NOREPLACE;
+ /// `MAP_GROWSDOWN`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const GROWSDOWN = c::MAP_GROWSDOWN;
+ /// `MAP_HUGETLB`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const HUGETLB = c::MAP_HUGETLB;
+ /// `MAP_HUGE_2MB`
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const HUGE_2MB = c::MAP_HUGE_2MB;
+ /// `MAP_HUGE_1GB`
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const HUGE_1GB = c::MAP_HUGE_1GB;
+ /// `MAP_LOCKED`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const LOCKED = c::MAP_LOCKED;
+ /// `MAP_NORESERVE`
+ #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "redox")))]
+ const NORESERVE = c::MAP_NORESERVE;
+ /// `MAP_POPULATE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ const POPULATE = c::MAP_POPULATE;
+ /// `MAP_STACK`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "redox",
+ )))]
+ const STACK = c::MAP_STACK;
+ /// `MAP_SYNC`
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_arch = "mips", target_arch = "mips64"),
+ )
+ )))]
+ const SYNC = c::MAP_SYNC;
+ /// `MAP_UNINITIALIZED`
+ #[cfg(any())]
+ const UNINITIALIZED = c::MAP_UNINITIALIZED;
+ }
+}
+
+#[cfg(target_os = "linux")]
+bitflags! {
+ /// `MREMAP_*` flags for use with [`mremap`].
+ ///
+ /// For `MREMAP_FIXED`, see [`mremap_fixed`].
+ ///
+ /// [`mremap`]: crate::io::mremap
+ /// [`mremap_fixed`]: crate::io::mremap_fixed
+ pub struct MremapFlags: i32 {
+ /// `MREMAP_MAYMOVE`
+ const MAYMOVE = c::MREMAP_MAYMOVE;
+ }
+}
+
+bitflags! {
+ /// `MS_*` flags for use with [`msync`].
+ ///
+ /// [`msync`]: crate::io::msync
+ pub struct MsyncFlags: i32 {
+ /// `MS_SYNC`—Requests an update and waits for it to complete.
+ const SYNC = c::MS_SYNC;
+ /// `MS_ASYNC`—Specifies that an update be scheduled, but the call
+ /// returns immediately.
+ const ASYNC = c::MS_ASYNC;
+ /// `MS_INVALIDATE`—Asks to invalidate other mappings of the same
+ /// file (so that they can be updated with the fresh values just
+ /// written).
+ const INVALIDATE = c::MS_INVALIDATE;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `MLOCK_*` flags for use with [`mlock_with`].
+ ///
+ /// [`mlock_with`]: crate::io::mlock_with
+ pub struct MlockFlags: i32 {
+ /// `MLOCK_ONFAULT`
+ const ONFAULT = c::MLOCK_ONFAULT as _;
+ }
+}
+
+/// `POSIX_MADV_*` constants for use with [`madvise`].
+///
+/// [`madvise`]: crate::mm::madvise
+#[cfg(not(target_os = "redox"))]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[repr(i32)]
+#[non_exhaustive]
+pub enum Advice {
+ /// `POSIX_MADV_NORMAL`
+ #[cfg(not(target_os = "android"))]
+ Normal = c::POSIX_MADV_NORMAL,
+
+ /// `POSIX_MADV_NORMAL`
+ #[cfg(target_os = "android")]
+ Normal = c::MADV_NORMAL,
+
+ /// `POSIX_MADV_SEQUENTIAL`
+ #[cfg(not(target_os = "android"))]
+ Sequential = c::POSIX_MADV_SEQUENTIAL,
+
+ /// `POSIX_MADV_SEQUENTIAL`
+ #[cfg(target_os = "android")]
+ Sequential = c::MADV_SEQUENTIAL,
+
+ /// `POSIX_MADV_RANDOM`
+ #[cfg(not(target_os = "android"))]
+ Random = c::POSIX_MADV_RANDOM,
+
+ /// `POSIX_MADV_RANDOM`
+ #[cfg(target_os = "android")]
+ Random = c::MADV_RANDOM,
+
+ /// `POSIX_MADV_WILLNEED`
+ #[cfg(not(target_os = "android"))]
+ WillNeed = c::POSIX_MADV_WILLNEED,
+
+ /// `POSIX_MADV_WILLNEED`
+ #[cfg(target_os = "android")]
+ WillNeed = c::MADV_WILLNEED,
+
+ /// `POSIX_MADV_DONTNEED`
+ #[cfg(not(any(target_os = "android", target_os = "emscripten")))]
+ DontNeed = c::POSIX_MADV_DONTNEED,
+
+ /// `POSIX_MADV_DONTNEED`
+ #[cfg(target_os = "android")]
+ DontNeed = i32::MAX - 1,
+
+ /// `MADV_DONTNEED`
+ // `MADV_DONTNEED` has the same value as `POSIX_MADV_DONTNEED`. We don't
+ // have a separate `posix_madvise` from `madvise`, so we expose a special
+ // value which we special-case.
+ #[cfg(target_os = "linux")]
+ LinuxDontNeed = i32::MAX,
+
+ /// `MADV_DONTNEED`
+ #[cfg(target_os = "android")]
+ LinuxDontNeed = c::MADV_DONTNEED,
+ /// `MADV_FREE`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxFree = c::MADV_FREE,
+ /// `MADV_REMOVE`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxRemove = c::MADV_REMOVE,
+ /// `MADV_DONTFORK`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxDontFork = c::MADV_DONTFORK,
+ /// `MADV_DOFORK`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxDoFork = c::MADV_DOFORK,
+ /// `MADV_HWPOISON`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxHwPoison = c::MADV_HWPOISON,
+ /// `MADV_SOFT_OFFLINE`
+ #[cfg(all(
+ any(target_os = "android", target_os = "linux"),
+ not(any(target_arch = "mips", target_arch = "mips64")),
+ ))]
+ LinuxSoftOffline = c::MADV_SOFT_OFFLINE,
+ /// `MADV_MERGEABLE`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxMergeable = c::MADV_MERGEABLE,
+ /// `MADV_UNMERGEABLE`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxUnmergeable = c::MADV_UNMERGEABLE,
+ /// `MADV_HUGEPAGE` (since Linux 2.6.38)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxHugepage = c::MADV_HUGEPAGE,
+ /// `MADV_NOHUGEPAGE` (since Linux 2.6.38)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxNoHugepage = c::MADV_NOHUGEPAGE,
+ /// `MADV_DONTDUMP` (since Linux 3.4)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxDontDump = c::MADV_DONTDUMP,
+ /// `MADV_DODUMP` (since Linux 3.4)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ LinuxDoDump = c::MADV_DODUMP,
+ /// `MADV_WIPEONFORK` (since Linux 4.14)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(feature = "mm")]
+ LinuxWipeOnFork = linux_raw_sys::general::MADV_WIPEONFORK as i32,
+ /// `MADV_KEEPONFORK` (since Linux 4.14)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(feature = "mm")]
+ LinuxKeepOnFork = linux_raw_sys::general::MADV_KEEPONFORK as i32,
+ /// `MADV_COLD` (since Linux 5.4)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(feature = "mm")]
+ LinuxCold = linux_raw_sys::general::MADV_COLD as i32,
+ /// `MADV_PAGEOUT` (since Linux 5.4)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(feature = "mm")]
+ LinuxPageOut = linux_raw_sys::general::MADV_PAGEOUT as i32,
+ /// `MADV_POPULATE_READ` (since Linux 5.14)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(feature = "mm")]
+ LinuxPopulateRead = linux_raw_sys::general::MADV_POPULATE_READ as i32,
+ /// `MADV_POPULATE_WRITE` (since Linux 5.14)
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(feature = "mm")]
+ LinuxPopulateWrite = linux_raw_sys::general::MADV_POPULATE_WRITE as i32,
+}
+
+#[cfg(target_os = "emscripten")]
+impl Advice {
+ /// `POSIX_MADV_DONTNEED`
+ #[allow(non_upper_case_globals)]
+ pub const DontNeed: Self = Self::Normal;
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `O_*` flags for use with [`userfaultfd`].
+ ///
+ /// [`userfaultfd`]: crate::io::userfaultfd
+ pub struct UserfaultfdFlags: c::c_int {
+ /// `O_CLOEXEC`
+ const CLOEXEC = c::O_CLOEXEC;
+ /// `O_NONBLOCK`
+ const NONBLOCK = c::O_NONBLOCK;
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/mod.rs b/vendor/rustix/src/imp/libc/mod.rs
new file mode 100644
index 000000000..e99a323ce
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/mod.rs
@@ -0,0 +1,111 @@
+//! The libc backend.
+//!
+//! On most platforms, this uses the `libc` crate to make system calls. On
+//! Windows, this uses the Winsock2 API in `windows-sys`, which can be adapted
+//! to have a very `libc`-like interface.
+
+// Every FFI call requires an unsafe block, and there are a lot of FFI
+// calls. For now, set this to allow for the libc backend.
+#![allow(clippy::undocumented_unsafe_blocks)]
+// Lots of libc types vary between platforms, so we often need a `.into()` on
+// one platform where it's redundant on another.
+#![allow(clippy::useless_conversion)]
+
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[macro_use]
+mod weak;
+
+mod conv;
+mod offset;
+
+#[cfg(windows)]
+mod io_lifetimes;
+#[cfg(not(windows))]
+#[cfg(not(feature = "std"))]
+pub(crate) mod fd {
+ pub(crate) use super::c::c_int as LibcFd;
+ pub use crate::io::fd::*;
+}
+#[cfg(windows)]
+pub(crate) mod fd {
+ pub use super::io_lifetimes::*;
+}
+#[cfg(not(windows))]
+#[cfg(feature = "std")]
+pub(crate) mod fd {
+ pub use io_lifetimes::*;
+
+ #[cfg(target_os = "wasi")]
+ #[allow(unused_imports)]
+ pub(crate) use super::c::c_int as LibcFd;
+ #[cfg(unix)]
+ #[allow(unused_imports)]
+ pub(crate) use std::os::unix::io::RawFd as LibcFd;
+ #[cfg(unix)]
+ pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+ #[cfg(target_os = "wasi")]
+ pub use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+}
+
+// On Windows we emulate selected libc-compatible interfaces. On non-Windows,
+// we just use libc here, since this is the libc backend.
+#[cfg(windows)]
+#[path = "winsock_c.rs"]
+pub(crate) mod c;
+#[cfg(not(windows))]
+pub(crate) use libc as c;
+
+#[cfg(not(windows))]
+// #[cfg(feature = "fs")] // TODO: Enable this once `OwnedFd` moves out of the tree.
+pub(crate) mod fs;
+pub(crate) mod io;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(feature = "io_uring")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "io_uring")))]
+pub(crate) mod io_uring;
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+pub(crate) mod mm;
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[cfg(feature = "net")]
+pub(crate) mod net;
+#[cfg(not(windows))]
+#[cfg(any(
+ feature = "param",
+ feature = "runtime",
+ feature = "time",
+ target_arch = "x86",
+))]
+pub(crate) mod param;
+#[cfg(not(windows))]
+pub(crate) mod process;
+#[cfg(not(windows))]
+#[cfg(feature = "rand")]
+pub(crate) mod rand;
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[cfg(feature = "termios")]
+pub(crate) mod termios;
+#[cfg(not(windows))]
+#[cfg(feature = "thread")]
+pub(crate) mod thread;
+#[cfg(not(windows))]
+pub(crate) mod time;
+
+/// If the host libc is glibc, return `true` if it is less than version 2.25.
+///
+/// To restate and clarify, this function returning true does not mean the libc
+/// is glibc just that if it is glibc, it is less than version 2.25.
+///
+/// For now, this function is only available on Linux, but if it ends up being
+/// used beyond that, this could be changed to e.g. `#[cfg(unix)]`.
+#[cfg(all(unix, target_env = "gnu"))]
+pub(crate) fn if_glibc_is_less_than_2_25() -> bool {
+ // This is also defined inside `weak_or_syscall!` in
+ // imp/libc/rand/syscalls.rs, but it's not convenient to re-export the weak
+ // symbol from that macro, so we duplicate it at a small cost here.
+ weak! { fn getrandom(*mut c::c_void, c::size_t, c::c_uint) -> c::ssize_t }
+
+ // glibc 2.25 has `getrandom`, which is how we satisfy the API contract of
+ // this function. But, there are likely other libc versions which have it.
+ getrandom.get().is_none()
+}
diff --git a/vendor/rustix/src/imp/libc/net/addr.rs b/vendor/rustix/src/imp/libc/net/addr.rs
new file mode 100644
index 000000000..1aeda5e5d
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/addr.rs
@@ -0,0 +1,320 @@
+//! IPv4, IPv6, and Socket addresses.
+
+use super::super::c;
+#[cfg(unix)]
+use crate::ffi::CStr;
+#[cfg(unix)]
+use crate::io;
+#[cfg(unix)]
+use crate::path;
+#[cfg(not(windows))]
+use core::convert::TryInto;
+#[cfg(unix)]
+use core::fmt;
+#[cfg(unix)]
+use core::slice;
+
+/// `struct sockaddr_un`
+#[cfg(unix)]
+#[derive(Clone)]
+#[doc(alias = "sockaddr_un")]
+pub struct SocketAddrUnix {
+ pub(crate) unix: c::sockaddr_un,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ len: c::socklen_t,
+}
+
+#[cfg(unix)]
+impl SocketAddrUnix {
+ /// Construct a new Unix-domain address from a filesystem path.
+ #[inline]
+ pub fn new<P: path::Arg>(path: P) -> io::Result<Self> {
+ path.into_with_c_str(Self::_new)
+ }
+
+ #[inline]
+ fn _new(path: &CStr) -> io::Result<Self> {
+ let mut unix = Self::init();
+ let bytes = path.to_bytes_with_nul();
+ if bytes.len() > unix.sun_path.len() {
+ return Err(io::Errno::NAMETOOLONG);
+ }
+ for (i, b) in bytes.iter().enumerate() {
+ unix.sun_path[i] = *b as c::c_char;
+ }
+
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ {
+ unix.sun_len = (offsetof_sun_path() + bytes.len()).try_into().unwrap();
+ }
+
+ Ok(Self {
+ unix,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ len: (offsetof_sun_path() + bytes.len()).try_into().unwrap(),
+ })
+ }
+
+ /// Construct a new abstract Unix-domain address from a byte slice.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+ pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
+ let mut unix = Self::init();
+ if 1 + name.len() > unix.sun_path.len() {
+ return Err(io::Errno::NAMETOOLONG);
+ }
+ unix.sun_path[0] = b'\0' as c::c_char;
+ for (i, b) in name.iter().enumerate() {
+ unix.sun_path[1 + i] = *b as c::c_char;
+ }
+ let len = offsetof_sun_path() + 1 + name.len();
+ let len = len.try_into().unwrap();
+ Ok(Self {
+ unix,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ len,
+ })
+ }
+
+ fn init() -> c::sockaddr_un {
+ c::sockaddr_un {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_len: 0,
+ sun_family: c::AF_UNIX as _,
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_path: [0; 104],
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ sun_path: [0; 108],
+ }
+ }
+
+ /// For a filesystem path address, return the path.
+ #[inline]
+ pub fn path(&self) -> Option<&CStr> {
+ let len = self.len();
+ if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char {
+ let end = len as usize - offsetof_sun_path();
+ let bytes = &self.unix.sun_path[..end];
+ // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And
+ // `from_bytes_with_nul_unchecked` since the string is NUL-terminated.
+ unsafe {
+ Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
+ bytes.as_ptr().cast(),
+ bytes.len(),
+ )))
+ }
+ } else {
+ None
+ }
+ }
+
+ /// For an abstract address, return the identifier.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+ pub fn abstract_name(&self) -> Option<&[u8]> {
+ let len = self.len();
+ if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char {
+ let end = len as usize - offsetof_sun_path();
+ let bytes = &self.unix.sun_path[1..end];
+ // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
+ unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ pub(crate) fn addr_len(&self) -> c::socklen_t {
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ {
+ self.len
+ }
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ {
+ c::socklen_t::from(self.unix.sun_len)
+ }
+ }
+
+ #[inline]
+ pub(crate) fn len(&self) -> usize {
+ self.addr_len() as usize
+ }
+}
+
+#[cfg(unix)]
+impl PartialEq for SocketAddrUnix {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len])
+ }
+}
+
+#[cfg(unix)]
+impl Eq for SocketAddrUnix {}
+
+#[cfg(unix)]
+impl PartialOrd for SocketAddrUnix {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len])
+ }
+}
+
+#[cfg(unix)]
+impl Ord for SocketAddrUnix {
+ #[inline]
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len])
+ }
+}
+
+#[cfg(unix)]
+impl core::hash::Hash for SocketAddrUnix {
+ #[inline]
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ let self_len = self.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].hash(state)
+ }
+}
+
+#[cfg(unix)]
+impl fmt::Debug for SocketAddrUnix {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(path) = self.path() {
+ path.fmt(fmt)
+ } else {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ if let Some(name) = self.abstract_name() {
+ return name.fmt(fmt);
+ }
+
+ "(unnamed)".fmt(fmt)
+ }
+ }
+}
+
+/// `struct sockaddr_storage` as a raw struct.
+pub type SocketAddrStorage = c::sockaddr_storage;
+
+/// Return the offset of the `sun_path` field of `sockaddr_un`.
+#[cfg(not(windows))]
+#[inline]
+pub(crate) fn offsetof_sun_path() -> usize {
+ let z = c::sockaddr_un {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_len: 0_u8,
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_family: 0_u8,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ sun_family: 0_u16,
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_path: [0; 104],
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ sun_path: [0; 108],
+ };
+ (crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
+}
diff --git a/vendor/rustix/src/imp/libc/net/ext.rs b/vendor/rustix/src/imp/libc/net/ext.rs
new file mode 100644
index 000000000..7b5313c51
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/ext.rs
@@ -0,0 +1,223 @@
+use super::super::c;
+
+/// The windows `sockaddr_in6` type is a union with accessor functions which
+/// are not `const fn`. Define our own layout-compatible version so that we
+/// can transmute in and out of it.
+#[cfg(windows)]
+#[repr(C)]
+struct sockaddr_in6 {
+ sin6_family: u16,
+ sin6_port: u16,
+ sin6_flowinfo: u32,
+ sin6_addr: c::in6_addr,
+ sin6_scope_id: u32,
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 {
+ addr.s_addr
+}
+
+#[cfg(not(feature = "std"))]
+#[cfg(windows)]
+#[inline]
+pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 {
+ // This should be `*addr.S_un.S_addr()`, except that isn't a `const fn`.
+ unsafe { core::mem::transmute(addr) }
+}
+
+// TODO: With Rust 1.55, we can use the above `in_addr_s_addr` definition that
+// uses a const-fn transmute.
+#[cfg(feature = "std")]
+#[cfg(windows)]
+#[inline]
+pub(crate) fn in_addr_s_addr(addr: c::in_addr) -> u32 {
+ // This should be `*addr.S_un.S_addr()`, except that isn't a `const fn`.
+ unsafe { core::mem::transmute(addr) }
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr {
+ c::in_addr { s_addr }
+}
+
+#[cfg(not(feature = "std"))]
+#[cfg(windows)]
+#[inline]
+pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr {
+ unsafe { core::mem::transmute(s_addr) }
+}
+
+// TODO: With Rust 1.55, we can use the above `in_addr_new` definition that
+// uses a const-fn transmute.
+#[cfg(feature = "std")]
+#[cfg(windows)]
+#[inline]
+pub(crate) fn in_addr_new(s_addr: u32) -> c::in_addr {
+ unsafe { core::mem::transmute(s_addr) }
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
+ addr.s6_addr
+}
+
+#[cfg(not(feature = "std"))]
+#[cfg(windows)]
+#[inline]
+pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
+ unsafe { core::mem::transmute(addr) }
+}
+
+// TODO: With Rust 1.55, we can use the above `in6_addr_s6_addr` definition
+// that uses a const-fn transmute.
+#[cfg(feature = "std")]
+#[cfg(windows)]
+#[inline]
+pub(crate) fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
+ unsafe { core::mem::transmute(addr) }
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
+ c::in6_addr { s6_addr }
+}
+
+#[cfg(not(feature = "std"))]
+#[cfg(windows)]
+#[inline]
+pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
+ unsafe { core::mem::transmute(s6_addr) }
+}
+
+// TODO: With Rust 1.55, we can use the above `in6_addr_new` definition that
+// uses a const-fn transmute.
+#[cfg(feature = "std")]
+#[cfg(windows)]
+#[inline]
+pub(crate) fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
+ unsafe { core::mem::transmute(s6_addr) }
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
+ addr.sin6_scope_id
+}
+
+#[cfg(not(feature = "std"))]
+#[cfg(windows)]
+#[inline]
+pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
+ let addr: sockaddr_in6 = unsafe { core::mem::transmute(addr) };
+ addr.sin6_scope_id
+}
+
+// TODO: With Rust 1.55, we can use the above `sockaddr_in6_sin6_scope_id`
+// definition that uses a const-fn transmute.
+#[cfg(feature = "std")]
+#[cfg(windows)]
+#[inline]
+pub(crate) fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
+ let addr: sockaddr_in6 = unsafe { core::mem::transmute(addr) };
+ addr.sin6_scope_id
+}
+
+#[cfg(not(feature = "std"))]
+#[cfg(not(windows))]
+#[inline]
+pub(crate) fn sockaddr_in6_sin6_scope_id_mut(addr: &mut c::sockaddr_in6) -> &mut u32 {
+ &mut addr.sin6_scope_id
+}
+
+#[cfg(not(feature = "std"))]
+#[cfg(windows)]
+#[inline]
+pub(crate) fn sockaddr_in6_sin6_scope_id_mut(addr: &mut c::sockaddr_in6) -> &mut u32 {
+ let addr: &mut sockaddr_in6 = unsafe { core::mem::transmute(addr) };
+ &mut addr.sin6_scope_id
+}
+
+#[cfg(not(windows))]
+#[inline]
+pub(crate) const fn sockaddr_in6_new(
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sin6_len: u8,
+ sin6_family: c::sa_family_t,
+ sin6_port: u16,
+ sin6_flowinfo: u32,
+ sin6_addr: c::in6_addr,
+ sin6_scope_id: u32,
+) -> c::sockaddr_in6 {
+ c::sockaddr_in6 {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sin6_len,
+ sin6_family,
+ sin6_port,
+ sin6_flowinfo,
+ sin6_addr,
+ sin6_scope_id,
+ #[cfg(target_os = "illumos")]
+ __sin6_src_id: 0,
+ }
+}
+
+#[cfg(not(feature = "std"))]
+#[cfg(windows)]
+#[inline]
+pub(crate) const fn sockaddr_in6_new(
+ sin6_family: u16,
+ sin6_port: u16,
+ sin6_flowinfo: u32,
+ sin6_addr: c::in6_addr,
+ sin6_scope_id: u32,
+) -> c::sockaddr_in6 {
+ let addr = sockaddr_in6 {
+ sin6_family,
+ sin6_port,
+ sin6_flowinfo,
+ sin6_addr,
+ sin6_scope_id,
+ };
+ unsafe { core::mem::transmute(addr) }
+}
+
+// TODO: With Rust 1.55, we can use the above `sockaddr_in6_new` definition
+// that uses a const-fn transmute.
+#[cfg(feature = "std")]
+#[cfg(windows)]
+#[inline]
+pub(crate) fn sockaddr_in6_new(
+ sin6_family: u16,
+ sin6_port: u16,
+ sin6_flowinfo: u32,
+ sin6_addr: c::in6_addr,
+ sin6_scope_id: u32,
+) -> c::sockaddr_in6 {
+ let addr = sockaddr_in6 {
+ sin6_family,
+ sin6_port,
+ sin6_flowinfo,
+ sin6_addr,
+ sin6_scope_id,
+ };
+ unsafe { core::mem::transmute(addr) }
+}
diff --git a/vendor/rustix/src/imp/libc/net/mod.rs b/vendor/rustix/src/imp/libc/net/mod.rs
new file mode 100644
index 000000000..f7196ae4f
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/mod.rs
@@ -0,0 +1,7 @@
+pub(crate) mod addr;
+pub(crate) mod ext;
+pub(crate) mod read_sockaddr;
+pub(crate) mod send_recv;
+pub(crate) mod syscalls;
+pub(crate) mod types;
+pub(crate) mod write_sockaddr;
diff --git a/vendor/rustix/src/imp/libc/net/read_sockaddr.rs b/vendor/rustix/src/imp/libc/net/read_sockaddr.rs
new file mode 100644
index 000000000..cb76b296c
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/read_sockaddr.rs
@@ -0,0 +1,249 @@
+use super::super::c;
+#[cfg(unix)]
+use super::addr::SocketAddrUnix;
+use super::ext::{in6_addr_s6_addr, in_addr_s_addr, sockaddr_in6_sin6_scope_id};
+#[cfg(not(windows))]
+use crate::ffi::CStr;
+use crate::io;
+use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
+#[cfg(not(windows))]
+use alloc::vec::Vec;
+use core::mem::size_of;
+
+// This must match the header of `sockaddr`.
+#[repr(C)]
+struct sockaddr_header {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sa_len: u8,
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ ss_family: u8,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ ss_family: u16,
+}
+
+#[inline]
+unsafe fn read_ss_family(storage: *const c::sockaddr_storage) -> u16 {
+ // Assert that we know the layout of `sockaddr`.
+ let _ = c::sockaddr {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sa_len: 0_u8,
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sa_family: 0_u8,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ sa_family: 0_u16,
+ sa_data: [0; 14],
+ };
+
+ (*storage.cast::<sockaddr_header>()).ss_family.into()
+}
+
+/// Set the `ss_family` field of a socket address to `AF_UNSPEC`, so that we
+/// can test for `AF_UNSPEC` to test whether it was stored to.
+pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr_storage) {
+ (*storage.cast::<sockaddr_header>()).ss_family = c::AF_UNSPEC as _;
+}
+
+pub(crate) unsafe fn read_sockaddr(
+ storage: *const c::sockaddr_storage,
+ len: usize,
+) -> io::Result<SocketAddrAny> {
+ #[cfg(unix)]
+ let offsetof_sun_path = super::addr::offsetof_sun_path();
+
+ if len < size_of::<c::sa_family_t>() {
+ return Err(io::Errno::INVAL);
+ }
+ match read_ss_family(storage).into() {
+ c::AF_INET => {
+ if len < size_of::<c::sockaddr_in>() {
+ return Err(io::Errno::INVAL);
+ }
+ let decode = *storage.cast::<c::sockaddr_in>();
+ Ok(SocketAddrAny::V4(SocketAddrV4::new(
+ Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))),
+ u16::from_be(decode.sin_port),
+ )))
+ }
+ c::AF_INET6 => {
+ if len < size_of::<c::sockaddr_in6>() {
+ return Err(io::Errno::INVAL);
+ }
+ let decode = *storage.cast::<c::sockaddr_in6>();
+ #[cfg(not(windows))]
+ let s6_addr = decode.sin6_addr.s6_addr;
+ #[cfg(windows)]
+ let s6_addr = decode.sin6_addr.u.Byte;
+ #[cfg(not(windows))]
+ let sin6_scope_id = decode.sin6_scope_id;
+ #[cfg(windows)]
+ let sin6_scope_id = decode.Anonymous.sin6_scope_id;
+ Ok(SocketAddrAny::V6(SocketAddrV6::new(
+ Ipv6Addr::from(s6_addr),
+ u16::from_be(decode.sin6_port),
+ u32::from_be(decode.sin6_flowinfo),
+ sin6_scope_id,
+ )))
+ }
+ #[cfg(unix)]
+ c::AF_UNIX => {
+ if len < offsetof_sun_path {
+ return Err(io::Errno::INVAL);
+ }
+ if len == offsetof_sun_path {
+ Ok(SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap()))
+ } else {
+ let decode = *storage.cast::<c::sockaddr_un>();
+
+ // Trim off unused bytes from the end of `path_bytes`.
+ let path_bytes = if cfg!(target_os = "freebsd") {
+ // FreeBSD sometimes sets the length to longer than the length
+ // of the NUL-terminated string. Find the NUL and truncate the
+ // string accordingly.
+ &decode.sun_path[..decode.sun_path.iter().position(|b| *b == 0).unwrap()]
+ } else {
+ // Otherwise, use the provided length.
+ let provided_len = len - 1 - offsetof_sun_path;
+ if decode.sun_path[provided_len] != b'\0' as c::c_char {
+ return Err(io::Errno::INVAL);
+ }
+ debug_assert_eq!(
+ CStr::from_ptr(decode.sun_path.as_ptr()).to_bytes().len(),
+ provided_len
+ );
+ &decode.sun_path[..provided_len]
+ };
+
+ Ok(SocketAddrAny::Unix(
+ SocketAddrUnix::new(path_bytes.iter().map(|c| *c as u8).collect::<Vec<u8>>())
+ .unwrap(),
+ ))
+ }
+ }
+ _ => Err(io::Errno::INVAL),
+ }
+}
+
+pub(crate) unsafe fn maybe_read_sockaddr_os(
+ storage: *const c::sockaddr_storage,
+ len: usize,
+) -> Option<SocketAddrAny> {
+ if len == 0 {
+ return None;
+ }
+
+ assert!(len >= size_of::<c::sa_family_t>());
+ let family = read_ss_family(storage).into();
+ if family == c::AF_UNSPEC {
+ None
+ } else {
+ Some(inner_read_sockaddr_os(family, storage, len))
+ }
+}
+
+pub(crate) unsafe fn read_sockaddr_os(
+ storage: *const c::sockaddr_storage,
+ len: usize,
+) -> SocketAddrAny {
+ assert!(len >= size_of::<c::sa_family_t>());
+ let family = read_ss_family(storage).into();
+ inner_read_sockaddr_os(family, storage, len)
+}
+
+unsafe fn inner_read_sockaddr_os(
+ family: c::c_int,
+ storage: *const c::sockaddr_storage,
+ len: usize,
+) -> SocketAddrAny {
+ #[cfg(unix)]
+ let offsetof_sun_path = super::addr::offsetof_sun_path();
+
+ assert!(len >= size_of::<c::sa_family_t>());
+ match family {
+ c::AF_INET => {
+ assert!(len >= size_of::<c::sockaddr_in>());
+ let decode = *storage.cast::<c::sockaddr_in>();
+ SocketAddrAny::V4(SocketAddrV4::new(
+ Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))),
+ u16::from_be(decode.sin_port),
+ ))
+ }
+ c::AF_INET6 => {
+ assert!(len >= size_of::<c::sockaddr_in6>());
+ let decode = *storage.cast::<c::sockaddr_in6>();
+ SocketAddrAny::V6(SocketAddrV6::new(
+ Ipv6Addr::from(in6_addr_s6_addr(decode.sin6_addr)),
+ u16::from_be(decode.sin6_port),
+ u32::from_be(decode.sin6_flowinfo),
+ sockaddr_in6_sin6_scope_id(decode),
+ ))
+ }
+ #[cfg(unix)]
+ c::AF_UNIX => {
+ assert!(len >= offsetof_sun_path);
+ if len == offsetof_sun_path {
+ SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap())
+ } else {
+ let decode = *storage.cast::<c::sockaddr_un>();
+ assert_eq!(
+ decode.sun_path[len - 1 - offsetof_sun_path],
+ b'\0' as c::c_char
+ );
+ let path_bytes = &decode.sun_path[..len - 1 - offsetof_sun_path];
+
+ // FreeBSD sometimes sets the length to longer than the length
+ // of the NUL-terminated string. Find the NUL and truncate the
+ // string accordingly.
+ #[cfg(target_os = "freebsd")]
+ let path_bytes = &path_bytes[..path_bytes.iter().position(|b| *b == 0).unwrap()];
+
+ SocketAddrAny::Unix(
+ SocketAddrUnix::new(path_bytes.iter().map(|c| *c as u8).collect::<Vec<u8>>())
+ .unwrap(),
+ )
+ }
+ }
+ other => unimplemented!("{:?}", other),
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/net/send_recv.rs b/vendor/rustix/src/imp/libc/net/send_recv.rs
new file mode 100644
index 000000000..9ab908d62
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/send_recv.rs
@@ -0,0 +1,77 @@
+use super::super::c;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `MSG_*`
+ pub struct SendFlags: i32 {
+ /// `MSG_CONFIRM`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ const CONFIRM = c::MSG_CONFIRM;
+ /// `MSG_DONTROUTE`
+ const DONTROUTE = c::MSG_DONTROUTE;
+ /// `MSG_DONTWAIT`
+ #[cfg(not(windows))]
+ const DONTWAIT = c::MSG_DONTWAIT;
+ /// `MSG_EOR`
+ #[cfg(not(windows))]
+ const EOT = c::MSG_EOR;
+ /// `MSG_MORE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ const MORE = c::MSG_MORE;
+ #[cfg(not(any(windows, target_os = "ios", target_os = "macos")))]
+ /// `MSG_NOSIGNAL`
+ const NOSIGNAL = c::MSG_NOSIGNAL;
+ /// `MSG_OOB`
+ const OOB = c::MSG_OOB;
+ }
+}
+
+bitflags! {
+ /// `MSG_*`
+ pub struct RecvFlags: i32 {
+ #[cfg(not(any(windows, target_os = "illumos", target_os = "ios", target_os = "macos")))]
+ /// `MSG_CMSG_CLOEXEC`
+ const CMSG_CLOEXEC = c::MSG_CMSG_CLOEXEC;
+ /// `MSG_DONTWAIT`
+ #[cfg(not(windows))]
+ const DONTWAIT = c::MSG_DONTWAIT;
+ /// `MSG_ERRQUEUE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ const ERRQUEUE = c::MSG_ERRQUEUE;
+ /// `MSG_OOB`
+ const OOB = c::MSG_OOB;
+ /// `MSG_PEEK`
+ const PEEK = c::MSG_PEEK;
+ /// `MSG_TRUNC`
+ const TRUNC = c::MSG_TRUNC as c::c_int;
+ /// `MSG_WAITALL`
+ const WAITALL = c::MSG_WAITALL;
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/net/syscalls.rs b/vendor/rustix/src/imp/libc/net/syscalls.rs
new file mode 100644
index 000000000..b0bab2e31
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/syscalls.rs
@@ -0,0 +1,866 @@
+//! libc syscalls supporting `rustix::net`.
+
+use super::super::c;
+use super::super::conv::{borrowed_fd, ret, ret_owned_fd, ret_send_recv, send_recv_len};
+#[cfg(unix)]
+use super::addr::SocketAddrUnix;
+use super::ext::{in6_addr_new, in_addr_new};
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+use super::read_sockaddr::initialize_family_to_unspec;
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+use super::read_sockaddr::{maybe_read_sockaddr_os, read_sockaddr_os};
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+use super::send_recv::{RecvFlags, SendFlags};
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+use super::types::{AcceptFlags, AddressFamily, Protocol, Shutdown, SocketFlags, SocketType};
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
+use crate::fd::BorrowedFd;
+use crate::io::{self, OwnedFd};
+use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6};
+use crate::utils::as_ptr;
+use core::convert::TryInto;
+use core::mem::{size_of, MaybeUninit};
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+use core::ptr::null_mut;
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> {
+ let nrecv = unsafe {
+ ret_send_recv(c::recv(
+ borrowed_fd(fd),
+ buf.as_mut_ptr().cast(),
+ send_recv_len(buf.len()),
+ flags.bits(),
+ ))?
+ };
+ Ok(nrecv as usize)
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
+ let nwritten = unsafe {
+ ret_send_recv(c::send(
+ borrowed_fd(fd),
+ buf.as_ptr().cast(),
+ send_recv_len(buf.len()),
+ flags.bits(),
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn recvfrom(
+ fd: BorrowedFd<'_>,
+ buf: &mut [u8],
+ flags: RecvFlags,
+) -> io::Result<(usize, Option<SocketAddrAny>)> {
+ unsafe {
+ let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
+ let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
+
+ // `recvfrom` does not write to the storage if the socket is
+ // connection-oriented sockets, so we initialize the family field to
+ // `AF_UNSPEC` so that we can detect this case.
+ initialize_family_to_unspec(storage.as_mut_ptr());
+
+ let nread = ret_send_recv(c::recvfrom(
+ borrowed_fd(fd),
+ buf.as_mut_ptr().cast(),
+ send_recv_len(buf.len()),
+ flags.bits(),
+ storage.as_mut_ptr().cast(),
+ &mut len,
+ ))?;
+ Ok((
+ nread as usize,
+ maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()),
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn sendto_v4(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrV4,
+) -> io::Result<usize> {
+ let nwritten = unsafe {
+ ret_send_recv(c::sendto(
+ borrowed_fd(fd),
+ buf.as_ptr().cast(),
+ send_recv_len(buf.len()),
+ flags.bits(),
+ as_ptr(&encode_sockaddr_v4(addr)).cast::<c::sockaddr>(),
+ size_of::<SocketAddrV4>() as _,
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn sendto_v6(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrV6,
+) -> io::Result<usize> {
+ let nwritten = unsafe {
+ ret_send_recv(c::sendto(
+ borrowed_fd(fd),
+ buf.as_ptr().cast(),
+ send_recv_len(buf.len()),
+ flags.bits(),
+ as_ptr(&encode_sockaddr_v6(addr)).cast::<c::sockaddr>(),
+ size_of::<SocketAddrV6>() as _,
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+pub(crate) fn sendto_unix(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrUnix,
+) -> io::Result<usize> {
+ let nwritten = unsafe {
+ ret_send_recv(c::sendto(
+ borrowed_fd(fd),
+ buf.as_ptr().cast(),
+ send_recv_len(buf.len()),
+ flags.bits(),
+ as_ptr(&addr.unix).cast(),
+ addr.addr_len(),
+ ))?
+ };
+ Ok(nwritten as usize)
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn socket(
+ domain: AddressFamily,
+ type_: SocketType,
+ protocol: Protocol,
+) -> io::Result<OwnedFd> {
+ unsafe {
+ ret_owned_fd(c::socket(
+ domain.0 as c::c_int,
+ type_.0 as c::c_int,
+ protocol.0,
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn socket_with(
+ domain: AddressFamily,
+ type_: SocketType,
+ flags: SocketFlags,
+ protocol: Protocol,
+) -> io::Result<OwnedFd> {
+ unsafe {
+ ret_owned_fd(c::socket(
+ domain.0 as c::c_int,
+ type_.0 as c::c_int | flags.bits(),
+ protocol.0,
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn bind_v4(sockfd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
+ unsafe {
+ ret(c::bind(
+ borrowed_fd(sockfd),
+ as_ptr(&encode_sockaddr_v4(addr)).cast(),
+ size_of::<c::sockaddr_in>() as c::socklen_t,
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn bind_v6(sockfd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
+ unsafe {
+ ret(c::bind(
+ borrowed_fd(sockfd),
+ as_ptr(&encode_sockaddr_v6(addr)).cast(),
+ size_of::<c::sockaddr_in6>() as c::socklen_t,
+ ))
+ }
+}
+
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+pub(crate) fn bind_unix(sockfd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
+ unsafe {
+ ret(c::bind(
+ borrowed_fd(sockfd),
+ as_ptr(&addr.unix).cast(),
+ addr.addr_len(),
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn connect_v4(sockfd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
+ unsafe {
+ ret(c::connect(
+ borrowed_fd(sockfd),
+ as_ptr(&encode_sockaddr_v4(addr)).cast(),
+ size_of::<c::sockaddr_in>() as c::socklen_t,
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn connect_v6(sockfd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
+ unsafe {
+ ret(c::connect(
+ borrowed_fd(sockfd),
+ as_ptr(&encode_sockaddr_v6(addr)).cast(),
+ size_of::<c::sockaddr_in6>() as c::socklen_t,
+ ))
+ }
+}
+
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+pub(crate) fn connect_unix(sockfd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
+ unsafe {
+ ret(c::connect(
+ borrowed_fd(sockfd),
+ as_ptr(&addr.unix).cast(),
+ addr.addr_len(),
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn listen(sockfd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
+ unsafe { ret(c::listen(borrowed_fd(sockfd), backlog)) }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn accept(sockfd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
+ unsafe {
+ let owned_fd = ret_owned_fd(c::accept(borrowed_fd(sockfd), null_mut(), null_mut()))?;
+ Ok(owned_fd)
+ }
+}
+
+#[cfg(not(any(
+ windows,
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, flags: AcceptFlags) -> io::Result<OwnedFd> {
+ unsafe {
+ let owned_fd = ret_owned_fd(c::accept4(
+ borrowed_fd(sockfd),
+ null_mut(),
+ null_mut(),
+ flags.bits(),
+ ))?;
+ Ok(owned_fd)
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn acceptfrom(sockfd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ unsafe {
+ let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
+ let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
+ let owned_fd = ret_owned_fd(c::accept(
+ borrowed_fd(sockfd),
+ storage.as_mut_ptr().cast(),
+ &mut len,
+ ))?;
+ Ok((
+ owned_fd,
+ maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()),
+ ))
+ }
+}
+
+#[cfg(not(any(
+ windows,
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub(crate) fn acceptfrom_with(
+ sockfd: BorrowedFd<'_>,
+ flags: AcceptFlags,
+) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ unsafe {
+ let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
+ let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
+ let owned_fd = ret_owned_fd(c::accept4(
+ borrowed_fd(sockfd),
+ storage.as_mut_ptr().cast(),
+ &mut len,
+ flags.bits(),
+ ))?;
+ Ok((
+ owned_fd,
+ maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()),
+ ))
+ }
+}
+
+/// Darwin lacks `accept4`, but does have `accept`. We define
+/// `AcceptFlags` to have no flags, so we can discard it here.
+#[cfg(any(windows, target_os = "ios", target_os = "macos"))]
+pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, _flags: AcceptFlags) -> io::Result<OwnedFd> {
+ accept(sockfd)
+}
+
+/// Darwin lacks `accept4`, but does have `accept`. We define
+/// `AcceptFlags` to have no flags, so we can discard it here.
+#[cfg(any(windows, target_os = "ios", target_os = "macos"))]
+pub(crate) fn acceptfrom_with(
+ sockfd: BorrowedFd<'_>,
+ _flags: AcceptFlags,
+) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ acceptfrom(sockfd)
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn shutdown(sockfd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
+ unsafe { ret(c::shutdown(borrowed_fd(sockfd), how as c::c_int)) }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn getsockname(sockfd: BorrowedFd<'_>) -> io::Result<SocketAddrAny> {
+ unsafe {
+ let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
+ let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
+ ret(c::getsockname(
+ borrowed_fd(sockfd),
+ storage.as_mut_ptr().cast(),
+ &mut len,
+ ))?;
+ Ok(read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn getpeername(sockfd: BorrowedFd<'_>) -> io::Result<Option<SocketAddrAny>> {
+ unsafe {
+ let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
+ let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
+ ret(c::getpeername(
+ borrowed_fd(sockfd),
+ storage.as_mut_ptr().cast(),
+ &mut len,
+ ))?;
+ Ok(maybe_read_sockaddr_os(
+ storage.as_ptr(),
+ len.try_into().unwrap(),
+ ))
+ }
+}
+
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+pub(crate) fn socketpair(
+ domain: AddressFamily,
+ type_: SocketType,
+ flags: SocketFlags,
+ protocol: Protocol,
+) -> io::Result<(OwnedFd, OwnedFd)> {
+ unsafe {
+ let mut fds = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(c::socketpair(
+ c::c_int::from(domain.0),
+ type_.0 as c::c_int | flags.bits(),
+ protocol.0,
+ fds.as_mut_ptr().cast::<c::c_int>(),
+ ))?;
+
+ let [fd0, fd1] = fds.assume_init();
+ Ok((fd0, fd1))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) mod sockopt {
+ use super::{c, in6_addr_new, in_addr_new, BorrowedFd};
+ use crate::io;
+ use crate::net::sockopt::Timeout;
+ use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
+ use crate::utils::as_mut_ptr;
+ use core::convert::TryInto;
+ use core::time::Duration;
+ #[cfg(windows)]
+ use windows_sys::Win32::Foundation::BOOL;
+
+ // TODO: With Rust 1.53 we can use `Duration::ZERO` instead.
+ const DURATION_ZERO: Duration = Duration::from_secs(0);
+
+ #[inline]
+ fn getsockopt<T: Copy>(fd: BorrowedFd<'_>, level: i32, optname: i32) -> io::Result<T> {
+ use super::*;
+
+ let mut optlen = core::mem::size_of::<T>().try_into().unwrap();
+ debug_assert!(
+ optlen as usize >= core::mem::size_of::<c::c_int>(),
+ "Socket APIs don't ever use `bool` directly"
+ );
+
+ unsafe {
+ let mut value = core::mem::zeroed::<T>();
+ ret(c::getsockopt(
+ borrowed_fd(fd),
+ level,
+ optname,
+ as_mut_ptr(&mut value).cast(),
+ &mut optlen,
+ ))?;
+ // On Windows at least, `getsockopt` has been observed writing 1
+ // byte on at least (`IPPROTO_TCP`, `TCP_NODELAY`), even though
+ // Windows' documentation says that should write a 4-byte `BOOL`.
+ // So, we initialize the memory to zeros above, and just assert
+ // that `getsockopt` doesn't write too many bytes here.
+ assert!(
+ optlen as usize <= size_of::<T>(),
+ "unexpected getsockopt size"
+ );
+ Ok(value)
+ }
+ }
+
+ #[inline]
+ fn setsockopt<T: Copy>(
+ fd: BorrowedFd<'_>,
+ level: i32,
+ optname: i32,
+ value: T,
+ ) -> io::Result<()> {
+ use super::*;
+
+ let optlen = core::mem::size_of::<T>().try_into().unwrap();
+ debug_assert!(
+ optlen as usize >= core::mem::size_of::<c::c_int>(),
+ "Socket APIs don't ever use `bool` directly"
+ );
+
+ unsafe {
+ ret(c::setsockopt(
+ borrowed_fd(fd),
+ level,
+ optname,
+ as_ptr(&value).cast(),
+ optlen,
+ ))
+ }
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_type(fd: BorrowedFd<'_>) -> io::Result<SocketType> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_TYPE)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_reuseaddr(fd: BorrowedFd<'_>, reuseaddr: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::SOL_SOCKET as _,
+ c::SO_REUSEADDR,
+ from_bool(reuseaddr),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_broadcast(fd: BorrowedFd<'_>, broadcast: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::SOL_SOCKET as _,
+ c::SO_BROADCAST,
+ from_bool(broadcast),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_broadcast(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_BROADCAST).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_linger(
+ fd: BorrowedFd<'_>,
+ linger: Option<Duration>,
+ ) -> io::Result<()> {
+ // Convert `linger` to seconds, rounding up.
+ let l_linger = if let Some(linger) = linger {
+ let mut l_linger = linger.as_secs();
+ if linger.subsec_nanos() != 0 {
+ l_linger = l_linger.checked_add(1).ok_or(io::Errno::INVAL)?;
+ }
+ l_linger.try_into().map_err(|_e| io::Errno::INVAL)?
+ } else {
+ 0
+ };
+ let linger = c::linger {
+ l_onoff: linger.is_some() as _,
+ l_linger,
+ };
+ setsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER, linger)
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result<Option<Duration>> {
+ let linger: c::linger = getsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER)?;
+ // TODO: With Rust 1.50, this could use `.then`.
+ Ok(if linger.l_onoff != 0 {
+ Some(Duration::from_secs(linger.l_linger as u64))
+ } else {
+ None
+ })
+ }
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+ pub(crate) fn set_socket_passcred(fd: BorrowedFd<'_>, passcred: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED, from_bool(passcred))
+ }
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+ pub(crate) fn get_socket_passcred(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_timeout(
+ fd: BorrowedFd<'_>,
+ id: Timeout,
+ timeout: Option<Duration>,
+ ) -> io::Result<()> {
+ let optname = match id {
+ Timeout::Recv => c::SO_RCVTIMEO,
+ Timeout::Send => c::SO_SNDTIMEO,
+ };
+
+ #[cfg(not(windows))]
+ let timeout = match timeout {
+ Some(timeout) => {
+ if timeout == DURATION_ZERO {
+ return Err(io::Errno::INVAL);
+ }
+
+ let tv_sec = timeout.as_secs().try_into();
+ #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+ let tv_sec = tv_sec.unwrap_or(c::c_long::MAX);
+ #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+ let tv_sec = tv_sec.unwrap_or(i64::MAX);
+
+ // `subsec_micros` rounds down, so we use `subsec_nanos` and
+ // manually round up.
+ let mut timeout = c::timeval {
+ tv_sec,
+ tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _,
+ };
+ if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+ timeout.tv_usec = 1;
+ }
+ timeout
+ }
+ None => c::timeval {
+ tv_sec: 0,
+ tv_usec: 0,
+ },
+ };
+
+ #[cfg(windows)]
+ let timeout: u32 = match timeout {
+ Some(timeout) => {
+ if timeout == DURATION_ZERO {
+ return Err(io::Errno::INVAL);
+ }
+
+ // `as_millis` rounds down, so we use `as_nanos` and
+ // manually round up.
+ let mut timeout: u32 = ((timeout.as_nanos() + 999_999) / 1_000_000)
+ .try_into()
+ .map_err(|_convert_err| io::Errno::INVAL)?;
+ if timeout == 0 {
+ timeout = 1;
+ }
+ timeout
+ }
+ None => 0,
+ };
+
+ setsockopt(fd, c::SOL_SOCKET, optname, timeout)
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_timeout(
+ fd: BorrowedFd<'_>,
+ id: Timeout,
+ ) -> io::Result<Option<Duration>> {
+ let optname = match id {
+ Timeout::Recv => c::SO_RCVTIMEO,
+ Timeout::Send => c::SO_SNDTIMEO,
+ };
+
+ #[cfg(not(windows))]
+ {
+ let timeout: c::timeval = getsockopt(fd, c::SOL_SOCKET, optname)?;
+ if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+ Ok(None)
+ } else {
+ Ok(Some(
+ Duration::from_secs(timeout.tv_sec as u64)
+ + Duration::from_micros(timeout.tv_usec as u64),
+ ))
+ }
+ }
+
+ #[cfg(windows)]
+ {
+ let timeout: u32 = getsockopt(fd, c::SOL_SOCKET, optname)?;
+ if timeout == 0 {
+ Ok(None)
+ } else {
+ Ok(Some(Duration::from_millis(timeout as u64)))
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_ttl(fd: BorrowedFd<'_>, ttl: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL, ttl)
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_v6only(fd: BorrowedFd<'_>, only_v6: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY, from_bool(only_v6))
+ }
+
+ #[inline]
+ pub(crate) fn get_ipv6_v6only(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_multicast_loop(
+ fd: BorrowedFd<'_>,
+ multicast_loop: bool,
+ ) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IP as _,
+ c::IP_MULTICAST_LOOP,
+ from_bool(multicast_loop),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_LOOP).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_multicast_ttl(fd: BorrowedFd<'_>, multicast_ttl: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL, multicast_ttl)
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_multicast_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_multicast_loop(
+ fd: BorrowedFd<'_>,
+ multicast_loop: bool,
+ ) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IPV6 as _,
+ c::IPV6_MULTICAST_LOOP,
+ from_bool(multicast_loop),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_ipv6_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_MULTICAST_LOOP).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_add_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ ) -> io::Result<()> {
+ let mreq = to_imr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_ADD_MEMBERSHIP, mreq)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_add_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv6Addr,
+ interface: u32,
+ ) -> io::Result<()> {
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "l4re",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "solaris",
+ )))]
+ use c::IPV6_ADD_MEMBERSHIP;
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "l4re",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "solaris",
+ ))]
+ use c::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
+
+ let mreq = to_ipv6mr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IPV6 as _, IPV6_ADD_MEMBERSHIP, mreq)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_drop_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ ) -> io::Result<()> {
+ let mreq = to_imr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_DROP_MEMBERSHIP, mreq)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_drop_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv6Addr,
+ interface: u32,
+ ) -> io::Result<()> {
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "l4re",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "solaris",
+ )))]
+ use c::IPV6_DROP_MEMBERSHIP;
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "l4re",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "solaris",
+ ))]
+ use c::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
+
+ let mreq = to_ipv6mr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IPV6 as _, IPV6_DROP_MEMBERSHIP, mreq)
+ }
+
+ #[inline]
+ pub(crate) fn set_tcp_nodelay(fd: BorrowedFd<'_>, nodelay: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY, from_bool(nodelay))
+ }
+
+ #[inline]
+ pub(crate) fn get_tcp_nodelay(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY).map(to_bool)
+ }
+
+ #[inline]
+ fn to_imr(multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> c::ip_mreq {
+ c::ip_mreq {
+ imr_multiaddr: to_imr_addr(multiaddr),
+ imr_interface: to_imr_addr(interface),
+ }
+ }
+
+ #[inline]
+ fn to_imr_addr(addr: &Ipv4Addr) -> c::in_addr {
+ in_addr_new(u32::from_ne_bytes(addr.octets()))
+ }
+
+ #[inline]
+ fn to_ipv6mr(multiaddr: &Ipv6Addr, interface: u32) -> c::ipv6_mreq {
+ c::ipv6_mreq {
+ ipv6mr_multiaddr: to_ipv6mr_multiaddr(multiaddr),
+ ipv6mr_interface: to_ipv6mr_interface(interface),
+ }
+ }
+
+ #[inline]
+ fn to_ipv6mr_multiaddr(multiaddr: &Ipv6Addr) -> c::in6_addr {
+ in6_addr_new(multiaddr.octets())
+ }
+
+ #[cfg(target_os = "android")]
+ #[inline]
+ fn to_ipv6mr_interface(interface: u32) -> c::c_int {
+ interface as c::c_int
+ }
+
+ #[cfg(not(target_os = "android"))]
+ #[inline]
+ fn to_ipv6mr_interface(interface: u32) -> c::c_uint {
+ interface as c::c_uint
+ }
+
+ // `getsockopt` and `setsockopt` represent boolean values as integers.
+ #[cfg(not(windows))]
+ type RawSocketBool = c::c_int;
+ #[cfg(windows)]
+ type RawSocketBool = BOOL;
+
+ // Wrap `RawSocketBool` in a newtype to discourage misuse.
+ #[repr(transparent)]
+ #[derive(Copy, Clone)]
+ struct SocketBool(RawSocketBool);
+
+ // Convert from a `bool` to a `SocketBool`.
+ #[inline]
+ fn from_bool(value: bool) -> SocketBool {
+ SocketBool(value as _)
+ }
+
+ // Convert from a `SocketBool` to a `bool`.
+ #[inline]
+ fn to_bool(value: SocketBool) -> bool {
+ value.0 != 0
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/net/types.rs b/vendor/rustix/src/imp/libc/net/types.rs
new file mode 100644
index 000000000..63e3a317e
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/types.rs
@@ -0,0 +1,621 @@
+use super::super::c;
+use bitflags::bitflags;
+
+/// A type for holding raw integer socket types.
+#[doc(hidden)]
+pub type RawSocketType = u32;
+
+/// `SOCK_*` constants for use with [`socket`].
+///
+/// [`socket`]: crate::net::socket
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct SocketType(pub(crate) RawSocketType);
+
+#[rustfmt::skip]
+impl SocketType {
+ /// `SOCK_STREAM`
+ pub const STREAM: Self = Self(c::SOCK_STREAM as u32);
+
+ /// `SOCK_DGRAM`
+ pub const DGRAM: Self = Self(c::SOCK_DGRAM as u32);
+
+ /// `SOCK_SEQPACKET`
+ pub const SEQPACKET: Self = Self(c::SOCK_SEQPACKET as u32);
+
+ /// `SOCK_RAW`
+ pub const RAW: Self = Self(c::SOCK_RAW as u32);
+
+ /// `SOCK_RDM`
+ pub const RDM: Self = Self(c::SOCK_RDM as u32);
+
+ /// Constructs a `SocketType` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawSocketType) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `SocketType`.
+ #[inline]
+ pub const fn as_raw(self) -> RawSocketType {
+ self.0
+ }
+}
+
+/// A type for holding raw integer address families.
+#[doc(hidden)]
+pub type RawAddressFamily = c::sa_family_t;
+
+/// `AF_*` constants.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct AddressFamily(pub(crate) RawAddressFamily);
+
+#[rustfmt::skip]
+impl AddressFamily {
+ /// `AF_UNSPEC`
+ pub const UNSPEC: Self = Self(c::AF_UNSPEC as _);
+ /// `AF_INET`
+ pub const INET: Self = Self(c::AF_INET as _);
+ /// `AF_INET6`
+ pub const INET6: Self = Self(c::AF_INET6 as _);
+ /// `AF_NETLINK`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const NETLINK: Self = Self(c::AF_NETLINK as _);
+ /// `AF_UNIX`, aka `AF_LOCAL`
+ #[doc(alias = "LOCAL")]
+ pub const UNIX: Self = Self(c::AF_UNIX as _);
+ /// `AF_AX25`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const AX25: Self = Self(c::AF_AX25 as _);
+ /// `AF_IPX`
+ pub const IPX: Self = Self(c::AF_IPX as _);
+ /// `AF_APPLETALK`
+ pub const APPLETALK: Self = Self(c::AF_APPLETALK as _);
+ /// `AF_NETROM`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const NETROM: Self = Self(c::AF_NETROM as _);
+ /// `AF_BRIDGE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const BRIDGE: Self = Self(c::AF_BRIDGE as _);
+ /// `AF_ATMPVC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const ATMPVC: Self = Self(c::AF_ATMPVC as _);
+ /// `AF_X25`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const X25: Self = Self(c::AF_X25 as _);
+ /// `AF_ROSE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const ROSE: Self = Self(c::AF_ROSE as _);
+ /// `AF_DECnet`
+ #[allow(non_upper_case_globals)]
+ pub const DECnet: Self = Self(c::AF_DECnet as _);
+ /// `AF_NETBEUI`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const NETBEUI: Self = Self(c::AF_NETBEUI as _);
+ /// `AF_SECURITY`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const SECURITY: Self = Self(c::AF_SECURITY as _);
+ /// `AF_KEY`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const KEY: Self = Self(c::AF_KEY as _);
+ /// `AF_PACKET`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const PACKET: Self = Self(c::AF_PACKET as _);
+ /// `AF_ASH`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const ASH: Self = Self(c::AF_ASH as _);
+ /// `AF_ECONET`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const ECONET: Self = Self(c::AF_ECONET as _);
+ /// `AF_ATMSVC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const ATMSVC: Self = Self(c::AF_ATMSVC as _);
+ /// `AF_RDS`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const RDS: Self = Self(c::AF_RDS as _);
+ /// `AF_SNA`
+ pub const SNA: Self = Self(c::AF_SNA as _);
+ /// `AF_IRDA`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const IRDA: Self = Self(c::AF_IRDA as _);
+ /// `AF_PPPOX`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const PPPOX: Self = Self(c::AF_PPPOX as _);
+ /// `AF_WANPIPE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const WANPIPE: Self = Self(c::AF_WANPIPE as _);
+ /// `AF_LLC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const LLC: Self = Self(c::AF_LLC as _);
+ /// `AF_CAN`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const CAN: Self = Self(c::AF_CAN as _);
+ /// `AF_TIPC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const TIPC: Self = Self(c::AF_TIPC as _);
+ /// `AF_BLUETOOTH`
+ #[cfg(not(any(windows, target_os = "illumos", target_os = "ios", target_os = "macos")))]
+ pub const BLUETOOTH: Self = Self(c::AF_BLUETOOTH as _);
+ /// `AF_IUCV`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const IUCV: Self = Self(c::AF_IUCV as _);
+ /// `AF_RXRPC`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const RXRPC: Self = Self(c::AF_RXRPC as _);
+ /// `AF_ISDN`
+ #[cfg(not(any(windows, target_os = "illumos")))]
+ pub const ISDN: Self = Self(c::AF_ISDN as _);
+ /// `AF_PHONET`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const PHONET: Self = Self(c::AF_PHONET as _);
+ /// `AF_IEEE802154`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const IEEE802154: Self = Self(c::AF_IEEE802154 as _);
+
+ /// Constructs a `AddressFamily` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawAddressFamily) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `AddressFamily`.
+ #[inline]
+ pub const fn as_raw(self) -> RawAddressFamily {
+ self.0
+ }
+}
+
+/// A type for holding raw integer protocols.
+#[doc(hidden)]
+pub type RawProtocol = i32;
+
+/// `IPPROTO_*`
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct Protocol(pub(crate) RawProtocol);
+
+#[rustfmt::skip]
+impl Protocol {
+ /// `IPPROTO_IP`
+ pub const IP: Self = Self(c::IPPROTO_IP as _);
+ /// `IPPROTO_ICMP`
+ pub const ICMP: Self = Self(c::IPPROTO_ICMP as _);
+ /// `IPPROTO_IGMP`
+ #[cfg(not(target_os = "illumos"))]
+ pub const IGMP: Self = Self(c::IPPROTO_IGMP as _);
+ /// `IPPROTO_IPIP`
+ #[cfg(not(any(windows, target_os = "illumos")))]
+ pub const IPIP: Self = Self(c::IPPROTO_IPIP as _);
+ /// `IPPROTO_TCP`
+ pub const TCP: Self = Self(c::IPPROTO_TCP as _);
+ /// `IPPROTO_EGP`
+ #[cfg(not(target_os = "illumos"))]
+ pub const EGP: Self = Self(c::IPPROTO_EGP as _);
+ /// `IPPROTO_PUP`
+ #[cfg(not(target_os = "illumos"))]
+ pub const PUP: Self = Self(c::IPPROTO_PUP as _);
+ /// `IPPROTO_UDP`
+ pub const UDP: Self = Self(c::IPPROTO_UDP as _);
+ /// `IPPROTO_IDP`
+ #[cfg(not(target_os = "illumos"))]
+ pub const IDP: Self = Self(c::IPPROTO_IDP as _);
+ /// `IPPROTO_TP`
+ #[cfg(not(any(windows, target_os = "illumos")))]
+ pub const TP: Self = Self(c::IPPROTO_TP as _);
+ /// `IPPROTO_DCCP`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ )))]
+ pub const DCCP: Self = Self(c::IPPROTO_DCCP as _);
+ /// `IPPROTO_IPV6`
+ pub const IPV6: Self = Self(c::IPPROTO_IPV6 as _);
+ /// `IPPROTO_RSVP`
+ #[cfg(not(any(windows, target_os = "illumos")))]
+ pub const RSVP: Self = Self(c::IPPROTO_RSVP as _);
+ /// `IPPROTO_GRE`
+ #[cfg(not(any(windows, target_os = "illumos")))]
+ pub const GRE: Self = Self(c::IPPROTO_GRE as _);
+ /// `IPPROTO_ESP`
+ #[cfg(not(target_os = "illumos"))]
+ pub const ESP: Self = Self(c::IPPROTO_ESP as _);
+ /// `IPPROTO_AH`
+ #[cfg(not(target_os = "illumos"))]
+ pub const AH: Self = Self(c::IPPROTO_AH as _);
+ /// `IPPROTO_MTP`
+ #[cfg(not(any(
+ windows,
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const MTP: Self = Self(c::IPPROTO_MTP as _);
+ /// `IPPROTO_BEETPH`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const BEETPH: Self = Self(c::IPPROTO_BEETPH as _);
+ /// `IPPROTO_ENCAP`
+ #[cfg(not(any(windows, target_os = "illumos")))]
+ pub const ENCAP: Self = Self(c::IPPROTO_ENCAP as _);
+ /// `IPPROTO_PIM`
+ #[cfg(not(target_os = "illumos"))]
+ pub const PIM: Self = Self(c::IPPROTO_PIM as _);
+ /// `IPPROTO_COMP`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const COMP: Self = Self(c::IPPROTO_COMP as _);
+ /// `IPPROTO_SCTP`
+ #[cfg(not(any(target_os = "dragonfly", target_os = "illumos", target_os = "openbsd")))]
+ pub const SCTP: Self = Self(c::IPPROTO_SCTP as _);
+ /// `IPPROTO_UDPLITE`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const UDPLITE: Self = Self(c::IPPROTO_UDPLITE as _);
+ /// `IPPROTO_MPLS`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ )))]
+ pub const MPLS: Self = Self(c::IPPROTO_MPLS as _);
+ /// `IPPROTO_RAW`
+ pub const RAW: Self = Self(c::IPPROTO_RAW as _);
+ /// `IPPROTO_MPTCP`
+ #[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const MPTCP: Self = Self(c::IPPROTO_MPTCP as _);
+ /// `IPPROTO_FRAGMENT`
+ #[cfg(not(target_os = "illumos"))]
+ pub const FRAGMENT: Self = Self(c::IPPROTO_FRAGMENT as _);
+ /// `IPPROTO_ICMPV6`
+ pub const ICMPV6: Self = Self(c::IPPROTO_ICMPV6 as _);
+ /// `IPPROTO_MH`
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ pub const MH: Self = Self(c::IPPROTO_MH as _);
+ /// `IPPROTO_ROUTING`
+ #[cfg(not(target_os = "illumos"))]
+ pub const ROUTING: Self = Self(c::IPPROTO_ROUTING as _);
+
+ /// Constructs a `Protocol` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawProtocol) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `Protocol`.
+ #[inline]
+ pub const fn as_raw(self) -> RawProtocol {
+ self.0
+ }
+}
+
+/// `SHUT_*` constants for use with [`shutdown`].
+///
+/// [`shutdown`]: crate::net::shutdown
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(i32)]
+pub enum Shutdown {
+ /// `SHUT_RD`—Disable further read operations.
+ Read = c::SHUT_RD,
+ /// `SHUT_WR`—Disable further write operations.
+ Write = c::SHUT_WR,
+ /// `SHUT_RDWR`—Disable further read and write operations.
+ ReadWrite = c::SHUT_RDWR,
+}
+
+bitflags! {
+ /// `SOCK_*` constants for use with [`accept_with`] and [`acceptfrom_with`].
+ ///
+ /// [`accept_with`]: crate::net::accept_with
+ /// [`acceptfrom_with`]: crate::net::acceptfrom_with
+ pub struct AcceptFlags: c::c_int {
+ /// `SOCK_NONBLOCK`
+ #[cfg(not(any(windows, target_os = "ios", target_os = "macos")))]
+ const NONBLOCK = c::SOCK_NONBLOCK;
+
+ /// `SOCK_CLOEXEC`
+ #[cfg(not(any(windows, target_os = "ios", target_os = "macos")))]
+ const CLOEXEC = c::SOCK_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `SOCK_*` constants for use with [`socket`].
+ ///
+ /// [`socket`]: crate::net::socket
+ pub struct SocketFlags: c::c_int {
+ /// `SOCK_NONBLOCK`
+ #[cfg(not(any(windows, target_os = "ios", target_os = "macos")))]
+ const NONBLOCK = c::SOCK_NONBLOCK;
+
+ /// `SOCK_CLOEXEC`
+ #[cfg(not(any(windows, target_os = "ios", target_os = "macos")))]
+ const CLOEXEC = c::SOCK_CLOEXEC;
+ }
+}
+
+/// Timeout identifier for use with [`set_socket_timeout`] and
+/// [`get_socket_timeout`].
+///
+/// [`set_socket_timeout`]: crate::net::sockopt::set_socket_timeout.
+/// [`get_socket_timeout`]: crate::net::sockopt::get_socket_timeout.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(i32)]
+pub enum Timeout {
+ /// `SO_RCVTIMEO`—Timeout for receiving.
+ Recv = c::SO_RCVTIMEO,
+
+ /// `SO_SNDTIMEO`—Timeout for sending.
+ Send = c::SO_SNDTIMEO,
+}
diff --git a/vendor/rustix/src/imp/libc/net/write_sockaddr.rs b/vendor/rustix/src/imp/libc/net/write_sockaddr.rs
new file mode 100644
index 000000000..adbf7255d
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/write_sockaddr.rs
@@ -0,0 +1,96 @@
+//! The BSD sockets API requires us to read the `ss_family` field before
+//! we can interpret the rest of a `sockaddr` produced by the kernel.
+
+use super::super::c;
+use super::addr::SocketAddrStorage;
+#[cfg(unix)]
+use super::addr::SocketAddrUnix;
+use super::ext::{in6_addr_new, in_addr_new, sockaddr_in6_new};
+use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6};
+use core::mem::size_of;
+
+pub(crate) unsafe fn write_sockaddr(
+ addr: &SocketAddrAny,
+ storage: *mut SocketAddrStorage,
+) -> usize {
+ match addr {
+ SocketAddrAny::V4(v4) => write_sockaddr_v4(v4, storage),
+ SocketAddrAny::V6(v6) => write_sockaddr_v6(v6, storage),
+ #[cfg(unix)]
+ SocketAddrAny::Unix(unix) => write_sockaddr_unix(unix, storage),
+ }
+}
+
+pub(crate) unsafe fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in {
+ c::sockaddr_in {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sin_len: size_of::<c::sockaddr_in>() as _,
+ sin_family: c::AF_INET as _,
+ sin_port: u16::to_be(v4.port()),
+ sin_addr: in_addr_new(u32::from_ne_bytes(v4.ip().octets())),
+ sin_zero: [0; 8_usize],
+ }
+}
+
+unsafe fn write_sockaddr_v4(v4: &SocketAddrV4, storage: *mut SocketAddrStorage) -> usize {
+ let encoded = encode_sockaddr_v4(v4);
+ core::ptr::write(storage.cast(), encoded);
+ size_of::<c::sockaddr_in>()
+}
+
+pub(crate) unsafe fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ {
+ sockaddr_in6_new(
+ size_of::<c::sockaddr_in6>() as _,
+ c::AF_INET6 as _,
+ u16::to_be(v6.port()),
+ u32::to_be(v6.flowinfo()),
+ in6_addr_new(v6.ip().octets()),
+ v6.scope_id(),
+ )
+ }
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ {
+ sockaddr_in6_new(
+ c::AF_INET6 as _,
+ u16::to_be(v6.port()),
+ u32::to_be(v6.flowinfo()),
+ in6_addr_new(v6.ip().octets()),
+ v6.scope_id(),
+ )
+ }
+}
+
+unsafe fn write_sockaddr_v6(v6: &SocketAddrV6, storage: *mut SocketAddrStorage) -> usize {
+ let encoded = encode_sockaddr_v6(v6);
+ core::ptr::write(storage.cast(), encoded);
+ size_of::<c::sockaddr_in6>()
+}
+
+#[cfg(unix)]
+unsafe fn write_sockaddr_unix(unix: &SocketAddrUnix, storage: *mut SocketAddrStorage) -> usize {
+ core::ptr::write(storage.cast(), unix.unix);
+ unix.len()
+}
diff --git a/vendor/rustix/src/imp/libc/offset.rs b/vendor/rustix/src/imp/libc/offset.rs
new file mode 100644
index 000000000..3002e8bdd
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/offset.rs
@@ -0,0 +1,361 @@
+//! Automatically enable “large file” support features.
+
+#[cfg(not(windows))]
+use super::c;
+
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+)))]
+pub(super) use c::{
+ fstat as libc_fstat, fstatat as libc_fstatat, ftruncate as libc_ftruncate, lseek as libc_lseek,
+ off_t as libc_off_t,
+};
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+))]
+pub(super) use c::{
+ fstat64 as libc_fstat, fstatat64 as libc_fstatat, ftruncate64 as libc_ftruncate,
+ lseek64 as libc_lseek, off64_t as libc_off_t, rlimit64 as libc_rlimit,
+};
+
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+ target_os = "wasi",
+)))]
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+pub(super) use c::mmap as libc_mmap;
+
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "l4re",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub(super) use c::{rlimit as libc_rlimit, RLIM_INFINITY as LIBC_RLIM_INFINITY};
+
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "emscripten",
+ target_os = "l4re",
+ target_os = "linux",
+ target_os = "wasi",
+)))]
+pub(super) use c::{getrlimit as libc_getrlimit, setrlimit as libc_setrlimit};
+
+// TODO: Add `RLIM64_INFINITY` to upstream libc.
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+))]
+pub(super) const LIBC_RLIM_INFINITY: u64 = !0_u64;
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+))]
+pub(super) use c::{getrlimit64 as libc_getrlimit, setrlimit64 as libc_setrlimit};
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+))]
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+pub(super) use c::mmap64 as libc_mmap;
+
+// `prlimit64` wasn't supported in glibc until 2.13.
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+weak_or_syscall! {
+ fn prlimit64(
+ pid: c::pid_t,
+ resource: c::__rlimit_resource_t,
+ new_limit: *const c::rlimit64,
+ old_limit: *mut c::rlimit64
+ ) via SYS_prlimit64 -> c::c_int
+}
+#[cfg(all(target_os = "linux", target_env = "musl"))]
+weak_or_syscall! {
+ fn prlimit64(
+ pid: c::pid_t,
+ resource: c::c_int,
+ new_limit: *const c::rlimit64,
+ old_limit: *mut c::rlimit64
+ ) via SYS_prlimit64 -> c::c_int
+}
+#[cfg(target_os = "android")]
+weak_or_syscall! {
+ fn prlimit64(
+ pid: c::pid_t,
+ resource: c::c_int,
+ new_limit: *const c::rlimit64,
+ old_limit: *mut c::rlimit64
+ ) via SYS_prlimit64 -> c::c_int
+}
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+pub(super) unsafe fn libc_prlimit(
+ pid: c::pid_t,
+ resource: c::__rlimit_resource_t,
+ new_limit: *const c::rlimit64,
+ old_limit: *mut c::rlimit64,
+) -> c::c_int {
+ prlimit64(pid, resource, new_limit, old_limit)
+}
+#[cfg(all(target_os = "linux", target_env = "musl"))]
+pub(super) unsafe fn libc_prlimit(
+ pid: c::pid_t,
+ resource: c::c_int,
+ new_limit: *const c::rlimit64,
+ old_limit: *mut c::rlimit64,
+) -> c::c_int {
+ prlimit64(pid, resource, new_limit, old_limit)
+}
+#[cfg(target_os = "android")]
+pub(super) unsafe fn libc_prlimit(
+ pid: c::pid_t,
+ resource: c::c_int,
+ new_limit: *const c::rlimit64,
+ old_limit: *mut c::rlimit64,
+) -> c::c_int {
+ prlimit64(pid, resource, new_limit, old_limit)
+}
+
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+ target_os = "redox",
+)))]
+pub(super) use c::openat as libc_openat;
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+))]
+pub(super) use c::openat64 as libc_openat;
+
+#[cfg(target_os = "fuchsia")]
+pub(super) use c::fallocate as libc_fallocate;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(super) use c::fallocate64 as libc_fallocate;
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "l4re",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub(super) use c::posix_fadvise as libc_posix_fadvise;
+#[cfg(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "linux",
+ target_os = "l4re",
+))]
+pub(super) use c::posix_fadvise64 as libc_posix_fadvise;
+
+#[cfg(all(not(any(
+ windows,
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+))))]
+pub(super) use c::{pread as libc_pread, pwrite as libc_pwrite};
+#[cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten"))]
+pub(super) use c::{pread64 as libc_pread, pwrite64 as libc_pwrite};
+#[cfg(any(target_os = "linux", target_os = "emscripten"))]
+pub(super) use c::{preadv64 as libc_preadv, pwritev64 as libc_pwritev};
+#[cfg(target_os = "android")]
+mod readwrite_pv64 {
+ use super::c;
+
+ // 64-bit offsets on 32-bit platforms are passed in endianness-specific
+ // lo/hi pairs. See src/imp/linux_raw/conv.rs for details.
+ #[cfg(all(target_endian = "little", target_pointer_width = "32"))]
+ fn lo(x: u64) -> usize {
+ (x >> 32) as usize
+ }
+ #[cfg(all(target_endian = "little", target_pointer_width = "32"))]
+ fn hi(x: u64) -> usize {
+ (x & 0xffff_ffff) as usize
+ }
+ #[cfg(all(target_endian = "big", target_pointer_width = "32"))]
+ fn lo(x: u64) -> usize {
+ (x & 0xffff_ffff) as usize
+ }
+ #[cfg(all(target_endian = "big", target_pointer_width = "32"))]
+ fn hi(x: u64) -> usize {
+ (x >> 32) as usize
+ }
+
+ pub(in super::super) unsafe fn preadv64(
+ fd: c::c_int,
+ iov: *const c::iovec,
+ iovcnt: c::c_int,
+ offset: c::off64_t,
+ ) -> c::ssize_t {
+ // Older Android libc lacks `preadv64`, so use the `weak!` mechanism to
+ // test for it, and call back to `c::syscall`. We don't use
+ // `weak_or_syscall` here because we need to pass the 64-bit offset
+ // specially.
+ weak! {
+ fn preadv64(c::c_int, *const c::iovec, c::c_int, c::off64_t) -> c::ssize_t
+ }
+ if let Some(fun) = preadv64.get() {
+ fun(fd, iov, iovcnt, offset)
+ } else {
+ #[cfg(target_pointer_width = "32")]
+ {
+ c::syscall(
+ c::SYS_preadv,
+ fd,
+ iov,
+ iovcnt,
+ hi(offset as u64),
+ lo(offset as u64),
+ ) as c::ssize_t
+ }
+ #[cfg(target_pointer_width = "64")]
+ {
+ c::syscall(c::SYS_preadv, fd, iov, iovcnt, offset) as c::ssize_t
+ }
+ }
+ }
+ pub(in super::super) unsafe fn pwritev64(
+ fd: c::c_int,
+ iov: *const c::iovec,
+ iovcnt: c::c_int,
+ offset: c::off64_t,
+ ) -> c::ssize_t {
+ // See the comments in `preadv64`.
+ weak! {
+ fn pwritev64(c::c_int, *const c::iovec, c::c_int, c::off64_t) -> c::ssize_t
+ }
+ if let Some(fun) = pwritev64.get() {
+ fun(fd, iov, iovcnt, offset)
+ } else {
+ #[cfg(target_pointer_width = "32")]
+ {
+ c::syscall(
+ c::SYS_pwritev,
+ fd,
+ iov,
+ iovcnt,
+ hi(offset as u64),
+ lo(offset as u64),
+ ) as c::ssize_t
+ }
+ #[cfg(target_pointer_width = "64")]
+ {
+ c::syscall(c::SYS_pwritev, fd, iov, iovcnt, offset) as c::ssize_t
+ }
+ }
+ }
+}
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub(super) use c::{preadv as libc_preadv, pwritev as libc_pwritev};
+#[cfg(target_os = "android")]
+pub(super) use readwrite_pv64::{preadv64 as libc_preadv, pwritev64 as libc_pwritev};
+// macOS added preadv and pwritev in version 11.0
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+mod readwrite_pv {
+ use super::c;
+
+ weakcall! {
+ pub(in super::super) fn preadv(
+ fd: c::c_int,
+ iov: *const c::iovec,
+ iovcnt: c::c_int,
+ offset: c::off_t
+ ) -> c::ssize_t
+ }
+ weakcall! {
+ pub(in super::super) fn pwritev(
+ fd: c::c_int,
+ iov: *const c::iovec,
+ iovcnt: c::c_int, offset: c::off_t
+ ) -> c::ssize_t
+ }
+}
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+pub(super) use c::{preadv64v2 as libc_preadv2, pwritev64v2 as libc_pwritev2};
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+pub(super) use readwrite_pv::{preadv as libc_preadv, pwritev as libc_pwritev};
+
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "l4re",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub(super) use c::posix_fallocate as libc_posix_fallocate;
+#[cfg(any(target_os = "l4re"))]
+pub(super) use c::posix_fallocate64 as libc_posix_fallocate;
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "linux",
+ target_os = "l4re",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub(super) use {c::fstatfs as libc_fstatfs, c::statfs as libc_statfs};
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+))]
+pub(super) use {c::fstatfs64 as libc_fstatfs, c::statfs64 as libc_statfs};
diff --git a/vendor/rustix/src/imp/libc/param/auxv.rs b/vendor/rustix/src/imp/libc/param/auxv.rs
new file mode 100644
index 000000000..584329da9
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/param/auxv.rs
@@ -0,0 +1,66 @@
+use super::super::c;
+#[cfg(any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+))]
+use crate::ffi::CStr;
+
+// `getauxval` wasn't supported in glibc until 2.16.
+#[cfg(any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+))]
+weak!(fn getauxval(c::c_ulong) -> *mut c::c_void);
+
+#[inline]
+pub(crate) fn page_size() -> usize {
+ unsafe { c::sysconf(c::_SC_PAGESIZE) as usize }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn clock_ticks_per_second() -> u64 {
+ unsafe { c::sysconf(c::_SC_CLK_TCK) as u64 }
+}
+
+#[cfg(any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+))]
+#[inline]
+pub(crate) fn linux_hwcap() -> (usize, usize) {
+ if let Some(libc_getauxval) = getauxval.get() {
+ unsafe {
+ let hwcap = libc_getauxval(c::AT_HWCAP) as usize;
+ let hwcap2 = libc_getauxval(c::AT_HWCAP2) as usize;
+ (hwcap, hwcap2)
+ }
+ } else {
+ (0, 0)
+ }
+}
+
+#[cfg(any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+))]
+#[inline]
+pub(crate) fn linux_execfn() -> &'static CStr {
+ if let Some(libc_getauxval) = getauxval.get() {
+ unsafe { CStr::from_ptr(libc_getauxval(c::AT_EXECFN).cast()) }
+ } else {
+ cstr!("")
+ }
+}
+
+/// Initialize process-wide state.
+#[cfg(any(
+ target_vendor = "mustang",
+ not(any(target_env = "gnu", target_env = "musl")),
+))]
+#[inline]
+#[doc(hidden)]
+pub(crate) unsafe fn init(_envp: *mut *mut u8) {
+ // Nothing to do. This is the libc backend, and libc does the
+ // initialization for us.
+}
diff --git a/vendor/rustix/src/imp/libc/param/mod.rs b/vendor/rustix/src/imp/libc/param/mod.rs
new file mode 100644
index 000000000..2cb2fe78a
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/param/mod.rs
@@ -0,0 +1 @@
+pub(crate) mod auxv;
diff --git a/vendor/rustix/src/imp/libc/process/cpu_set.rs b/vendor/rustix/src/imp/libc/process/cpu_set.rs
new file mode 100644
index 000000000..14ad8d208
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/process/cpu_set.rs
@@ -0,0 +1,49 @@
+#![allow(non_snake_case)]
+
+use super::super::c;
+use super::types::{RawCpuSet, CPU_SETSIZE};
+
+#[inline]
+pub(crate) fn CPU_SET(cpu: usize, cpuset: &mut RawCpuSet) {
+ assert!(
+ cpu < CPU_SETSIZE,
+ "cpu out of bounds: the cpu max is {} but the cpu is {}",
+ CPU_SETSIZE,
+ cpu
+ );
+ unsafe { c::CPU_SET(cpu, cpuset) }
+}
+
+#[inline]
+pub(crate) fn CPU_ZERO(cpuset: &mut RawCpuSet) {
+ unsafe { c::CPU_ZERO(cpuset) }
+}
+
+#[inline]
+pub(crate) fn CPU_CLR(cpu: usize, cpuset: &mut RawCpuSet) {
+ assert!(
+ cpu < CPU_SETSIZE,
+ "cpu out of bounds: the cpu max is {} but the cpu is {}",
+ CPU_SETSIZE,
+ cpu
+ );
+ unsafe { c::CPU_CLR(cpu, cpuset) }
+}
+
+#[inline]
+pub(crate) fn CPU_ISSET(cpu: usize, cpuset: &RawCpuSet) -> bool {
+ assert!(
+ cpu < CPU_SETSIZE,
+ "cpu out of bounds: the cpu max is {} but the cpu is {}",
+ CPU_SETSIZE,
+ cpu
+ );
+ unsafe { c::CPU_ISSET(cpu, cpuset) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub(crate) fn CPU_COUNT(cpuset: &RawCpuSet) -> u32 {
+ use core::convert::TryInto;
+ unsafe { c::CPU_COUNT(cpuset).try_into().unwrap() }
+}
diff --git a/vendor/rustix/src/imp/libc/process/mod.rs b/vendor/rustix/src/imp/libc/process/mod.rs
new file mode 100644
index 000000000..8675c1af9
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/process/mod.rs
@@ -0,0 +1,12 @@
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+pub(crate) mod cpu_set;
+#[cfg(not(windows))]
+pub(crate) mod syscalls;
+pub(crate) mod types;
+#[cfg(not(target_os = "wasi"))]
+pub(crate) mod wait;
diff --git a/vendor/rustix/src/imp/libc/process/syscalls.rs b/vendor/rustix/src/imp/libc/process/syscalls.rs
new file mode 100644
index 000000000..9874f617f
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/process/syscalls.rs
@@ -0,0 +1,419 @@
+//! libc syscalls supporting `rustix::process`.
+
+use super::super::c;
+#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
+use super::super::conv::borrowed_fd;
+use super::super::conv::{c_str, ret, ret_c_int, ret_discarded_char_ptr};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use super::super::conv::{syscall_ret, syscall_ret_u32};
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+use super::types::RawCpuSet;
+#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
+use crate::fd::BorrowedFd;
+use crate::ffi::CStr;
+use crate::io;
+use core::mem::MaybeUninit;
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+use {
+ super::super::conv::ret_infallible,
+ super::super::offset::{libc_getrlimit, libc_rlimit, libc_setrlimit, LIBC_RLIM_INFINITY},
+ crate::process::{Resource, Rlimit},
+ core::convert::TryInto,
+};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use {
+ super::super::offset::libc_prlimit,
+ crate::process::{Cpuid, MembarrierCommand, MembarrierQuery},
+};
+#[cfg(not(target_os = "wasi"))]
+use {
+ super::types::RawUname,
+ crate::process::{Gid, Pid, RawNonZeroPid, RawPid, Signal, Uid, WaitOptions, WaitStatus},
+};
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) fn chdir(path: &CStr) -> io::Result<()> {
+ unsafe { ret(c::chdir(c_str(path))) }
+}
+
+#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
+pub(crate) fn fchdir(dirfd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(c::fchdir(borrowed_fd(dirfd))) }
+}
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) fn getcwd(buf: &mut [u8]) -> io::Result<()> {
+ unsafe { ret_discarded_char_ptr(c::getcwd(buf.as_mut_ptr().cast(), buf.len())) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn membarrier_query() -> MembarrierQuery {
+ // GLIBC does not have a wrapper for `membarrier`; [the documentation]
+ // says to use `syscall`.
+ //
+ // [the documentation]: https://man7.org/linux/man-pages/man2/membarrier.2.html#NOTES
+ const MEMBARRIER_CMD_QUERY: u32 = 0;
+ unsafe {
+ match syscall_ret_u32(c::syscall(c::SYS_membarrier, MEMBARRIER_CMD_QUERY, 0)) {
+ Ok(query) => MembarrierQuery::from_bits_unchecked(query),
+ Err(_) => MembarrierQuery::empty(),
+ }
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn membarrier(cmd: MembarrierCommand) -> io::Result<()> {
+ unsafe { syscall_ret(c::syscall(c::SYS_membarrier, cmd as u32, 0)) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
+ const MEMBARRIER_CMD_FLAG_CPU: u32 = 1;
+ unsafe {
+ syscall_ret(c::syscall(
+ c::SYS_membarrier,
+ cmd as u32,
+ MEMBARRIER_CMD_FLAG_CPU,
+ cpu.as_raw(),
+ ))
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[must_use]
+pub(crate) fn getuid() -> Uid {
+ unsafe {
+ let uid = c::getuid();
+ Uid::from_raw(uid)
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[must_use]
+pub(crate) fn geteuid() -> Uid {
+ unsafe {
+ let uid = c::geteuid();
+ Uid::from_raw(uid)
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[must_use]
+pub(crate) fn getgid() -> Gid {
+ unsafe {
+ let gid = c::getgid();
+ Gid::from_raw(gid)
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[must_use]
+pub(crate) fn getegid() -> Gid {
+ unsafe {
+ let gid = c::getegid();
+ Gid::from_raw(gid)
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[must_use]
+pub(crate) fn getpid() -> Pid {
+ unsafe {
+ let pid = c::getpid();
+ debug_assert_ne!(pid, 0);
+ Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid))
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[must_use]
+pub(crate) fn getppid() -> Option<Pid> {
+ unsafe {
+ let pid: i32 = c::getppid();
+ Pid::from_raw(pid)
+ }
+}
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+#[inline]
+pub(crate) fn sched_getaffinity(pid: Option<Pid>, cpuset: &mut RawCpuSet) -> io::Result<()> {
+ unsafe {
+ ret(c::sched_getaffinity(
+ Pid::as_raw(pid) as _,
+ core::mem::size_of::<RawCpuSet>(),
+ cpuset,
+ ))
+ }
+}
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+#[inline]
+pub(crate) fn sched_setaffinity(pid: Option<Pid>, cpuset: &RawCpuSet) -> io::Result<()> {
+ unsafe {
+ ret(c::sched_setaffinity(
+ Pid::as_raw(pid) as _,
+ core::mem::size_of::<RawCpuSet>(),
+ cpuset,
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn sched_yield() {
+ unsafe {
+ let _ = c::sched_yield();
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn uname() -> RawUname {
+ let mut uname = MaybeUninit::<RawUname>::uninit();
+ unsafe {
+ ret(c::uname(uname.as_mut_ptr())).unwrap();
+ uname.assume_init()
+ }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+#[inline]
+pub(crate) fn nice(inc: i32) -> io::Result<i32> {
+ libc_errno::set_errno(libc_errno::Errno(0));
+ let r = unsafe { c::nice(inc) };
+ if libc_errno::errno().0 != 0 {
+ ret_c_int(r)
+ } else {
+ Ok(r)
+ }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub(crate) fn getpriority_user(uid: Uid) -> io::Result<i32> {
+ libc_errno::set_errno(libc_errno::Errno(0));
+ let r = unsafe { c::getpriority(c::PRIO_USER, uid.as_raw() as _) };
+ if libc_errno::errno().0 != 0 {
+ ret_c_int(r)
+ } else {
+ Ok(r)
+ }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub(crate) fn getpriority_pgrp(pgid: Option<Pid>) -> io::Result<i32> {
+ libc_errno::set_errno(libc_errno::Errno(0));
+ let r = unsafe { c::getpriority(c::PRIO_PGRP, Pid::as_raw(pgid) as _) };
+ if libc_errno::errno().0 != 0 {
+ ret_c_int(r)
+ } else {
+ Ok(r)
+ }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub(crate) fn getpriority_process(pid: Option<Pid>) -> io::Result<i32> {
+ libc_errno::set_errno(libc_errno::Errno(0));
+ let r = unsafe { c::getpriority(c::PRIO_PROCESS, Pid::as_raw(pid) as _) };
+ if libc_errno::errno().0 != 0 {
+ ret_c_int(r)
+ } else {
+ Ok(r)
+ }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub(crate) fn setpriority_user(uid: Uid, priority: i32) -> io::Result<()> {
+ unsafe { ret(c::setpriority(c::PRIO_USER, uid.as_raw() as _, priority)) }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub(crate) fn setpriority_pgrp(pgid: Option<Pid>, priority: i32) -> io::Result<()> {
+ unsafe {
+ ret(c::setpriority(
+ c::PRIO_PGRP,
+ Pid::as_raw(pgid) as _,
+ priority,
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub(crate) fn setpriority_process(pid: Option<Pid>, priority: i32) -> io::Result<()> {
+ unsafe {
+ ret(c::setpriority(
+ c::PRIO_PROCESS,
+ Pid::as_raw(pid) as _,
+ priority,
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub(crate) fn getrlimit(limit: Resource) -> Rlimit {
+ let mut result = MaybeUninit::<libc_rlimit>::uninit();
+ unsafe {
+ ret_infallible(libc_getrlimit(limit as _, result.as_mut_ptr()));
+ rlimit_from_libc(result.assume_init())
+ }
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[inline]
+pub(crate) fn setrlimit(limit: Resource, new: Rlimit) -> io::Result<()> {
+ let lim = rlimit_to_libc(new)?;
+ unsafe { ret(libc_setrlimit(limit as _, &lim)) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub(crate) fn prlimit(pid: Option<Pid>, limit: Resource, new: Rlimit) -> io::Result<Rlimit> {
+ let lim = rlimit_to_libc(new)?;
+ let mut result = MaybeUninit::<libc_rlimit>::uninit();
+ unsafe {
+ ret(libc_prlimit(
+ Pid::as_raw(pid),
+ limit as _,
+ &lim,
+ result.as_mut_ptr(),
+ ))
+ .map(|()| rlimit_from_libc(result.assume_init()))
+ }
+}
+
+/// Convert a Rust [`Rlimit`] to a C `libc_rlimit`.
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+fn rlimit_from_libc(lim: libc_rlimit) -> Rlimit {
+ let current = if lim.rlim_cur == LIBC_RLIM_INFINITY {
+ None
+ } else {
+ Some(lim.rlim_cur.try_into().unwrap())
+ };
+ let maximum = if lim.rlim_max == LIBC_RLIM_INFINITY {
+ None
+ } else {
+ Some(lim.rlim_max.try_into().unwrap())
+ };
+ Rlimit { current, maximum }
+}
+
+/// Convert a C `libc_rlimit` to a Rust `Rlimit`.
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+fn rlimit_to_libc(lim: Rlimit) -> io::Result<libc_rlimit> {
+ let Rlimit { current, maximum } = lim;
+ let rlim_cur = match current {
+ Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?,
+ None => LIBC_RLIM_INFINITY as _,
+ };
+ let rlim_max = match maximum {
+ Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?,
+ None => LIBC_RLIM_INFINITY as _,
+ };
+ Ok(libc_rlimit { rlim_cur, rlim_max })
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn wait(waitopts: WaitOptions) -> io::Result<Option<(Pid, WaitStatus)>> {
+ _waitpid(!0, waitopts)
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn waitpid(
+ pid: Option<Pid>,
+ waitopts: WaitOptions,
+) -> io::Result<Option<(Pid, WaitStatus)>> {
+ _waitpid(Pid::as_raw(pid), waitopts)
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn _waitpid(
+ pid: RawPid,
+ waitopts: WaitOptions,
+) -> io::Result<Option<(Pid, WaitStatus)>> {
+ unsafe {
+ let mut status: c::c_int = 0;
+ let pid = ret_c_int(c::waitpid(pid as _, &mut status, waitopts.bits() as _))?;
+ Ok(RawNonZeroPid::new(pid).map(|non_zero| {
+ (
+ Pid::from_raw_nonzero(non_zero),
+ WaitStatus::new(status as _),
+ )
+ }))
+ }
+}
+
+#[inline]
+pub(crate) fn exit_group(code: c::c_int) -> ! {
+ // `_exit` and `_Exit` are the same; it's just a matter of which ones
+ // the libc bindings expose.
+ #[cfg(any(target_os = "wasi", target_os = "solid"))]
+ unsafe {
+ c::_Exit(code)
+ }
+ #[cfg(unix)]
+ unsafe {
+ c::_exit(code)
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn setsid() -> io::Result<Pid> {
+ unsafe {
+ let pid = ret_c_int(c::setsid())?;
+ debug_assert_ne!(pid, 0);
+ Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)))
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn kill_process(pid: Pid, sig: Signal) -> io::Result<()> {
+ unsafe { ret(c::kill(pid.as_raw_nonzero().get(), sig as i32)) }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn kill_process_group(pid: Pid, sig: Signal) -> io::Result<()> {
+ unsafe {
+ ret(c::kill(
+ pid.as_raw_nonzero().get().wrapping_neg(),
+ sig as i32,
+ ))
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn kill_current_process_group(sig: Signal) -> io::Result<()> {
+ unsafe { ret(c::kill(0, sig as i32)) }
+}
diff --git a/vendor/rustix/src/imp/libc/process/types.rs b/vendor/rustix/src/imp/libc/process/types.rs
new file mode 100644
index 000000000..60d629d81
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/process/types.rs
@@ -0,0 +1,361 @@
+use super::super::c;
+
+/// A command for use with [`membarrier`] and [`membarrier_cpu`].
+///
+/// For `MEMBARRIER_CMD_QUERY`, see [`membarrier_query`].
+///
+/// [`membarrier`]: crate::process::membarrier
+/// [`membarrier_cpu`]: crate::process::membarrier_cpu
+/// [`membarrier_query`]: crate::process::membarrier_query
+// TODO: These are not yet exposed through libc, so we define the
+// constants ourselves.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+#[repr(u32)]
+pub enum MembarrierCommand {
+ /// `MEMBARRIER_CMD_GLOBAL`
+ #[doc(alias = "Shared")]
+ #[doc(alias = "MEMBARRIER_CMD_SHARED")]
+ Global = 1,
+ /// `MEMBARRIER_CMD_GLOBAL_EXPEDITED`
+ GlobalExpedited = 2,
+ /// `MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED`
+ RegisterGlobalExpedited = 4,
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED`
+ PrivateExpedited = 8,
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED`
+ RegisterPrivateExpedited = 16,
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE`
+ PrivateExpeditedSyncCore = 32,
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE`
+ RegisterPrivateExpeditedSyncCore = 64,
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
+ PrivateExpeditedRseq = 128,
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
+ RegisterPrivateExpeditedRseq = 256,
+}
+
+/// A resource value for use with [`getrlimit`], [`setrlimit`], and
+/// [`prlimit`].
+///
+/// [`getrlimit`]: crate::process::getrlimit
+/// [`setrlimit`]: crate::process::setrlimit
+/// [`prlimit`]: crate::process::prlimit
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[repr(i32)]
+pub enum Resource {
+ /// `RLIMIT_CPU`
+ Cpu = c::RLIMIT_CPU as c::c_int,
+ /// `RLIMIT_FSIZE`
+ Fsize = c::RLIMIT_FSIZE as c::c_int,
+ /// `RLIMIT_DATA`
+ Data = c::RLIMIT_DATA as c::c_int,
+ /// `RLIMIT_STACK`
+ Stack = c::RLIMIT_STACK as c::c_int,
+ /// `RLIMIT_CORE`
+ Core = c::RLIMIT_CORE as c::c_int,
+ /// `RLIMIT_RSS`
+ #[cfg(not(any(target_os = "illumos", target_os = "ios", target_os = "macos")))]
+ Rss = c::RLIMIT_RSS as c::c_int,
+ /// `RLIMIT_NPROC`
+ #[cfg(not(target_os = "illumos"))]
+ Nproc = c::RLIMIT_NPROC as c::c_int,
+ /// `RLIMIT_NOFILE`
+ Nofile = c::RLIMIT_NOFILE as c::c_int,
+ /// `RLIMIT_MEMLOCK`
+ #[cfg(not(target_os = "illumos"))]
+ Memlock = c::RLIMIT_MEMLOCK as c::c_int,
+ /// `RLIMIT_AS`
+ #[cfg(not(target_os = "openbsd"))]
+ As = c::RLIMIT_AS as c::c_int,
+ /// `RLIMIT_LOCKS`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ Locks = c::RLIMIT_LOCKS as c::c_int,
+ /// `RLIMIT_SIGPENDING`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ Sigpending = c::RLIMIT_SIGPENDING as c::c_int,
+ /// `RLIMIT_MSGQUEUE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ Msgqueue = c::RLIMIT_MSGQUEUE as c::c_int,
+ /// `RLIMIT_NICE`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ Nice = c::RLIMIT_NICE as c::c_int,
+ /// `RLIMIT_RTPRIO`
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ Rtprio = c::RLIMIT_RTPRIO as c::c_int,
+ /// `RLIMIT_RTTIME`
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ Rttime = c::RLIMIT_RTTIME as c::c_int,
+}
+
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+impl Resource {
+ /// `RLIMIT_RSS`
+ #[allow(non_upper_case_globals)]
+ pub const Rss: Self = Self::As;
+}
+
+/// A signal number for use with [`kill_process`], [`kill_process_group`],
+/// and [`kill_current_process_group`].
+///
+/// [`kill_process`]: crate::process::kill_process
+/// [`kill_process_group`]: crate::process::kill_process_group
+/// [`kill_current_process_group`]: crate::process::kill_current_process_group
+#[cfg(not(target_os = "wasi"))]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[repr(i32)]
+pub enum Signal {
+ /// `SIGHUP`
+ Hup = c::SIGHUP,
+ /// `SIGINT`
+ Int = c::SIGINT,
+ /// `SIGQUIT`
+ Quit = c::SIGQUIT,
+ /// `SIGILL`
+ Ill = c::SIGILL,
+ /// `SIGTRAP`
+ Trap = c::SIGTRAP,
+ /// `SIGABRT`, aka `SIGIOT`
+ #[doc(alias = "Iot")]
+ #[doc(alias = "Abrt")]
+ Abort = c::SIGABRT,
+ /// `SIGBUS`
+ Bus = c::SIGBUS,
+ /// `SIGFPE`
+ Fpe = c::SIGFPE,
+ /// `SIGKILL`
+ Kill = c::SIGKILL,
+ /// `SIGUSR1`
+ Usr1 = c::SIGUSR1,
+ /// `SIGSEGV`
+ Segv = c::SIGSEGV,
+ /// `SIGUSR2`
+ Usr2 = c::SIGUSR2,
+ /// `SIGPIPE`
+ Pipe = c::SIGPIPE,
+ /// `SIGALRM`
+ #[doc(alias = "Alrm")]
+ Alarm = c::SIGALRM,
+ /// `SIGTERM`
+ Term = c::SIGTERM,
+ /// `SIGSTKFLT`
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_arch = "mips", target_arch = "mips64"),
+ )
+ )))]
+ Stkflt = c::SIGSTKFLT,
+ /// `SIGCHLD`
+ #[doc(alias = "Chld")]
+ Child = c::SIGCHLD,
+ /// `SIGCONT`
+ Cont = c::SIGCONT,
+ /// `SIGSTOP`
+ Stop = c::SIGSTOP,
+ /// `SIGTSTP`
+ Tstp = c::SIGTSTP,
+ /// `SIGTTIN`
+ Ttin = c::SIGTTIN,
+ /// `SIGTTOU`
+ Ttou = c::SIGTTOU,
+ /// `SIGURG`
+ Urg = c::SIGURG,
+ /// `SIGXCPU`
+ Xcpu = c::SIGXCPU,
+ /// `SIGXFSZ`
+ Xfsz = c::SIGXFSZ,
+ /// `SIGVTALRM`
+ #[doc(alias = "Vtalrm")]
+ Vtalarm = c::SIGVTALRM,
+ /// `SIGPROF`
+ Prof = c::SIGPROF,
+ /// `SIGWINCH`
+ Winch = c::SIGWINCH,
+ /// `SIGIO`, aka `SIGPOLL`
+ #[doc(alias = "Poll")]
+ Io = c::SIGIO,
+ /// `SIGPWR`
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ #[doc(alias = "Pwr")]
+ Power = c::SIGPWR,
+ /// `SIGSYS`, aka `SIGUNUSED`
+ #[doc(alias = "Unused")]
+ Sys = c::SIGSYS,
+}
+
+#[cfg(not(target_os = "wasi"))]
+impl Signal {
+ /// Convert a raw signal number into a `Signal`, if possible.
+ pub fn from_raw(sig: i32) -> Option<Self> {
+ match sig as _ {
+ c::SIGHUP => Some(Self::Hup),
+ c::SIGINT => Some(Self::Int),
+ c::SIGQUIT => Some(Self::Quit),
+ c::SIGILL => Some(Self::Ill),
+ c::SIGTRAP => Some(Self::Trap),
+ c::SIGABRT => Some(Self::Abort),
+ c::SIGBUS => Some(Self::Bus),
+ c::SIGFPE => Some(Self::Fpe),
+ c::SIGKILL => Some(Self::Kill),
+ c::SIGUSR1 => Some(Self::Usr1),
+ c::SIGSEGV => Some(Self::Segv),
+ c::SIGUSR2 => Some(Self::Usr2),
+ c::SIGPIPE => Some(Self::Pipe),
+ c::SIGALRM => Some(Self::Alarm),
+ c::SIGTERM => Some(Self::Term),
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ all(
+ any(target_os = "android", target_os = "linux"),
+ any(target_arch = "mips", target_arch = "mips64"),
+ )
+ )))]
+ c::SIGSTKFLT => Some(Self::Stkflt),
+ c::SIGCHLD => Some(Self::Child),
+ c::SIGCONT => Some(Self::Cont),
+ c::SIGSTOP => Some(Self::Stop),
+ c::SIGTSTP => Some(Self::Tstp),
+ c::SIGTTIN => Some(Self::Ttin),
+ c::SIGTTOU => Some(Self::Ttou),
+ c::SIGURG => Some(Self::Urg),
+ c::SIGXCPU => Some(Self::Xcpu),
+ c::SIGXFSZ => Some(Self::Xfsz),
+ c::SIGVTALRM => Some(Self::Vtalarm),
+ c::SIGPROF => Some(Self::Prof),
+ c::SIGWINCH => Some(Self::Winch),
+ c::SIGIO => Some(Self::Io),
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ c::SIGPWR => Some(Self::Power),
+ c::SIGSYS => Some(Self::Sys),
+ _ => None,
+ }
+ }
+}
+
+pub const EXIT_SUCCESS: c::c_int = c::EXIT_SUCCESS;
+pub const EXIT_FAILURE: c::c_int = c::EXIT_FAILURE;
+#[cfg(not(target_os = "wasi"))]
+pub const EXIT_SIGNALED_SIGABRT: c::c_int = 128 + c::SIGABRT;
+
+/// A process identifier as a raw integer.
+#[cfg(not(target_os = "wasi"))]
+pub type RawPid = c::pid_t;
+/// A non-zero process identifier as a raw non-zero integer.
+#[cfg(not(target_os = "wasi"))]
+pub type RawNonZeroPid = core::num::NonZeroI32;
+/// A group identifier as a raw integer.
+#[cfg(not(target_os = "wasi"))]
+pub type RawGid = c::gid_t;
+/// A user identifier as a raw integer.
+#[cfg(not(target_os = "wasi"))]
+pub type RawUid = c::uid_t;
+/// A CPU identifier as a raw integer.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub type RawCpuid = u32;
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) type RawUname = c::utsname;
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+pub(crate) type RawCpuSet = c::cpu_set_t;
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+#[inline]
+pub(crate) fn raw_cpu_set_new() -> RawCpuSet {
+ let mut set = unsafe { core::mem::zeroed() };
+ super::cpu_set::CPU_ZERO(&mut set);
+ set
+}
+
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+pub(crate) const CPU_SETSIZE: usize = c::CPU_SETSIZE as usize;
diff --git a/vendor/rustix/src/imp/libc/process/wait.rs b/vendor/rustix/src/imp/libc/process/wait.rs
new file mode 100644
index 000000000..6de79955d
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/process/wait.rs
@@ -0,0 +1,6 @@
+use super::super::c;
+
+pub(crate) use c::{
+ WCONTINUED, WEXITSTATUS, WIFCONTINUED, WIFEXITED, WIFSIGNALED, WIFSTOPPED, WNOHANG, WSTOPSIG,
+ WTERMSIG, WUNTRACED,
+};
diff --git a/vendor/rustix/src/imp/libc/rand/mod.rs b/vendor/rustix/src/imp/libc/rand/mod.rs
new file mode 100644
index 000000000..1e0181a99
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/rand/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/libc/rand/syscalls.rs b/vendor/rustix/src/imp/libc/rand/syscalls.rs
new file mode 100644
index 000000000..1c4286235
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/rand/syscalls.rs
@@ -0,0 +1,16 @@
+//! libc syscalls supporting `rustix::rand`.
+
+#[cfg(target_os = "linux")]
+use {super::super::c, super::super::conv::ret_ssize_t, crate::io, crate::rand::GetRandomFlags};
+
+#[cfg(target_os = "linux")]
+pub(crate) fn getrandom(buf: &mut [u8], flags: GetRandomFlags) -> io::Result<usize> {
+ // `getrandom` wasn't supported in glibc until 2.25.
+ weak_or_syscall! {
+ fn getrandom(buf: *mut c::c_void, buflen: c::size_t, flags: c::c_uint) via SYS_getrandom -> c::ssize_t
+ }
+
+ let nread =
+ unsafe { ret_ssize_t(getrandom(buf.as_mut_ptr().cast(), buf.len(), flags.bits()))? };
+ Ok(nread as usize)
+}
diff --git a/vendor/rustix/src/imp/libc/rand/types.rs b/vendor/rustix/src/imp/libc/rand/types.rs
new file mode 100644
index 000000000..2ba3f1119
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/rand/types.rs
@@ -0,0 +1,19 @@
+#[cfg(target_os = "linux")]
+use super::super::c;
+#[cfg(target_os = "linux")]
+use bitflags::bitflags;
+
+#[cfg(target_os = "linux")]
+bitflags! {
+ /// `GRND_*` flags for use with [`getrandom`].
+ ///
+ /// [`getrandom`]: crate::rand::getrandom
+ pub struct GetRandomFlags: u32 {
+ /// `GRND_RANDOM`
+ const RANDOM = c::GRND_RANDOM;
+ /// `GRND_NONBLOCK`
+ const NONBLOCK = c::GRND_NONBLOCK;
+ /// `GRND_INSECURE`
+ const INSECURE = c::GRND_INSECURE;
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/termios/mod.rs b/vendor/rustix/src/imp/libc/termios/mod.rs
new file mode 100644
index 000000000..1e0181a99
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/termios/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/libc/termios/syscalls.rs b/vendor/rustix/src/imp/libc/termios/syscalls.rs
new file mode 100644
index 000000000..91b01b4a1
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/termios/syscalls.rs
@@ -0,0 +1,159 @@
+//! libc syscalls supporting `rustix::termios`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp::syscalls` module documentation for details.
+
+#![allow(unsafe_code)]
+
+use super::super::c;
+use super::super::conv::{borrowed_fd, ret, ret_pid_t};
+use crate::fd::BorrowedFd;
+#[cfg(feature = "procfs")]
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+use crate::ffi::CStr;
+use crate::io;
+use crate::process::{Pid, RawNonZeroPid};
+use crate::termios::{Action, OptionalActions, QueueSelector, Speed, Termios, Winsize};
+use core::mem::MaybeUninit;
+use libc_errno::errno;
+
+pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
+ let mut result = MaybeUninit::<Termios>::uninit();
+ unsafe {
+ ret(c::tcgetattr(borrowed_fd(fd), result.as_mut_ptr())).map(|()| result.assume_init())
+ }
+}
+
+pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
+ unsafe {
+ let pid = ret_pid_t(c::tcgetpgrp(borrowed_fd(fd)))?;
+ debug_assert_ne!(pid, 0);
+ Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)))
+ }
+}
+
+pub(crate) fn tcsetpgrp(fd: BorrowedFd<'_>, pid: Pid) -> io::Result<()> {
+ unsafe { ret(c::tcsetpgrp(borrowed_fd(fd), pid.as_raw_nonzero().get())) }
+}
+
+pub(crate) fn tcsetattr(
+ fd: BorrowedFd,
+ optional_actions: OptionalActions,
+ termios: &Termios,
+) -> io::Result<()> {
+ unsafe {
+ ret(c::tcsetattr(
+ borrowed_fd(fd),
+ optional_actions as _,
+ termios,
+ ))
+ }
+}
+
+pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
+ unsafe { ret(c::tcsendbreak(borrowed_fd(fd), 0)) }
+}
+
+pub(crate) fn tcdrain(fd: BorrowedFd) -> io::Result<()> {
+ unsafe { ret(c::tcdrain(borrowed_fd(fd))) }
+}
+
+pub(crate) fn tcflush(fd: BorrowedFd, queue_selector: QueueSelector) -> io::Result<()> {
+ unsafe { ret(c::tcflush(borrowed_fd(fd), queue_selector as _)) }
+}
+
+pub(crate) fn tcflow(fd: BorrowedFd, action: Action) -> io::Result<()> {
+ unsafe { ret(c::tcflow(borrowed_fd(fd), action as _)) }
+}
+
+pub(crate) fn tcgetsid(fd: BorrowedFd) -> io::Result<Pid> {
+ unsafe {
+ let pid = ret_pid_t(c::tcgetsid(borrowed_fd(fd)))?;
+ debug_assert_ne!(pid, 0);
+ Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)))
+ }
+}
+
+pub(crate) fn tcsetwinsize(fd: BorrowedFd, winsize: Winsize) -> io::Result<()> {
+ unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCSWINSZ, &winsize)) }
+}
+
+pub(crate) fn tcgetwinsize(fd: BorrowedFd) -> io::Result<Winsize> {
+ unsafe {
+ let mut buf = MaybeUninit::<Winsize>::uninit();
+ ret(c::ioctl(
+ borrowed_fd(fd),
+ c::TIOCGWINSZ.into(),
+ buf.as_mut_ptr(),
+ ))?;
+ Ok(buf.assume_init())
+ }
+}
+
+#[inline]
+#[must_use]
+pub(crate) fn cfgetospeed(termios: &Termios) -> Speed {
+ unsafe { c::cfgetospeed(termios) }
+}
+
+#[inline]
+#[must_use]
+pub(crate) fn cfgetispeed(termios: &Termios) -> Speed {
+ unsafe { c::cfgetispeed(termios) }
+}
+
+#[inline]
+pub(crate) fn cfmakeraw(termios: &mut Termios) {
+ unsafe { c::cfmakeraw(termios) }
+}
+
+#[inline]
+pub(crate) fn cfsetospeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
+ unsafe { ret(c::cfsetospeed(termios, speed)) }
+}
+
+#[inline]
+pub(crate) fn cfsetispeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
+ unsafe { ret(c::cfsetispeed(termios, speed)) }
+}
+
+#[inline]
+pub(crate) fn cfsetspeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
+ unsafe { ret(c::cfsetspeed(termios, speed)) }
+}
+
+pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool {
+ let res = unsafe { c::isatty(borrowed_fd(fd)) };
+ if res == 0 {
+ match errno().0 {
+ #[cfg(not(any(target_os = "android", target_os = "linux")))]
+ c::ENOTTY => false,
+
+ // Old Linux versions reportedly return `EINVAL`.
+ // <https://man7.org/linux/man-pages/man3/isatty.3.html#ERRORS>
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ c::ENOTTY | c::EINVAL => false,
+
+ // Darwin mysteriously returns `EOPNOTSUPP` sometimes.
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ c::EOPNOTSUPP => false,
+
+ err => panic!("unexpected error from isatty: {:?}", err),
+ }
+ } else {
+ true
+ }
+}
+
+#[cfg(feature = "procfs")]
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+pub(crate) fn ttyname(dirfd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize> {
+ unsafe {
+ // `ttyname_r` returns its error status rather than using `errno`.
+ match c::ttyname_r(borrowed_fd(dirfd), buf.as_mut_ptr().cast(), buf.len()) {
+ 0 => Ok(CStr::from_ptr(buf.as_ptr().cast()).to_bytes().len()),
+ err => Err(io::Errno::from_raw_os_error(err)),
+ }
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/termios/types.rs b/vendor/rustix/src/imp/libc/termios/types.rs
new file mode 100644
index 000000000..7e6728755
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/termios/types.rs
@@ -0,0 +1,951 @@
+use super::super::c;
+
+/// `TCSA*` values for use with [`tcsetattr`].
+///
+/// [`tcsetattr`]: crate::termios::tcsetattr
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(i32)]
+pub enum OptionalActions {
+ /// `TCSANOW`—Make the change immediately.
+ Now = c::TCSANOW,
+
+ /// `TCSADRAIN`—Make the change after all output has been transmitted.
+ Drain = c::TCSADRAIN,
+
+ /// `TCSAFLUSH`—Discard any pending input and then make the change
+ /// after all output has been transmitted.
+ Flush = c::TCSAFLUSH,
+}
+
+/// `TC*` values for use with [`tcflush`].
+///
+/// [`tcflush`]: crate::termios::tcflush
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(i32)]
+pub enum QueueSelector {
+ /// `TCIFLUSH`—Flush data received but not read.
+ IFlush = c::TCIFLUSH,
+
+ /// `TCOFLUSH`—Flush data written but not transmitted.
+ OFlush = c::TCOFLUSH,
+
+ /// `TCIOFLUSH`—`IFlush` and `OFlush` combined.
+ IOFlush = c::TCIOFLUSH,
+}
+
+/// `TC*` values for use with [`tcflow`].
+///
+/// [`tcflow`]: crate::termios::tcflow
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(i32)]
+pub enum Action {
+ /// `TCOOFF`—Suspend output.
+ OOff = c::TCOOFF,
+
+ /// `TCOON`—Restart suspended output.
+ OOn = c::TCOON,
+
+ /// `TCIOFF`—Transmits a STOP byte.
+ IOff = c::TCIOFF,
+
+ /// `TCION`—Transmits a START byte.
+ IOn = c::TCION,
+}
+
+/// `struct termios` for use with [`tcgetattr`].
+///
+/// [`tcgetattr`]: crate::termios::tcgetattr
+pub type Termios = c::termios;
+
+/// `struct winsize` for use with [`tcgetwinsize`].
+///
+/// [`tcgetwinsize`]: crate::termios::tcgetwinsize
+pub type Winsize = c::winsize;
+
+/// `tcflag_t`—A type for the flags fields of [`Termios`].
+pub type Tcflag = c::tcflag_t;
+
+/// `speed_t`—A return type for [`cfsetspeed`] and similar.
+///
+/// [`cfsetspeed`]: crate::termios::cfsetspeed
+pub type Speed = c::speed_t;
+
+/// `VINTR`
+pub const VINTR: usize = c::VINTR as usize;
+
+/// `VQUIT`
+pub const VQUIT: usize = c::VQUIT as usize;
+
+/// `VERASE`
+pub const VERASE: usize = c::VERASE as usize;
+
+/// `VKILL`
+pub const VKILL: usize = c::VKILL as usize;
+
+/// `VEOF`
+pub const VEOF: usize = c::VEOF as usize;
+
+/// `VTIME`
+pub const VTIME: usize = c::VTIME as usize;
+
+/// `VMIN`
+pub const VMIN: usize = c::VMIN as usize;
+
+/// `VSWTC`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const VSWTC: usize = c::VSWTC as usize;
+
+/// `VSTART`
+pub const VSTART: usize = c::VSTART as usize;
+
+/// `VSTOP`
+pub const VSTOP: usize = c::VSTOP as usize;
+
+/// `VSUSP`
+pub const VSUSP: usize = c::VSUSP as usize;
+
+/// `VEOL`
+pub const VEOL: usize = c::VEOL as usize;
+
+/// `VREPRINT`
+pub const VREPRINT: usize = c::VREPRINT as usize;
+
+/// `VDISCARD`
+pub const VDISCARD: usize = c::VDISCARD as usize;
+
+/// `VWERASE`
+pub const VWERASE: usize = c::VWERASE as usize;
+
+/// `VLNEXT`
+pub const VLNEXT: usize = c::VLNEXT as usize;
+
+/// `VEOL2`
+pub const VEOL2: usize = c::VEOL2 as usize;
+
+/// `IGNBRK`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const IGNBRK: c::c_uint = c::IGNBRK;
+
+/// `BRKINT`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const BRKINT: c::c_uint = c::BRKINT;
+
+/// `IGNPAR`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const IGNPAR: c::c_uint = c::IGNPAR;
+
+/// `PARMRK`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const PARMRK: c::c_uint = c::PARMRK;
+
+/// `INPCK`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const INPCK: c::c_uint = c::INPCK;
+
+/// `ISTRIP`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ISTRIP: c::c_uint = c::ISTRIP;
+
+/// `INLCR`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const INLCR: c::c_uint = c::INLCR;
+
+/// `IGNCR`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const IGNCR: c::c_uint = c::IGNCR;
+
+/// `ICRNL`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ICRNL: c::c_uint = c::ICRNL;
+
+/// `IUCLC`
+#[cfg(any(target_os = "haiku", target_os = "illumos", target_os = "solaris"))]
+pub const IUCLC: c::c_uint = c::IUCLC;
+
+/// `IXON`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const IXON: c::c_uint = c::IXON;
+
+/// `IXANY`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const IXANY: c::c_uint = c::IXANY;
+
+/// `IXOFF`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const IXOFF: c::c_uint = c::IXOFF;
+
+/// `IMAXBEL`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const IMAXBEL: c::c_uint = c::IMAXBEL;
+
+/// `IUTF8`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const IUTF8: c::c_uint = c::IUTF8;
+
+/// `OPOST`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const OPOST: c::c_uint = c::OPOST;
+
+/// `OLCUC`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "redox",
+)))]
+pub const OLCUC: c::c_uint = c::OLCUC;
+
+/// `ONLCR`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ONLCR: c::c_uint = c::ONLCR;
+
+/// `OCRNL`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const OCRNL: c::c_uint = c::OCRNL;
+
+/// `ONOCR`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ONOCR: c::c_uint = c::ONOCR;
+
+/// `ONLRET`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ONLRET: c::c_uint = c::ONLRET;
+
+/// `OFILL`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const OFILL: c::c_uint = c::OFILL;
+
+/// `OFDEL`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const OFDEL: c::c_uint = c::OFDEL;
+
+/// `NLDLY`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const NLDLY: c::c_uint = c::NLDLY;
+
+/// `NL0`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const NL0: c::c_uint = c::NL0;
+
+/// `NL1`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const NL1: c::c_uint = c::NL1;
+
+/// `CRDLY`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const CRDLY: c::c_uint = c::CRDLY;
+
+/// `CR0`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const CR0: c::c_uint = c::CR0;
+
+/// `CR1`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const CR1: c::c_uint = c::CR1;
+
+/// `CR2`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const CR2: c::c_uint = c::CR2;
+
+/// `CR3`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const CR3: c::c_uint = c::CR3;
+
+/// `TABDLY`
+#[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "illumos",
+ target_os = "redox",
+)))]
+pub const TABDLY: c::c_uint = c::TABDLY;
+
+/// `TAB0`
+#[cfg(not(any(
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const TAB0: c::c_uint = c::TAB0;
+
+/// `TAB1`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const TAB1: c::c_uint = c::TAB1;
+
+/// `TAB2`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const TAB2: c::c_uint = c::TAB2;
+
+/// `TAB3`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const TAB3: c::c_uint = c::TAB3;
+
+/// `BSDLY`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const BSDLY: c::c_uint = c::BSDLY;
+
+/// `BS0`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const BS0: c::c_uint = c::BS0;
+
+/// `BS1`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "emscripten",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const BS1: c::c_uint = c::BS1;
+
+/// `FFDLY`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const FFDLY: c::c_uint = c::FFDLY;
+
+/// `FF0`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const FF0: c::c_uint = c::FF0;
+
+/// `FF1`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const FF1: c::c_uint = c::FF1;
+
+/// `VTDLY`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const VTDLY: c::c_uint = c::VTDLY;
+
+/// `VT0`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const VT0: c::c_uint = c::VT0;
+
+/// `VT1`
+#[cfg(not(any(
+ target_env = "musl",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const VT1: c::c_uint = c::VT1;
+
+/// `B0`
+pub const B0: Speed = c::B0;
+
+/// `B50`
+pub const B50: Speed = c::B50;
+
+/// `B75`
+pub const B75: Speed = c::B75;
+
+/// `B110`
+pub const B110: Speed = c::B110;
+
+/// `B134`
+pub const B134: Speed = c::B134;
+
+/// `B150`
+pub const B150: Speed = c::B150;
+
+/// `B200`
+pub const B200: Speed = c::B200;
+
+/// `B300`
+pub const B300: Speed = c::B300;
+
+/// `B600`
+pub const B600: Speed = c::B600;
+
+/// `B1200`
+pub const B1200: Speed = c::B1200;
+
+/// `B1800`
+pub const B1800: Speed = c::B1800;
+
+/// `B2400`
+pub const B2400: Speed = c::B2400;
+
+/// `B4800`
+pub const B4800: Speed = c::B4800;
+
+/// `B9600`
+pub const B9600: Speed = c::B9600;
+
+/// `B19200`
+pub const B19200: Speed = c::B19200;
+
+/// `B38400`
+pub const B38400: Speed = c::B38400;
+
+/// `B57600`
+pub const B57600: Speed = c::B57600;
+
+/// `B115200`
+pub const B115200: Speed = c::B115200;
+
+/// `B230400`
+pub const B230400: Speed = c::B230400;
+
+/// `B460800`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "openbsd")))]
+pub const B460800: Speed = c::B460800;
+
+/// `B500000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B500000: Speed = c::B500000;
+
+/// `B576000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B576000: Speed = c::B576000;
+
+/// `B921600`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "openbsd")))]
+pub const B921600: Speed = c::B921600;
+
+/// `B1000000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B1000000: Speed = c::B1000000;
+
+/// `B1152000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B1152000: Speed = c::B1152000;
+
+/// `B1500000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B1500000: Speed = c::B1500000;
+
+/// `B2000000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B2000000: Speed = c::B2000000;
+
+/// `B2500000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B2500000: Speed = c::B2500000;
+
+/// `B3000000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B3000000: Speed = c::B3000000;
+
+/// `B3500000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B3500000: Speed = c::B3500000;
+
+/// `B4000000`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub const B4000000: Speed = c::B4000000;
+
+/// `CSIZE`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const CSIZE: c::c_uint = c::CSIZE;
+
+/// `CS5`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const CS5: c::c_uint = c::CS5;
+
+/// `CS6`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const CS6: c::c_uint = c::CS6;
+
+/// `CS7`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const CS7: c::c_uint = c::CS7;
+
+/// `CS8`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const CS8: c::c_uint = c::CS8;
+
+/// `CSTOPB`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const CSTOPB: c::c_uint = c::CSTOPB;
+
+/// `CREAD`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const CREAD: c::c_uint = c::CREAD;
+
+/// `PARENB`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const PARENB: c::c_uint = c::PARENB;
+
+/// `PARODD`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const PARODD: c::c_uint = c::PARODD;
+
+/// `HUPCL`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const HUPCL: c::c_uint = c::HUPCL;
+
+/// `CLOCAL`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const CLOCAL: c::c_uint = c::CLOCAL;
+
+/// `ISIG`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ISIG: c::c_uint = c::ISIG;
+
+/// `ICANON`—A flag for the `c_lflag` field of [`Termios`] indicating
+/// canonical mode.
+pub const ICANON: Tcflag = c::ICANON;
+
+/// `ECHO`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ECHO: c::c_uint = c::ECHO;
+
+/// `ECHOE`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ECHOE: c::c_uint = c::ECHOE;
+
+/// `ECHOK`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ECHOK: c::c_uint = c::ECHOK;
+
+/// `ECHONL`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const ECHONL: c::c_uint = c::ECHONL;
+
+/// `NOFLSH`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const NOFLSH: c::c_uint = c::NOFLSH;
+
+/// `TOSTOP`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const TOSTOP: c::c_uint = c::TOSTOP;
+
+/// `IEXTEN`
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub const IEXTEN: c::c_uint = c::IEXTEN;
+
+/// `EXTA`
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub const EXTA: c::c_uint = c::EXTA;
+
+/// `EXTB`
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub const EXTB: c::c_uint = c::EXTB;
+
+/// `CBAUD`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const CBAUD: c::c_uint = c::CBAUD;
+
+/// `CBAUDEX`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const CBAUDEX: c::c_uint = c::CBAUDEX;
+
+/// `CIBAUD`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_arch = "powerpc",
+ target_arch = "powerpc64",
+)))]
+pub const CIBAUD: c::tcflag_t = c::CIBAUD;
+
+/// `CIBAUD`
+// TODO: Upstream this.
+#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
+pub const CIBAUD: c::tcflag_t = 0o77600000;
+
+/// `CMSPAR`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const CMSPAR: c::c_uint = c::CMSPAR;
+
+/// `CRTSCTS`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const CRTSCTS: c::c_uint = c::CRTSCTS;
+
+/// `XCASE`
+#[cfg(any(target_arch = "s390x", target_os = "haiku"))]
+pub const XCASE: c::c_uint = c::XCASE;
+
+/// `ECHOCTL`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const ECHOCTL: c::c_uint = c::ECHOCTL;
+
+/// `ECHOPRT`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const ECHOPRT: c::c_uint = c::ECHOPRT;
+
+/// `ECHOKE`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const ECHOKE: c::c_uint = c::ECHOKE;
+
+/// `FLUSHO`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const FLUSHO: c::c_uint = c::FLUSHO;
+
+/// `PENDIN`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const PENDIN: c::c_uint = c::PENDIN;
+
+/// `EXTPROC`
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub const EXTPROC: c::c_uint = c::EXTPROC;
+
+/// `XTABS`
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub const XTABS: c::c_uint = c::XTABS;
diff --git a/vendor/rustix/src/imp/libc/thread/mod.rs b/vendor/rustix/src/imp/libc/thread/mod.rs
new file mode 100644
index 000000000..40e0d1135
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/thread/mod.rs
@@ -0,0 +1,2 @@
+#[cfg(not(windows))]
+pub(crate) mod syscalls;
diff --git a/vendor/rustix/src/imp/libc/thread/syscalls.rs b/vendor/rustix/src/imp/libc/thread/syscalls.rs
new file mode 100644
index 000000000..c885372dc
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/thread/syscalls.rs
@@ -0,0 +1,282 @@
+//! libc syscalls supporting `rustix::thread`.
+
+use super::super::c;
+use super::super::conv::ret;
+use super::super::time::types::LibcTimespec;
+use crate::io;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::process::{Pid, RawNonZeroPid};
+#[cfg(not(target_os = "redox"))]
+use crate::thread::{NanosleepRelativeResult, Timespec};
+use core::mem::MaybeUninit;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "emscripten",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+use {crate::thread::ClockId, core::ptr::null_mut};
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+weak!(fn __clock_nanosleep_time64(c::clockid_t, c::c_int, *const LibcTimespec, *mut LibcTimespec) -> c::c_int);
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+weak!(fn __nanosleep64(*const LibcTimespec, *mut LibcTimespec) -> c::c_int);
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[inline]
+pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
+ let mut remain = MaybeUninit::<LibcTimespec>::uninit();
+ let flags = 0;
+
+ // 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe by
+ // default.
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ unsafe {
+ if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
+ match libc_clock_nanosleep(
+ id as c::clockid_t,
+ flags,
+ &request.clone().into(),
+ remain.as_mut_ptr(),
+ ) {
+ 0 => NanosleepRelativeResult::Ok,
+ err if err == io::Errno::INTR.0 => {
+ NanosleepRelativeResult::Interrupted(remain.assume_init().into())
+ }
+ err => NanosleepRelativeResult::Err(io::Errno(err)),
+ }
+ } else {
+ clock_nanosleep_relative_old(id, request)
+ }
+ }
+
+ // Main version: libc is y2038 safe and has `clock_nanosleep`.
+ #[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )))]
+ unsafe {
+ match c::clock_nanosleep(id as c::clockid_t, flags, request, remain.as_mut_ptr()) {
+ 0 => NanosleepRelativeResult::Ok,
+ err if err == io::Errno::INTR.0 => {
+ NanosleepRelativeResult::Interrupted(remain.assume_init())
+ }
+ err => NanosleepRelativeResult::Err(io::Errno(err)),
+ }
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+unsafe fn clock_nanosleep_relative_old(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
+ use core::convert::TryInto;
+ let tv_sec = match request.tv_sec.try_into() {
+ Ok(tv_sec) => tv_sec,
+ Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW),
+ };
+ let tv_nsec = match request.tv_nsec.try_into() {
+ Ok(tv_nsec) => tv_nsec,
+ Err(_) => return NanosleepRelativeResult::Err(io::Errno::INVAL),
+ };
+ let old_request = c::timespec { tv_sec, tv_nsec };
+ let mut old_remain = MaybeUninit::<c::timespec>::uninit();
+ let flags = 0;
+
+ match c::clock_nanosleep(
+ id as c::clockid_t,
+ flags,
+ &old_request,
+ old_remain.as_mut_ptr(),
+ ) {
+ 0 => NanosleepRelativeResult::Ok,
+ err if err == io::Errno::INTR.0 => {
+ let old_remain = old_remain.assume_init();
+ let remain = Timespec {
+ tv_sec: old_remain.tv_sec.into(),
+ tv_nsec: old_remain.tv_nsec.into(),
+ };
+ NanosleepRelativeResult::Interrupted(remain)
+ }
+ err => NanosleepRelativeResult::Err(io::Errno(err)),
+ }
+}
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
+ target_os = "emscripten",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[inline]
+pub(crate) fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::Result<()> {
+ let flags = c::TIMER_ABSTIME;
+
+ // 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe by
+ // default.
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ {
+ if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
+ match unsafe {
+ libc_clock_nanosleep(
+ id as c::clockid_t,
+ flags,
+ &request.clone().into(),
+ null_mut(),
+ )
+ } {
+ 0 => Ok(()),
+ err => Err(io::Errno(err)),
+ }
+ } else {
+ clock_nanosleep_absolute_old(id, request)
+ }
+ }
+
+ // Main version: libc is y2038 safe and has `clock_nanosleep`.
+ #[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )))]
+ match unsafe { c::clock_nanosleep(id as c::clockid_t, flags, request, null_mut()) } {
+ 0 => Ok(()),
+ err => Err(io::Errno(err)),
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+fn clock_nanosleep_absolute_old(id: ClockId, request: &Timespec) -> io::Result<()> {
+ use core::convert::TryInto;
+
+ let flags = c::TIMER_ABSTIME;
+
+ let old_request = c::timespec {
+ tv_sec: request.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: request.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
+ };
+ match unsafe { c::clock_nanosleep(id as c::clockid_t, flags, &old_request, null_mut()) } {
+ 0 => Ok(()),
+ err => Err(io::Errno(err)),
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+#[inline]
+pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult {
+ let mut remain = MaybeUninit::<LibcTimespec>::uninit();
+
+ // 32-bit gnu version: libc has `nanosleep` but it is not y2038 safe by
+ // default.
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ unsafe {
+ if let Some(libc_nanosleep) = __nanosleep64.get() {
+ match ret(libc_nanosleep(&request.clone().into(), remain.as_mut_ptr())) {
+ Ok(()) => NanosleepRelativeResult::Ok,
+ Err(io::Errno::INTR) => {
+ NanosleepRelativeResult::Interrupted(remain.assume_init().into())
+ }
+ Err(err) => NanosleepRelativeResult::Err(err),
+ }
+ } else {
+ nanosleep_old(request)
+ }
+ }
+
+ // Main version: libc is y2038 safe and has `nanosleep`.
+ #[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )))]
+ unsafe {
+ match ret(c::nanosleep(request, remain.as_mut_ptr())) {
+ Ok(()) => NanosleepRelativeResult::Ok,
+ Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(remain.assume_init()),
+ Err(err) => NanosleepRelativeResult::Err(err),
+ }
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+unsafe fn nanosleep_old(request: &Timespec) -> NanosleepRelativeResult {
+ use core::convert::TryInto;
+ let tv_sec = match request.tv_sec.try_into() {
+ Ok(tv_sec) => tv_sec,
+ Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW),
+ };
+ let tv_nsec = match request.tv_nsec.try_into() {
+ Ok(tv_nsec) => tv_nsec,
+ Err(_) => return NanosleepRelativeResult::Err(io::Errno::INVAL),
+ };
+ let old_request = c::timespec { tv_sec, tv_nsec };
+ let mut old_remain = MaybeUninit::<c::timespec>::uninit();
+
+ match ret(c::nanosleep(&old_request, old_remain.as_mut_ptr())) {
+ Ok(()) => NanosleepRelativeResult::Ok,
+ Err(io::Errno::INTR) => {
+ let old_remain = old_remain.assume_init();
+ let remain = Timespec {
+ tv_sec: old_remain.tv_sec.into(),
+ tv_nsec: old_remain.tv_nsec.into(),
+ };
+ NanosleepRelativeResult::Interrupted(remain)
+ }
+ Err(err) => NanosleepRelativeResult::Err(err),
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[must_use]
+pub(crate) fn gettid() -> Pid {
+ // `gettid` wasn't supported in glibc until 2.30, and musl until 1.2.2,
+ // so use `syscall`.
+ // <https://sourceware.org/bugzilla/show_bug.cgi?id=6399#c62>
+ weak_or_syscall! {
+ fn gettid() via SYS_gettid -> c::pid_t
+ }
+
+ unsafe {
+ let tid = gettid();
+ debug_assert_ne!(tid, 0);
+ Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(tid))
+ }
+}
diff --git a/vendor/rustix/src/imp/libc/time/mod.rs b/vendor/rustix/src/imp/libc/time/mod.rs
new file mode 100644
index 000000000..bff7fd564
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/time/mod.rs
@@ -0,0 +1,3 @@
+#[cfg(not(windows))]
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/libc/time/syscalls.rs b/vendor/rustix/src/imp/libc/time/syscalls.rs
new file mode 100644
index 000000000..2bbaf8ff1
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/time/syscalls.rs
@@ -0,0 +1,414 @@
+//! libc syscalls supporting `rustix::time`.
+
+use super::super::c;
+use super::super::conv::ret;
+#[cfg(feature = "time")]
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+use super::super::time::types::LibcItimerspec;
+use super::super::time::types::LibcTimespec;
+use super::types::Timespec;
+#[cfg(not(target_os = "wasi"))]
+use super::types::{ClockId, DynamicClockId};
+use crate::io;
+use core::mem::MaybeUninit;
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(feature = "time")]
+use {
+ super::super::conv::{borrowed_fd, ret_owned_fd},
+ crate::fd::BorrowedFd,
+ crate::io::OwnedFd,
+ crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags},
+};
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+weak!(fn __clock_gettime64(c::clockid_t, *mut LibcTimespec) -> c::c_int);
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+weak!(fn __clock_getres64(c::clockid_t, *mut LibcTimespec) -> c::c_int);
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[cfg(feature = "time")]
+weak!(fn __timerfd_gettime64(c::c_int, *mut LibcItimerspec) -> c::c_int);
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[cfg(feature = "time")]
+weak!(fn __timerfd_settime64(c::c_int, c::c_int, *const LibcItimerspec, *mut LibcItimerspec) -> c::c_int);
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[inline]
+#[must_use]
+pub(crate) fn clock_getres(id: ClockId) -> Timespec {
+ let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
+
+ // 32-bit gnu version: libc has `clock_getres` but it is not y2038 safe by
+ // default.
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ unsafe {
+ if let Some(libc_clock_getres) = __clock_getres64.get() {
+ ret(libc_clock_getres(id as c::clockid_t, timespec.as_mut_ptr())).unwrap();
+ timespec.assume_init().into()
+ } else {
+ clock_getres_old(id)
+ }
+ }
+
+ // Main version: libc is y2038 safe and has `clock_getres`.
+ #[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )))]
+ unsafe {
+ let _ = c::clock_getres(id as c::clockid_t, timespec.as_mut_ptr());
+ timespec.assume_init()
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[must_use]
+unsafe fn clock_getres_old(id: ClockId) -> Timespec {
+ let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
+ ret(c::clock_getres(
+ id as c::clockid_t,
+ old_timespec.as_mut_ptr(),
+ ))
+ .unwrap();
+ let old_timespec = old_timespec.assume_init();
+ Timespec {
+ tv_sec: old_timespec.tv_sec.into(),
+ tv_nsec: old_timespec.tv_nsec.into(),
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[must_use]
+pub(crate) fn clock_gettime(id: ClockId) -> Timespec {
+ let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
+
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ unsafe {
+ if let Some(libc_clock_gettime) = __clock_gettime64.get() {
+ ret(libc_clock_gettime(
+ id as c::clockid_t,
+ timespec.as_mut_ptr(),
+ ))
+ .unwrap();
+ timespec.assume_init().into()
+ } else {
+ clock_gettime_old(id)
+ }
+ }
+
+ // Use `unwrap()` here because `clock_getres` can fail if the clock itself
+ // overflows a number of seconds, but if that happens, the monotonic clocks
+ // can't maintain their invariants, or the realtime clocks aren't properly
+ // configured.
+ #[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )))]
+ unsafe {
+ ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr())).unwrap();
+ timespec.assume_init()
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[must_use]
+unsafe fn clock_gettime_old(id: ClockId) -> Timespec {
+ let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
+ ret(c::clock_gettime(
+ id as c::clockid_t,
+ old_timespec.as_mut_ptr(),
+ ))
+ .unwrap();
+ let old_timespec = old_timespec.assume_init();
+ Timespec {
+ tv_sec: old_timespec.tv_sec.into(),
+ tv_nsec: old_timespec.tv_nsec.into(),
+ }
+}
+
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub(crate) fn clock_gettime_dynamic(id: DynamicClockId<'_>) -> io::Result<Timespec> {
+ let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
+ unsafe {
+ let id: c::clockid_t = match id {
+ DynamicClockId::Known(id) => id as c::clockid_t,
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ DynamicClockId::Dynamic(fd) => {
+ use crate::fd::AsRawFd;
+ const CLOCKFD: i32 = 3;
+ (!fd.as_raw_fd() << 3) | CLOCKFD
+ }
+
+ #[cfg(not(any(target_os = "android", target_os = "linux")))]
+ DynamicClockId::Dynamic(_fd) => {
+ // Dynamic clocks are not supported on this platform.
+ return Err(io::Errno::INVAL);
+ }
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ DynamicClockId::RealtimeAlarm => c::CLOCK_REALTIME_ALARM,
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ DynamicClockId::Tai => c::CLOCK_TAI,
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ DynamicClockId::Boottime => c::CLOCK_BOOTTIME,
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ DynamicClockId::BoottimeAlarm => c::CLOCK_BOOTTIME_ALARM,
+ };
+
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ {
+ if let Some(libc_clock_gettime) = __clock_gettime64.get() {
+ ret(libc_clock_gettime(
+ id as c::clockid_t,
+ timespec.as_mut_ptr(),
+ ))?;
+
+ Ok(timespec.assume_init().into())
+ } else {
+ clock_gettime_dynamic_old(id)
+ }
+ }
+
+ #[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )))]
+ {
+ ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr()))?;
+
+ Ok(timespec.assume_init())
+ }
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[inline]
+unsafe fn clock_gettime_dynamic_old(id: c::clockid_t) -> io::Result<Timespec> {
+ let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
+
+ ret(c::clock_gettime(
+ id as c::clockid_t,
+ old_timespec.as_mut_ptr(),
+ ))?;
+
+ let old_timespec = old_timespec.assume_init();
+ Ok(Timespec {
+ tv_sec: old_timespec.tv_sec.into(),
+ tv_nsec: old_timespec.tv_nsec.into(),
+ })
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(feature = "time")]
+pub(crate) fn timerfd_create(id: TimerfdClockId, flags: TimerfdFlags) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(c::timerfd_create(id as c::clockid_t, flags.bits())) }
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(feature = "time")]
+pub(crate) fn timerfd_settime(
+ fd: BorrowedFd<'_>,
+ flags: TimerfdTimerFlags,
+ new_value: &Itimerspec,
+) -> io::Result<Itimerspec> {
+ let mut result = MaybeUninit::<LibcItimerspec>::uninit();
+
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ unsafe {
+ if let Some(libc_timerfd_settime) = __timerfd_settime64.get() {
+ ret(libc_timerfd_settime(
+ borrowed_fd(fd),
+ flags.bits(),
+ &new_value.clone().into(),
+ result.as_mut_ptr(),
+ ))
+ .map(|()| result.assume_init().into())
+ } else {
+ timerfd_settime_old(fd, flags, new_value)
+ }
+ }
+
+ #[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )))]
+ unsafe {
+ ret(c::timerfd_settime(
+ borrowed_fd(fd),
+ flags.bits(),
+ new_value,
+ result.as_mut_ptr(),
+ ))
+ .map(|()| result.assume_init())
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[cfg(feature = "time")]
+unsafe fn timerfd_settime_old(
+ fd: BorrowedFd<'_>,
+ flags: TimerfdTimerFlags,
+ new_value: &Itimerspec,
+) -> io::Result<Itimerspec> {
+ use core::convert::TryInto;
+
+ let mut old_result = MaybeUninit::<c::itimerspec>::uninit();
+
+ // Convert `new_value` to the old `itimerspec` format.
+ let old_new_value = c::itimerspec {
+ it_interval: c::timespec {
+ tv_sec: new_value
+ .it_interval
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: new_value
+ .it_interval
+ .tv_nsec
+ .try_into()
+ .map_err(|_| io::Errno::INVAL)?,
+ },
+ it_value: c::timespec {
+ tv_sec: new_value
+ .it_value
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: new_value
+ .it_value
+ .tv_nsec
+ .try_into()
+ .map_err(|_| io::Errno::INVAL)?,
+ },
+ };
+
+ ret(c::timerfd_settime(
+ borrowed_fd(fd),
+ flags.bits(),
+ &old_new_value,
+ old_result.as_mut_ptr(),
+ ))?;
+
+ let old_result = old_result.assume_init();
+ Ok(Itimerspec {
+ it_interval: Timespec {
+ tv_sec: old_result
+ .it_interval
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: old_result.it_interval.tv_nsec as _,
+ },
+ it_value: Timespec {
+ tv_sec: old_result
+ .it_interval
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: old_result.it_interval.tv_nsec as _,
+ },
+ })
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(feature = "time")]
+pub(crate) fn timerfd_gettime(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
+ let mut result = MaybeUninit::<LibcItimerspec>::uninit();
+
+ #[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ ))]
+ unsafe {
+ if let Some(libc_timerfd_gettime) = __timerfd_gettime64.get() {
+ ret(libc_timerfd_gettime(borrowed_fd(fd), result.as_mut_ptr()))
+ .map(|()| result.assume_init().into())
+ } else {
+ timerfd_gettime_old(fd)
+ }
+ }
+
+ #[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+ )))]
+ unsafe {
+ ret(c::timerfd_gettime(borrowed_fd(fd), result.as_mut_ptr())).map(|()| result.assume_init())
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[cfg(feature = "time")]
+unsafe fn timerfd_gettime_old(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
+ use core::convert::TryInto;
+
+ let mut old_result = MaybeUninit::<c::itimerspec>::uninit();
+
+ ret(c::timerfd_gettime(borrowed_fd(fd), old_result.as_mut_ptr()))?;
+
+ let old_result = old_result.assume_init();
+ Ok(Itimerspec {
+ it_interval: Timespec {
+ tv_sec: old_result
+ .it_interval
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: old_result.it_interval.tv_nsec as _,
+ },
+ it_value: Timespec {
+ tv_sec: old_result
+ .it_interval
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: old_result.it_interval.tv_nsec as _,
+ },
+ })
+}
diff --git a/vendor/rustix/src/imp/libc/time/types.rs b/vendor/rustix/src/imp/libc/time/types.rs
new file mode 100644
index 000000000..4aa2b22e5
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/time/types.rs
@@ -0,0 +1,362 @@
+use super::super::c;
+#[cfg(not(target_os = "wasi"))]
+use crate::fd::BorrowedFd;
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+use bitflags::bitflags;
+
+/// `struct timespec`
+#[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+)))]
+pub type Timespec = c::timespec;
+
+/// `struct timespec`
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[derive(Debug, Clone)]
+#[repr(C)]
+pub struct Timespec {
+ /// Seconds.
+ pub tv_sec: Secs,
+
+ /// Nanoseconds. Must be less than 1_000_000_000.
+ pub tv_nsec: Nsecs,
+}
+
+/// A type for the `tv_sec` field of [`Timespec`].
+#[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+)))]
+#[allow(deprecated)]
+pub type Secs = c::time_t;
+
+/// A type for the `tv_sec` field of [`Timespec`].
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+pub type Secs = i64;
+
+/// A type for the `tv_nsec` field of [`Timespec`].
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+pub type Nsecs = i64;
+
+/// A type for the `tv_nsec` field of [`Timespec`].
+#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+pub type Nsecs = c::c_long;
+
+/// On most platforms, `LibcTimespec` is just `Timespec`.
+#[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+)))]
+pub(crate) type LibcTimespec = Timespec;
+
+/// On 32-bit glibc platforms, `timespec` has anonymous padding fields, which
+/// Rust doesn't support yet (see `unnamed_fields`), so we define our own
+/// struct with explicit padding, with bidirectional `From` impls.
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub(crate) struct LibcTimespec {
+ pub(crate) tv_sec: Secs,
+
+ #[cfg(target_endian = "big")]
+ padding: core::mem::MaybeUninit<u32>,
+
+ pub(crate) tv_nsec: Nsecs,
+
+ #[cfg(target_endian = "little")]
+ padding: core::mem::MaybeUninit<u32>,
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+impl From<LibcTimespec> for Timespec {
+ #[inline]
+ fn from(t: LibcTimespec) -> Self {
+ Self {
+ tv_sec: t.tv_sec,
+ tv_nsec: t.tv_nsec,
+ }
+ }
+}
+
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+impl From<Timespec> for LibcTimespec {
+ #[inline]
+ fn from(t: Timespec) -> Self {
+ Self {
+ tv_sec: t.tv_sec,
+ tv_nsec: t.tv_nsec,
+ padding: core::mem::MaybeUninit::uninit(),
+ }
+ }
+}
+
+/// `CLOCK_*` constants for use with [`clock_gettime`].
+///
+/// These constants are always supported at runtime so `clock_gettime` never
+/// has to fail with `INVAL` due to an unsupported clock. See
+/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not
+/// all of them are always supported.
+///
+/// [`clock_gettime`]: crate::time::clock_gettime
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[cfg_attr(not(target_os = "dragonfly"), repr(i32))]
+#[cfg_attr(target_os = "dragonfly", repr(u64))]
+#[non_exhaustive]
+pub enum ClockId {
+ /// `CLOCK_REALTIME`
+ Realtime = c::CLOCK_REALTIME,
+
+ /// `CLOCK_MONOTONIC`
+ Monotonic = c::CLOCK_MONOTONIC,
+
+ /// `CLOCK_PROCESS_CPUTIME_ID`
+ #[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ ProcessCPUTime = c::CLOCK_PROCESS_CPUTIME_ID,
+
+ /// `CLOCK_THREAD_CPUTIME_ID`
+ #[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ ThreadCPUTime = c::CLOCK_THREAD_CPUTIME_ID,
+
+ /// `CLOCK_REALTIME_COARSE`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ RealtimeCoarse = c::CLOCK_REALTIME_COARSE,
+
+ /// `CLOCK_MONOTONIC_COARSE`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ MonotonicCoarse = c::CLOCK_MONOTONIC_COARSE,
+
+ /// `CLOCK_MONOTONIC_RAW`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ MonotonicRaw = c::CLOCK_MONOTONIC_RAW,
+}
+
+/// `CLOCK_*` constants for use with [`clock_gettime`].
+///
+/// These constants are always supported at runtime so `clock_gettime` never
+/// has to fail with `INVAL` due to an unsupported clock. See
+/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not
+/// all of them are always supported.
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum ClockId {
+ /// `CLOCK_REALTIME`
+ Realtime = c::CLOCK_REALTIME,
+
+ /// `CLOCK_MONOTONIC`
+ Monotonic = c::CLOCK_MONOTONIC,
+
+ /// `CLOCK_PROCESS_CPUTIME_ID`
+ ProcessCPUTime = c::CLOCK_PROCESS_CPUTIME_ID,
+
+ /// `CLOCK_THREAD_CPUTIME_ID`
+ ThreadCPUTime = c::CLOCK_THREAD_CPUTIME_ID,
+}
+
+/// `CLOCK_*` constants for use with [`clock_gettime_dynamic`].
+///
+/// These constants may be unsupported at runtime, depending on the OS version,
+/// and `clock_gettime_dynamic` may fail with `INVAL`. See [`ClockId`] for
+/// clocks which are always supported at runtime.
+///
+/// [`clock_gettime_dynamic`]: crate::time::clock_gettime_dynamic
+#[cfg(not(target_os = "wasi"))]
+#[derive(Debug, Copy, Clone)]
+#[non_exhaustive]
+pub enum DynamicClockId<'a> {
+ /// `ClockId` values that are always supported at runtime.
+ Known(ClockId),
+
+ /// Linux dynamic clocks.
+ Dynamic(BorrowedFd<'a>),
+
+ /// `CLOCK_REALTIME_ALARM`, available on Linux >= 3.0
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ RealtimeAlarm,
+
+ /// `CLOCK_TAI`, available on Linux >= 3.10
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ Tai,
+
+ /// `CLOCK_BOOTTIME`, available on Linux >= 2.6.39
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ Boottime,
+
+ /// `CLOCK_BOOTTIME_ALARM`, available on Linux >= 2.6.39
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ BoottimeAlarm,
+}
+
+/// `struct itimerspec`
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+)))]
+pub type Itimerspec = c::itimerspec;
+
+/// `struct itimerspec`
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct Itimerspec {
+ pub it_interval: Timespec,
+ pub it_value: Timespec,
+}
+
+/// On most platforms, `LibcItimerspec` is just `Itimerspec`.
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(not(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+)))]
+pub(crate) type LibcItimerspec = Itimerspec;
+
+/// On 32-bit glibc platforms, `LibcTimespec` differs from `Timespec`, so we
+/// define our own struct, with bidirectional `From` impls.
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub(crate) struct LibcItimerspec {
+ pub it_interval: LibcTimespec,
+ pub it_value: LibcTimespec,
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+impl From<LibcItimerspec> for Itimerspec {
+ #[inline]
+ fn from(t: LibcItimerspec) -> Self {
+ Self {
+ it_interval: t.it_interval.into(),
+ it_value: t.it_value.into(),
+ }
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(all(
+ any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
+ target_env = "gnu",
+))]
+impl From<Itimerspec> for LibcItimerspec {
+ #[inline]
+ fn from(t: Itimerspec) -> Self {
+ Self {
+ it_interval: t.it_interval.into(),
+ it_value: t.it_value.into(),
+ }
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+bitflags! {
+ /// `TFD_*` flags for use with [`timerfd_create`].
+ pub struct TimerfdFlags: c::c_int {
+ /// `TFD_NONBLOCK`
+ const NONBLOCK = c::TFD_NONBLOCK;
+
+ /// `TFD_CLOEXEC`
+ const CLOEXEC = c::TFD_CLOEXEC;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+bitflags! {
+ /// `TFD_TIMER_*` flags for use with [`timerfd_settime`].
+ pub struct TimerfdTimerFlags: c::c_int {
+ /// `TFD_TIMER_ABSTIME`
+ const ABSTIME = c::TFD_TIMER_ABSTIME;
+
+ /// `TFD_TIMER_CANCEL_ON_SET`
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ const CANCEL_ON_SET = 2; // TODO: upstream TFD_TIMER_CANCEL_ON_SET
+ }
+}
+
+/// `CLOCK_*` constants for use with [`timerfd_create`].
+///
+/// [`timerfd_create`]: crate::time::timerfd_create
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[repr(i32)]
+#[non_exhaustive]
+pub enum TimerfdClockId {
+ /// `CLOCK_REALTIME`—A clock that tells the "real" time.
+ ///
+ /// This is a clock that tells the amount of time elapsed since the
+ /// Unix epoch, 1970-01-01T00:00:00Z. The clock is externally settable, so
+ /// it is not monotonic. Successive reads may see decreasing times, so it
+ /// isn't reliable for measuring durations.
+ Realtime = c::CLOCK_REALTIME,
+
+ /// `CLOCK_MONOTONIC`—A clock that tells an abstract time.
+ ///
+ /// Unlike `Realtime`, this clock is not based on a fixed known epoch, so
+ /// individual times aren't meaningful. However, since it isn't settable,
+ /// it is reliable for measuring durations.
+ ///
+ /// This clock does not advance while the system is suspended; see
+ /// `Boottime` for a clock that does.
+ Monotonic = c::CLOCK_MONOTONIC,
+
+ /// `CLOCK_BOOTTIME`—Like `Monotonic`, but advances while suspended.
+ ///
+ /// This clock is similar to `Monotonic`, but does advance while the system
+ /// is suspended.
+ Boottime = c::CLOCK_BOOTTIME,
+
+ /// `CLOCK_REALTIME_ALARM`—Like `Realtime`, but wakes a suspended system.
+ ///
+ /// This clock is like `Realtime`, but can wake up a suspended system.
+ ///
+ /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
+ RealtimeAlarm = c::CLOCK_REALTIME_ALARM,
+
+ /// `CLOCK_BOOTTIME_ALARM`—Like `Boottime`, but wakes a suspended system.
+ ///
+ /// This clock is like `Boottime`, but can wake up a suspended system.
+ ///
+ /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
+ BoottimeAlarm = c::CLOCK_BOOTTIME_ALARM,
+}
diff --git a/vendor/rustix/src/imp/libc/weak.rs b/vendor/rustix/src/imp/libc/weak.rs
new file mode 100644
index 000000000..893403b1c
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/weak.rs
@@ -0,0 +1,226 @@
+// Implementation derived from `weak` in Rust's
+// library/std/src/sys/unix/weak.rs at revision
+// fd0cb0cdc21dd9c06025277d772108f8d42cb25f.
+
+//! Support for "weak linkage" to symbols on Unix
+//!
+//! Some I/O operations we do in libstd require newer versions of OSes but we
+//! need to maintain binary compatibility with older releases for now. In order
+//! to use the new functionality when available we use this module for
+//! detection.
+//!
+//! One option to use here is weak linkage, but that is unfortunately only
+//! really workable on Linux. Hence, use dlsym to get the symbol value at
+//! runtime. This is also done for compatibility with older versions of glibc,
+//! and to avoid creating dependencies on `GLIBC_PRIVATE` symbols. It assumes
+//! that we've been dynamically linked to the library the symbol comes from,
+//! but that is currently always the case for things like libpthread/libc.
+//!
+//! A long time ago this used weak linkage for the `__pthread_get_minstack`
+//! symbol, but that caused Debian to detect an unnecessarily strict versioned
+//! dependency on libc6 (#23628).
+
+// There are a variety of `#[cfg]`s controlling which targets are involved in
+// each instance of `weak!` and `syscall!`. Rather than trying to unify all of
+// that, we'll just allow that some unix targets don't use this module at all.
+#![allow(dead_code, unused_macros)]
+#![allow(clippy::doc_markdown)]
+
+use crate::ffi::CStr;
+use core::ffi::c_void;
+use core::ptr::null_mut;
+use core::sync::atomic::{self, AtomicPtr, Ordering};
+use core::{marker, mem};
+
+const NULL: *mut c_void = null_mut();
+const INVALID: *mut c_void = 1 as *mut c_void;
+
+macro_rules! weak {
+ ($vis:vis fn $name:ident($($t:ty),*) -> $ret:ty) => (
+ #[allow(non_upper_case_globals)]
+ $vis static $name: $crate::imp::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
+ $crate::imp::weak::Weak::new(concat!(stringify!($name), '\0'));
+ )
+}
+
+pub(crate) struct Weak<F> {
+ name: &'static str,
+ addr: AtomicPtr<c_void>,
+ _marker: marker::PhantomData<F>,
+}
+
+impl<F> Weak<F> {
+ pub(crate) const fn new(name: &'static str) -> Self {
+ Self {
+ name,
+ addr: AtomicPtr::new(INVALID),
+ _marker: marker::PhantomData,
+ }
+ }
+
+ pub(crate) fn get(&self) -> Option<F> {
+ assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+ unsafe {
+ // Relaxed is fine here because we fence before reading through the
+ // pointer (see the comment below).
+ match self.addr.load(Ordering::Relaxed) {
+ INVALID => self.initialize(),
+ NULL => None,
+ addr => {
+ let func = mem::transmute_copy::<*mut c_void, F>(&addr);
+ // The caller is presumably going to read through this value
+ // (by calling the function we've dlsymed). This means we'd
+ // need to have loaded it with at least C11's consume
+ // ordering in order to be guaranteed that the data we read
+ // from the pointer isn't from before the pointer was
+ // stored. Rust has no equivalent to memory_order_consume,
+ // so we use an acquire fence (sorry, ARM).
+ //
+ // Now, in practice this likely isn't needed even on CPUs
+ // where relaxed and consume mean different things. The
+ // symbols we're loading are probably present (or not) at
+ // init, and even if they aren't the runtime dynamic loader
+ // is extremely likely have sufficient barriers internally
+ // (possibly implicitly, for example the ones provided by
+ // invoking `mprotect`).
+ //
+ // That said, none of that's *guaranteed*, and so we fence.
+ atomic::fence(Ordering::Acquire);
+ Some(func)
+ }
+ }
+ }
+ }
+
+ // Cold because it should only happen during first-time initialization.
+ #[cold]
+ unsafe fn initialize(&self) -> Option<F> {
+ let val = fetch(self.name);
+ // This synchronizes with the acquire fence in `get`.
+ self.addr.store(val, Ordering::Release);
+
+ match val {
+ NULL => None,
+ addr => Some(mem::transmute_copy::<*mut c_void, F>(&addr)),
+ }
+ }
+}
+
+unsafe fn fetch(name: &str) -> *mut c_void {
+ let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
+ Ok(c_str) => c_str,
+ Err(..) => return null_mut(),
+ };
+ libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr().cast())
+}
+
+#[cfg(not(any(target_os = "android", target_os = "linux")))]
+macro_rules! syscall {
+ (fn $name:ident($($arg_name:ident: $t:ty),*) via $_sys_name:ident -> $ret:ty) => (
+ unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ libc_errno::set_errno(libc_errno::Errno(libc::ENOSYS));
+ -1
+ }
+ }
+ )
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+macro_rules! syscall {
+ (fn $name:ident($($arg_name:ident: $t:ty),*) via $sys_name:ident -> $ret:ty) => (
+ unsafe fn $name($($arg_name:$t),*) -> $ret {
+ // This looks like a hack, but concat_idents only accepts idents
+ // (not paths).
+ use libc::*;
+
+ trait AsSyscallArg {
+ type SyscallArgType;
+ fn into_syscall_arg(self) -> Self::SyscallArgType;
+ }
+
+ // Pass pointer types as pointers, to preserve provenance.
+ impl<T> AsSyscallArg for *mut T {
+ type SyscallArgType = *mut T;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self }
+ }
+ impl<T> AsSyscallArg for *const T {
+ type SyscallArgType = *const T;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self }
+ }
+
+ // Pass `BorrowedFd` values as the integer value.
+ impl AsSyscallArg for $crate::fd::BorrowedFd<'_> {
+ type SyscallArgType = c::c_long;
+ fn into_syscall_arg(self) -> Self::SyscallArgType {
+ $crate::fd::AsRawFd::as_raw_fd(&self) as _
+ }
+ }
+
+ // Coerce integer values into `c_long`.
+ impl AsSyscallArg for i32 {
+ type SyscallArgType = c::c_long;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+ impl AsSyscallArg for u32 {
+ type SyscallArgType = c::c_long;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+ impl AsSyscallArg for usize {
+ type SyscallArgType = c::c_long;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+
+ // `concat_idents is unstable, so we take an extra `sys_name`
+ // parameter and have our users do the concat for us for now.
+ /*
+ syscall(
+ concat_idents!(SYS_, $name),
+ $($arg_name.into_syscall_arg()),*
+ ) as $ret
+ */
+
+ syscall($sys_name, $($arg_name.into_syscall_arg()),*) as $ret
+ }
+ )
+}
+
+macro_rules! weakcall {
+ ($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ $vis unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
+ // interposition, but if it's not found just fail.
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ libc_errno::set_errno(libc_errno::Errno(libc::ENOSYS));
+ -1
+ }
+ }
+ )
+}
+
+/// A combination of `weakcall` and `syscall`. Use the libc function if it's
+/// available, and fall back to `libc::syscall` otherwise.
+macro_rules! weak_or_syscall {
+ ($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) via $sys_name:ident -> $ret:ty) => (
+ $vis unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
+ // interposition, but if it's not found just fail.
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ syscall! { fn $name($($arg_name: $t),*) via $sys_name -> $ret }
+ $name($($arg_name),*)
+ }
+ }
+ )
+}
diff --git a/vendor/rustix/src/imp/libc/winsock_c.rs b/vendor/rustix/src/imp/libc/winsock_c.rs
new file mode 100644
index 000000000..1fbce416f
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/winsock_c.rs
@@ -0,0 +1,82 @@
+//! Adapt the Winsock2 API to resemble a POSIX-style libc API.
+
+#![allow(unused_imports)]
+#![allow(non_camel_case_types)]
+
+use windows_sys::Win32::Networking::WinSock;
+
+pub(crate) use libc::{
+ c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong,
+ c_ushort, c_void, ssize_t,
+};
+pub(crate) type socklen_t = i32;
+
+// windows-sys declares these constants as unsigned. For better compatibility
+// with Unix-family APIs, redeclare them as signed. Filed upstream:
+// <https://github.com/microsoft/windows-rs/issues/1718>
+pub(crate) const AF_INET: i32 = WinSock::AF_INET as _;
+pub(crate) const AF_INET6: i32 = WinSock::AF_INET6 as _;
+pub(crate) const AF_UNSPEC: i32 = WinSock::AF_UNSPEC as _;
+pub(crate) const SO_TYPE: i32 = WinSock::SO_TYPE as _;
+pub(crate) const SO_REUSEADDR: i32 = WinSock::SO_REUSEADDR as _;
+pub(crate) const SO_BROADCAST: i32 = WinSock::SO_BROADCAST as _;
+pub(crate) const SO_LINGER: i32 = WinSock::SO_LINGER as _;
+pub(crate) const SOL_SOCKET: i32 = WinSock::SOL_SOCKET as _;
+pub(crate) const SO_RCVTIMEO: i32 = WinSock::SO_RCVTIMEO as _;
+pub(crate) const SO_SNDTIMEO: i32 = WinSock::SO_SNDTIMEO as _;
+pub(crate) const IP_TTL: i32 = WinSock::IP_TTL as _;
+pub(crate) const TCP_NODELAY: i32 = WinSock::TCP_NODELAY as _;
+pub(crate) const IP_ADD_MEMBERSHIP: i32 = WinSock::IP_ADD_MEMBERSHIP as _;
+pub(crate) const IP_DROP_MEMBERSHIP: i32 = WinSock::IP_DROP_MEMBERSHIP as _;
+pub(crate) const IP_MULTICAST_TTL: i32 = WinSock::IP_MULTICAST_TTL as _;
+pub(crate) const IP_MULTICAST_LOOP: i32 = WinSock::IP_MULTICAST_LOOP as _;
+pub(crate) const IPV6_ADD_MEMBERSHIP: i32 = WinSock::IPV6_ADD_MEMBERSHIP as _;
+pub(crate) const IPV6_DROP_MEMBERSHIP: i32 = WinSock::IPV6_DROP_MEMBERSHIP as _;
+pub(crate) const IPV6_MULTICAST_LOOP: i32 = WinSock::IPV6_MULTICAST_LOOP as _;
+pub(crate) const IPV6_V6ONLY: i32 = WinSock::IPV6_V6ONLY as _;
+pub(crate) const POLLERR: i16 = WinSock::POLLERR as _;
+pub(crate) const POLLIN: i16 = WinSock::POLLIN as _;
+pub(crate) const POLLNVAL: i16 = WinSock::POLLNVAL as _;
+pub(crate) const POLLHUP: i16 = WinSock::POLLHUP as _;
+pub(crate) const POLLPRI: i16 = WinSock::POLLPRI as _;
+pub(crate) const POLLOUT: i16 = WinSock::POLLOUT as _;
+pub(crate) const POLLRDNORM: i16 = WinSock::POLLRDNORM as _;
+pub(crate) const POLLWRNORM: i16 = WinSock::POLLWRNORM as _;
+pub(crate) const POLLRDBAND: i16 = WinSock::POLLRDBAND as _;
+pub(crate) const POLLWRBAND: i16 = WinSock::POLLWRBAND as _;
+
+// As above, cast the types for better compatibility, and also rename these to
+// their Unix names.
+pub(crate) const SHUT_RDWR: i32 = WinSock::SD_BOTH as _;
+pub(crate) const SHUT_RD: i32 = WinSock::SD_RECEIVE as _;
+pub(crate) const SHUT_WR: i32 = WinSock::SD_SEND as _;
+
+// Include the contents of `WinSock`, renaming as needed to match POSIX.
+//
+// Use `WSA_E_CANCELLED` for `ECANCELED` instead of `WSAECANCELLED`, because
+// `WSAECANCELLED` will be removed in the future.
+// <https://docs.microsoft.com/en-us/windows/win32/api/ws2spi/nc-ws2spi-lpnsplookupserviceend#remarks>
+pub(crate) use WinSock::{
+ closesocket as close, ioctlsocket as ioctl, WSAPoll as poll, ADDRESS_FAMILY as sa_family_t,
+ ADDRINFOA as addrinfo, IN6_ADDR as in6_addr, IN_ADDR as in_addr, IPV6_MREQ as ipv6_mreq,
+ IP_MREQ as ip_mreq, SOCKADDR as sockaddr, SOCKADDR_IN as sockaddr_in,
+ SOCKADDR_IN6 as sockaddr_in6, SOCKADDR_STORAGE as sockaddr_storage, WSAEACCES as EACCES,
+ WSAEADDRINUSE as EADDRINUSE, WSAEADDRNOTAVAIL as EADDRNOTAVAIL,
+ WSAEAFNOSUPPORT as EAFNOSUPPORT, WSAEALREADY as EALREADY, WSAEBADF as EBADF,
+ WSAECONNABORTED as ECONNABORTED, WSAECONNREFUSED as ECONNREFUSED, WSAECONNRESET as ECONNRESET,
+ WSAEDESTADDRREQ as EDESTADDRREQ, WSAEDISCON as EDISCON, WSAEDQUOT as EDQUOT,
+ WSAEFAULT as EFAULT, WSAEHOSTDOWN as EHOSTDOWN, WSAEHOSTUNREACH as EHOSTUNREACH,
+ WSAEINPROGRESS as EINPROGRESS, WSAEINTR as EINTR, WSAEINVAL as EINVAL,
+ WSAEINVALIDPROCTABLE as EINVALIDPROCTABLE, WSAEINVALIDPROVIDER as EINVALIDPROVIDER,
+ WSAEISCONN as EISCONN, WSAELOOP as ELOOP, WSAEMFILE as EMFILE, WSAEMSGSIZE as EMSGSIZE,
+ WSAENAMETOOLONG as ENAMETOOLONG, WSAENETDOWN as ENETDOWN, WSAENETRESET as ENETRESET,
+ WSAENETUNREACH as ENETUNREACH, WSAENOBUFS as ENOBUFS, WSAENOMORE as ENOMORE,
+ WSAENOPROTOOPT as ENOPROTOOPT, WSAENOTCONN as ENOTCONN, WSAENOTEMPTY as ENOTEMPTY,
+ WSAENOTSOCK as ENOTSOCK, WSAEOPNOTSUPP as EOPNOTSUPP, WSAEPFNOSUPPORT as EPFNOSUPPORT,
+ WSAEPROCLIM as EPROCLIM, WSAEPROTONOSUPPORT as EPROTONOSUPPORT, WSAEPROTOTYPE as EPROTOTYPE,
+ WSAEPROVIDERFAILEDINIT as EPROVIDERFAILEDINIT, WSAEREFUSED as EREFUSED, WSAEREMOTE as EREMOTE,
+ WSAESHUTDOWN as ESHUTDOWN, WSAESOCKTNOSUPPORT as ESOCKTNOSUPPORT, WSAESTALE as ESTALE,
+ WSAETIMEDOUT as ETIMEDOUT, WSAETOOMANYREFS as ETOOMANYREFS, WSAEUSERS as EUSERS,
+ WSAEWOULDBLOCK as EWOULDBLOCK, WSAEWOULDBLOCK as EAGAIN, WSAPOLLFD as pollfd,
+ WSA_E_CANCELLED as ECANCELED, *,
+};
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/aarch64.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/aarch64.rs
new file mode 100644
index 000000000..7d33a4a52
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/aarch64.rs
@@ -0,0 +1,266 @@
+//! aarch64 Linux system calls.
+
+use crate::imp::reg::{ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0};
+use core::arch::asm;
+
+#[cfg(target_pointer_width = "32")]
+compile_error!("arm64-ilp32 is not supported yet");
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ lateout("x0") r0,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ in("x0") a0.to_asm(),
+ options(noreturn)
+ )
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ in("x2") a2.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ in("x2") a2.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ in("x2") a2.to_asm(),
+ in("x3") a3.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ in("x2") a2.to_asm(),
+ in("x3") a3.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ in("x2") a2.to_asm(),
+ in("x3") a3.to_asm(),
+ in("x4") a4.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ in("x2") a2.to_asm(),
+ in("x3") a3.to_asm(),
+ in("x4") a4.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ in("x2") a2.to_asm(),
+ in("x3") a3.to_asm(),
+ in("x4") a4.to_asm(),
+ in("x5") a5.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("x8") nr.to_asm(),
+ inlateout("x0") a0.to_asm() => r0,
+ in("x1") a1.to_asm(),
+ in("x2") a2.to_asm(),
+ in("x3") a3.to_asm(),
+ in("x4") a4.to_asm(),
+ in("x5") a5.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/arm.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/arm.rs
new file mode 100644
index 000000000..9acccd6dc
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/arm.rs
@@ -0,0 +1,263 @@
+//! arm Linux system calls.
+
+use crate::imp::reg::{ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0};
+use core::arch::asm;
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ lateout("r0") r0,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ in("r0") a0.to_asm(),
+ options(noreturn)
+ )
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ in("r2") a2.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ in("r2") a2.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ in("r2") a2.to_asm(),
+ in("r3") a3.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ in("r2") a2.to_asm(),
+ in("r3") a3.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ in("r2") a2.to_asm(),
+ in("r3") a3.to_asm(),
+ in("r4") a4.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ in("r2") a2.to_asm(),
+ in("r3") a3.to_asm(),
+ in("r4") a4.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ in("r2") a2.to_asm(),
+ in("r3") a3.to_asm(),
+ in("r4") a4.to_asm(),
+ in("r5") a5.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "svc 0",
+ in("r7") nr.to_asm(),
+ inlateout("r0") a0.to_asm() => r0,
+ in("r1") a1.to_asm(),
+ in("r2") a2.to_asm(),
+ in("r3") a3.to_asm(),
+ in("r4") a4.to_asm(),
+ in("r5") a5.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/mips.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/mips.rs
new file mode 100644
index 000000000..0f2b9d9d2
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/mips.rs
@@ -0,0 +1,543 @@
+//! mipsel Linux system calls.
+//!
+//! On mipsel, Linux indicates success or failure using `$a3` rather
+//! than by returning a negative error code as most other architectures do.
+//!
+//! Mips-family platforms have a special calling convention for `__NR_pipe`,
+//! however we use `__NR_pipe2` instead to avoid having to implement it.
+
+use crate::imp::reg::{
+ ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, A6, R0,
+};
+use core::arch::asm;
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ asm!(
+ "syscall",
+ in("$2" /*$v0*/) nr.to_asm(),
+ in("$4" /*$a0*/) a0.to_asm(),
+ options(noreturn)
+ )
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ ".set noat",
+ "subu $sp, 32",
+ "sw {}, 16($sp)",
+ "syscall",
+ "addu $sp, 32",
+ ".set at",
+ in(reg) a4.to_asm(),
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ ".set noat",
+ "subu $sp, 32",
+ "sw {}, 16($sp)",
+ "syscall",
+ "addu $sp, 32",
+ ".set at",
+ in(reg) a4.to_asm(),
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ ".set noat",
+ "subu $sp, 32",
+ "sw {}, 16($sp)",
+ "sw {}, 20($sp)",
+ "syscall",
+ "addu $sp, 32",
+ ".set at",
+ in(reg) a4.to_asm(),
+ in(reg) a5.to_asm(),
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ ".set noat",
+ "subu $sp, 32",
+ "sw {}, 16($sp)",
+ "sw {}, 20($sp)",
+ "syscall",
+ "addu $sp, 32",
+ ".set at",
+ in(reg) a4.to_asm(),
+ in(reg) a5.to_asm(),
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall7_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ a6: ArgReg<'_, A6>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ ".set noat",
+ "subu $sp, 32",
+ "sw {}, 16($sp)",
+ "sw {}, 20($sp)",
+ "sw {}, 24($sp)",
+ "syscall",
+ "addu $sp, 32",
+ ".set at",
+ in(reg) a4.to_asm(),
+ in(reg) a5.to_asm(),
+ in(reg) a6.to_asm(),
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$t0*/) _,
+ lateout("$9" /*$t1*/) _,
+ lateout("$10" /*$t2*/) _,
+ lateout("$11" /*$t3*/) _,
+ lateout("$12" /*$t4*/) _,
+ lateout("$13" /*$t5*/) _,
+ lateout("$14" /*$t6*/) _,
+ lateout("$15" /*$t7*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/mips64.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/mips64.rs
new file mode 100644
index 000000000..36dd79316
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/mips64.rs
@@ -0,0 +1,464 @@
+//! mips64el Linux system calls.
+//!
+//! On mips64el, Linux indicates success or failure using `$a3` (`$7`) rather
+//! than by returning a negative error code as most other architectures do.
+//!
+//! Mips-family platforms have a special calling convention for `__NR_pipe`,
+//! however we use `__NR_pipe2` instead to avoid having to implement it.
+
+use crate::imp::reg::{ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0};
+use core::arch::asm;
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ asm!(
+ "syscall",
+ in("$2" /*$v0*/) nr.to_asm(),
+ in("$4" /*$a0*/) a0.to_asm(),
+ options(noreturn)
+ )
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ lateout("$7" /*$a3*/) err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ lateout("$8" /*$a4*/) _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ inlateout("$8" /*$a4*/) a4.to_asm() => _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ inlateout("$8" /*$a4*/) a4.to_asm() => _,
+ lateout("$9" /*$a5*/) _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ inlateout("$8" /*$a4*/) a4.to_asm() => _,
+ inlateout("$9" /*$a5*/) a5.to_asm() => _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let x0;
+ let err: usize;
+ asm!(
+ "syscall",
+ inlateout("$2" /*$v0*/) nr.to_asm() => x0,
+ in("$4" /*$a0*/) a0.to_asm(),
+ in("$5" /*$a1*/) a1.to_asm(),
+ in("$6" /*$a2*/) a2.to_asm(),
+ inlateout("$7" /*$a3*/) a3.to_asm() => err,
+ inlateout("$8" /*$a4*/) a4.to_asm() => _,
+ inlateout("$9" /*$a5*/) a5.to_asm() => _,
+ lateout("$10" /*$a6*/) _,
+ lateout("$11" /*$a7*/) _,
+ lateout("$12" /*$t0*/) _,
+ lateout("$13" /*$t1*/) _,
+ lateout("$14" /*$t2*/) _,
+ lateout("$15" /*$t3*/) _,
+ lateout("$24" /*$t8*/) _,
+ lateout("$25" /*$t9*/) _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(if err != 0 {
+ (x0 as usize).wrapping_neg() as *mut _
+ } else {
+ x0
+ })
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/mod.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/mod.rs
new file mode 100644
index 000000000..3e25e2149
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/mod.rs
@@ -0,0 +1,17 @@
+//! Inline asm for making system calls.
+//!
+//! Compilers should really have intrinsics for making system calls. They're
+//! much like regular calls, with custom calling conventions, and calling
+//! conventions are otherwise the compiler's job. But for now, use inline asm.
+
+#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
+#[cfg_attr(target_arch = "arm", path = "arm.rs")]
+#[cfg_attr(target_arch = "mips", path = "mips.rs")]
+#[cfg_attr(target_arch = "mips64", path = "mips64.rs")]
+#[cfg_attr(target_arch = "powerpc64", path = "powerpc64.rs")]
+#[cfg_attr(target_arch = "riscv64", path = "riscv64.rs")]
+#[cfg_attr(target_arch = "x86", path = "x86.rs")]
+#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
+mod target_arch;
+
+pub(in crate::imp) use self::target_arch::*;
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/powerpc64.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/powerpc64.rs
new file mode 100644
index 000000000..520bd4d79
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/powerpc64.rs
@@ -0,0 +1,411 @@
+//! powerpc64le Linux system calls.
+//!
+//! On powerpc64le, Linux indicates success or failure using `cr0.SO` rather
+//! than by returning a negative error code as most other architectures do. In
+//! theory we could immediately translate this into a `Result`, and it'd save a
+//! few branches. And in theory we could have specialized sequences for use
+//! with syscalls that are known to never fail. However, those would require
+//! more extensive changes in rustix's platform-independent code. For now, we
+//! check the flag and negate the error value to make PowerPC64 look like other
+//! architectures.
+
+use crate::imp::reg::{ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0};
+use core::arch::asm;
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ lateout("r3") r0,
+ lateout("r4") _,
+ lateout("r5") _,
+ lateout("r6") _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ lateout("r4") _,
+ lateout("r5") _,
+ lateout("r6") _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ lateout("r4") _,
+ lateout("r5") _,
+ lateout("r6") _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ asm!(
+ "sc",
+ in("r0") nr.to_asm(),
+ in("r3") a0.to_asm(),
+ options(noreturn)
+ )
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ lateout("r5") _,
+ lateout("r6") _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ lateout("r5") _,
+ lateout("r6") _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ inlateout("r5") a2.to_asm() => _,
+ lateout("r6") _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ inlateout("r5") a2.to_asm() => _,
+ lateout("r6") _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ inlateout("r5") a2.to_asm() => _,
+ inlateout("r6") a3.to_asm() => _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ inlateout("r5") a2.to_asm() => _,
+ inlateout("r6") a3.to_asm() => _,
+ lateout("r7") _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ inlateout("r5") a2.to_asm() => _,
+ inlateout("r6") a3.to_asm() => _,
+ inlateout("r7") a4.to_asm() => _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ inlateout("r5") a2.to_asm() => _,
+ inlateout("r6") a3.to_asm() => _,
+ inlateout("r7") a4.to_asm() => _,
+ lateout("r8") _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ inlateout("r5") a2.to_asm() => _,
+ inlateout("r6") a3.to_asm() => _,
+ inlateout("r7") a4.to_asm() => _,
+ inlateout("r8") a5.to_asm() => _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "sc",
+ "bns 0f",
+ "neg 3, 3",
+ "0:",
+ inlateout("r0") nr.to_asm() => _,
+ inlateout("r3") a0.to_asm() => r0,
+ inlateout("r4") a1.to_asm() => _,
+ inlateout("r5") a2.to_asm() => _,
+ inlateout("r6") a3.to_asm() => _,
+ inlateout("r7") a4.to_asm() => _,
+ inlateout("r8") a5.to_asm() => _,
+ lateout("r9") _,
+ lateout("r10") _,
+ lateout("r11") _,
+ lateout("r12") _,
+ lateout("cr0") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/riscv64.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/riscv64.rs
new file mode 100644
index 000000000..3ed36a16c
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/riscv64.rs
@@ -0,0 +1,263 @@
+//! riscv64 Linux system calls.
+
+use crate::imp::reg::{ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0};
+use core::arch::asm;
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ lateout("a0") r0,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ in("a0") a0.to_asm(),
+ options(noreturn)
+ );
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ in("a2") a2.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ in("a2") a2.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ in("a2") a2.to_asm(),
+ in("a3") a3.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ in("a2") a2.to_asm(),
+ in("a3") a3.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ in("a2") a2.to_asm(),
+ in("a3") a3.to_asm(),
+ in("a4") a4.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ in("a2") a2.to_asm(),
+ in("a3") a3.to_asm(),
+ in("a4") a4.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ in("a2") a2.to_asm(),
+ in("a3") a3.to_asm(),
+ in("a4") a4.to_asm(),
+ in("a5") a5.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "ecall",
+ in("a7") nr.to_asm(),
+ inlateout("a0") a0.to_asm() => r0,
+ in("a1") a1.to_asm(),
+ in("a2") a2.to_asm(),
+ in("a3") a3.to_asm(),
+ in("a4") a4.to_asm(),
+ in("a5") a5.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/x86.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/x86.rs
new file mode 100644
index 000000000..8d1b4ed0a
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/x86.rs
@@ -0,0 +1,492 @@
+//! 32-bit x86 Linux system calls.
+//!
+//! There are two forms; `indirect_*` which take a callee, which allow calling
+//! through the vDSO when possible, and plain forms, which use the `int 0x80`
+//! instruction.
+//!
+//! Most `rustix` syscalls use the vsyscall mechanism rather than going using
+//! `int 0x80` sequences.
+
+#![allow(dead_code)]
+
+use crate::imp::reg::{ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0};
+use crate::imp::vdso_wrappers::SyscallType;
+use core::arch::asm;
+
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall0(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "call {callee}",
+ callee = in(reg) callee,
+ inlateout("eax") nr.to_asm() => r0,
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall1(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "call {callee}",
+ callee = in(reg) callee,
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall1_noreturn(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> ! {
+ asm!(
+ "call {callee}",
+ callee = in(reg) callee,
+ in("eax") nr.to_asm(),
+ in("ebx") a0.to_asm(),
+ options(noreturn)
+ )
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall2(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "call {callee}",
+ callee = in(reg) callee,
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall3(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "call {callee}",
+ callee = in(reg) callee,
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall4(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ // a3 should go in esi, but `asm!` won't let us use it as an operand.
+ // temporarily swap it into place, and then swap it back afterward.
+ //
+ // We hard-code the callee operand to use edi instead of `in(reg)` because
+ // even though we can't name esi as an operand, the compiler can use esi to
+ // satisfy `in(reg)`.
+ asm!(
+ "xchg esi, {a3}",
+ "call edi",
+ "xchg esi, {a3}",
+ a3 = in(reg) a3.to_asm(),
+ in("edi") callee,
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall5(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ // Oof. a3 should go in esi, and `asm!` won't let us use that register as
+ // an operand. And we can't request stack slots. And there are no other
+ // registers free. Use eax as a temporary pointer to a slice, since it
+ // gets clobbered as the return value anyway.
+ asm!(
+ "push esi",
+ "push DWORD PTR [eax + 0]",
+ "mov esi, DWORD PTR [eax + 4]",
+ "mov eax, DWORD PTR [eax + 8]",
+ "call DWORD PTR [esp]",
+ "pop esi",
+ "pop esi",
+ inout("eax") &[callee as _, a3.to_asm(), nr.to_asm()] => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ in("edi") a4.to_asm(),
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[allow(clippy::too_many_arguments)]
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall6(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ // Oof again. a3 should go in esi, and a5 should go in ebp, and `asm!`
+ // won't let us use either of those registers as operands. And we can't
+ // request stack slots. And there are no other registers free. Use eax as a
+ // temporary pointer to a slice, since it gets clobbered as the return
+ // value anyway.
+ //
+ // This is another reason that syscalls should be compiler intrinsics
+ // rather than inline asm.
+ asm!(
+ "push ebp",
+ "push esi",
+ "push DWORD PTR [eax + 0]",
+ "mov esi, DWORD PTR [eax + 4]",
+ "mov ebp, DWORD PTR [eax + 8]",
+ "mov eax, DWORD PTR [eax + 12]",
+ "call DWORD PTR [esp]",
+ "pop esi",
+ "pop esi",
+ "pop ebp",
+ inout("eax") &[callee as _, a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ in("edi") a4.to_asm(),
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "int $$0x80",
+ inlateout("eax") nr.to_asm() => r0,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "int $$0x80",
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "int $$0x80",
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ asm!(
+ "int $$0x80",
+ in("eax") nr.to_asm(),
+ in("ebx") a0.to_asm(),
+ options(noreturn)
+ )
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "int $$0x80",
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "int $$0x80",
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "int $$0x80",
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "int $$0x80",
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ // a3 should go in esi, but `asm!` won't let us use it as an operand.
+ // Temporarily swap it into place, and then swap it back afterward.
+ asm!(
+ "xchg esi, {a3}",
+ "int $$0x80",
+ "xchg esi, {a3}",
+ a3 = in(reg) a3.to_asm(),
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "xchg esi, {a3}",
+ "int $$0x80",
+ "xchg esi, {a3}",
+ a3 = in(reg) a3.to_asm(),
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ // As in `syscall4`, use xchg to handle a3. a4 should go in edi, and we can
+ // use that register as an operand. Unlike in `indirect_syscall5`, we don't
+ // have a `callee` operand taking up a register, so we have enough
+ // registers and don't need to use a slice.
+ asm!(
+ "xchg esi, {a3}",
+ "int $$0x80",
+ "xchg esi, {a3}",
+ a3 = in(reg) a3.to_asm(),
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ in("edi") a4.to_asm(),
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ // See the comments in `syscall5`.
+ asm!(
+ "xchg esi, {a3}",
+ "int $$0x80",
+ "xchg esi, {a3}",
+ a3 = in(reg) a3.to_asm(),
+ inlateout("eax") nr.to_asm() => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ in("edi") a4.to_asm(),
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ // See the comments in `indirect_syscall6`.
+ asm!(
+ "push ebp",
+ "push esi",
+ "mov esi, DWORD PTR [eax + 0]",
+ "mov ebp, DWORD PTR [eax + 4]",
+ "mov eax, DWORD PTR [eax + 8]",
+ "int $$0x80",
+ "pop esi",
+ "pop ebp",
+ inout("eax") &[a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ in("edi") a4.to_asm(),
+ options(preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ // See the comments in `indirect_syscall6`.
+ asm!(
+ "push ebp",
+ "push esi",
+ "mov esi, DWORD PTR [eax + 0]",
+ "mov ebp, DWORD PTR [eax + 4]",
+ "mov eax, DWORD PTR [eax + 8]",
+ "int $$0x80",
+ "pop esi",
+ "pop ebp",
+ inout("eax") &[a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
+ in("ebx") a0.to_asm(),
+ in("ecx") a1.to_asm(),
+ in("edx") a2.to_asm(),
+ in("edi") a4.to_asm(),
+ options(preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/inline/x86_64.rs b/vendor/rustix/src/imp/linux_raw/arch/inline/x86_64.rs
new file mode 100644
index 000000000..75d6124f7
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/inline/x86_64.rs
@@ -0,0 +1,291 @@
+//! x86-64 Linux system calls.
+
+use crate::imp::reg::{ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0};
+use core::arch::asm;
+
+#[cfg(target_pointer_width = "32")]
+compile_error!("x32 is not yet supported");
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ asm!(
+ "syscall",
+ in("rax") nr.to_asm(),
+ in("rdi") a0.to_asm(),
+ options(noreturn)
+ )
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall2_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ in("rdx") a2.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall3_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ in("rdx") a2.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ in("rdx") a2.to_asm(),
+ in("r10") a3.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall4_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ in("rdx") a2.to_asm(),
+ in("r10") a3.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ in("rdx") a2.to_asm(),
+ in("r10") a3.to_asm(),
+ in("r8") a4.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall5_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ in("rdx") a2.to_asm(),
+ in("r10") a3.to_asm(),
+ in("r8") a4.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ in("rdx") a2.to_asm(),
+ in("r10") a3.to_asm(),
+ in("r8") a4.to_asm(),
+ in("r9") a5.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags)
+ );
+ FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall6_readonly(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ let r0;
+ asm!(
+ "syscall",
+ inlateout("rax") nr.to_asm() => r0,
+ in("rdi") a0.to_asm(),
+ in("rsi") a1.to_asm(),
+ in("rdx") a2.to_asm(),
+ in("r10") a3.to_asm(),
+ in("r8") a4.to_asm(),
+ in("r9") a5.to_asm(),
+ lateout("rcx") _,
+ lateout("r11") _,
+ options(nostack, preserves_flags, readonly)
+ );
+ FromAsm::from_asm(r0)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/mod.rs b/vendor/rustix/src/imp/linux_raw/arch/mod.rs
new file mode 100644
index 000000000..81f3a255e
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/mod.rs
@@ -0,0 +1,218 @@
+//! Architecture-specific syscall code.
+//!
+//! `rustix` has inline assembly sequences using `asm!`, but that requires
+//! nightly Rust, so it also has out-of-line ("outline") assembly sequences
+//! in .s files. And 32-bit x86 is special (see comments below).
+//!
+//! This module also has a `choose` submodule which chooses a scheme and is
+//! what most of the `rustix` syscalls use.
+//!
+//! # Safety
+//!
+//! This contains the inline `asm` statements performing the syscall
+//! instructions and FFI declarations declaring the out-of-line ("outline")
+//! syscall instructions.
+
+#![allow(unsafe_code)]
+#![cfg_attr(not(feature = "all-apis"), allow(unused_imports))]
+
+// When inline asm is available, use it. Otherwise, use out-of-line asm. These
+// functions always use the machine's syscall instruction, even when it isn't
+// the fastest option available.
+#[cfg_attr(asm, path = "inline/mod.rs")]
+#[cfg_attr(not(asm), path = "outline/mod.rs")]
+pub(in crate::imp) mod asm;
+
+// On most architectures, the architecture syscall instruction is fast, so use
+// it directly.
+#[cfg(any(
+ target_arch = "arm",
+ target_arch = "aarch64",
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ target_arch = "riscv64",
+ target_arch = "x86_64",
+))]
+pub(in crate::imp) use self::asm as choose;
+
+// On 32-bit x86, use vDSO wrappers for all syscalls. We could use the
+// architecture syscall instruction (`int 0x80`), but the vDSO kernel_vsyscall
+// mechanism is much faster.
+#[cfg(target_arch = "x86")]
+pub(in crate::imp) use super::vdso_wrappers::x86_via_vdso as choose;
+
+// This would be the code for always using `int 0x80` on 32-bit x86.
+//#[cfg(target_arch = "x86")]
+//pub(in crate::imp) use self::asm as choose;
+
+// Macros for invoking system calls.
+//
+// These factor out:
+// - Calling `nr` on the syscall number to convert it into `SyscallNumber`.
+// - Calling `.into()` on each of the arguments to convert them into `ArgReg`.
+// - Qualifying the `syscall*` and `__NR_*` identifiers.
+// - Counting the number of arguments.
+macro_rules! syscall {
+ ($nr:ident) => {
+ $crate::imp::arch::choose::syscall0($crate::imp::reg::nr(linux_raw_sys::general::$nr))
+ };
+
+ ($nr:ident, $a0:expr) => {
+ $crate::imp::arch::choose::syscall1(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr) => {
+ $crate::imp::arch::choose::syscall2(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
+ $crate::imp::arch::choose::syscall3(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
+ $crate::imp::arch::choose::syscall4(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
+ $crate::imp::arch::choose::syscall5(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
+ $crate::imp::arch::choose::syscall6(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
+ $crate::imp::arch::choose::syscall7(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ $a6.into(),
+ )
+ };
+}
+
+macro_rules! syscall_readonly {
+ ($nr:ident) => {
+ $crate::imp::arch::choose::syscall0_readonly($crate::imp::reg::nr(
+ linux_raw_sys::general::$nr,
+ ))
+ };
+
+ ($nr:ident, $a0:expr) => {
+ $crate::imp::arch::choose::syscall1_readonly(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr) => {
+ $crate::imp::arch::choose::syscall2_readonly(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
+ $crate::imp::arch::choose::syscall3_readonly(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
+ $crate::imp::arch::choose::syscall4_readonly(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
+ $crate::imp::arch::choose::syscall5_readonly(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
+ $crate::imp::arch::choose::syscall6_readonly(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
+ $crate::imp::arch::choose::syscall7_readonly(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ $a6.into(),
+ )
+ };
+}
+
+#[cfg(feature = "runtime")]
+macro_rules! syscall_noreturn {
+ ($nr:ident, $a0:expr) => {
+ $crate::imp::arch::choose::syscall1_noreturn(
+ $crate::imp::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ )
+ };
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/aarch64.s b/vendor/rustix/src/imp/linux_raw/arch/outline/aarch64.s
new file mode 100644
index 000000000..1fad2fa6d
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/aarch64.s
@@ -0,0 +1,119 @@
+// Assembly code for making aarch64 syscalls.
+//
+// aarch64 syscall argument register ordering is the same as the aarch64
+// userspace argument register ordering except that the syscall number
+// (nr) is passed in w8.
+//
+// outline.rs takes care of reordering the nr argument to the end for us,
+// so we only need to move nr into w8.
+//
+// arm64-ilp32 is not yet supported.
+
+ .file "aarch64.s"
+ .arch armv8-a
+
+ .section .text.rustix_syscall0_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall0_nr_last
+ .hidden rustix_syscall0_nr_last
+ .type rustix_syscall0_nr_last, @function
+rustix_syscall0_nr_last:
+ .cfi_startproc
+ mov w8, w0
+ svc #0
+ ret
+ .cfi_endproc
+ .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
+
+ .section .text.rustix_syscall1_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall1_nr_last
+ .hidden rustix_syscall1_nr_last
+ .type rustix_syscall1_nr_last, @function
+rustix_syscall1_nr_last:
+ .cfi_startproc
+ mov w8, w1
+ svc #0
+ ret
+ .cfi_endproc
+ .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
+
+ .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall1_noreturn_nr_last
+ .hidden rustix_syscall1_noreturn_nr_last
+ .type rustix_syscall1_noreturn_nr_last, @function
+rustix_syscall1_noreturn_nr_last:
+ .cfi_startproc
+ mov w8, w1
+ svc #0
+ brk #0x1
+ .cfi_endproc
+ .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
+
+ .section .text.rustix_syscall2_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall2_nr_last
+ .hidden rustix_syscall2_nr_last
+ .type rustix_syscall2_nr_last, @function
+rustix_syscall2_nr_last:
+ .cfi_startproc
+ mov w8, w2
+ svc #0
+ ret
+ .cfi_endproc
+ .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
+
+ .section .text.rustix_syscall3_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall3_nr_last
+ .hidden rustix_syscall3_nr_last
+ .type rustix_syscall3_nr_last, @function
+rustix_syscall3_nr_last:
+ .cfi_startproc
+ mov w8, w3
+ svc #0
+ ret
+ .cfi_endproc
+ .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
+
+ .section .text.rustix_syscall4_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall4_nr_last
+ .hidden rustix_syscall4_nr_last
+ .type rustix_syscall4_nr_last, @function
+rustix_syscall4_nr_last:
+ .cfi_startproc
+ mov w8, w4
+ svc #0
+ ret
+ .cfi_endproc
+ .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
+
+ .section .text.rustix_syscall5_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall5_nr_last
+ .hidden rustix_syscall5_nr_last
+ .type rustix_syscall5_nr_last, @function
+rustix_syscall5_nr_last:
+ .cfi_startproc
+ mov w8, w5
+ svc #0
+ ret
+ .cfi_endproc
+ .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
+
+ .section .text.rustix_syscall6_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall6_nr_last
+ .hidden rustix_syscall6_nr_last
+ .type rustix_syscall6_nr_last, @function
+rustix_syscall6_nr_last:
+ .cfi_startproc
+ mov w8, w6
+ svc #0
+ ret
+ .cfi_endproc
+ .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/arm.s b/vendor/rustix/src/imp/linux_raw/arch/outline/arm.s
new file mode 100644
index 000000000..7001686f1
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/arm.s
@@ -0,0 +1,135 @@
+// Assembly code for making arm syscalls.
+//
+// arm syscall argument register ordering is the similar to the arm
+// userspace argument register ordering except that the syscall number
+// (nr) is passed in r7.
+//
+// nr_last.rs takes care of reordering the nr argument to the end for us,
+// so we only need to move nr into r7 and take care of r4 and r5 if needed.
+
+ .file "arm.s"
+ .arch armv5t
+
+ .section .text.rustix_syscall0_nr_last,"ax",%progbits
+ .p2align 4
+ .weak rustix_syscall0_nr_last
+ .hidden rustix_syscall0_nr_last
+ .type rustix_syscall0_nr_last, %function
+rustix_syscall0_nr_last:
+ .fnstart
+ .cantunwind
+ push {r7, lr}
+ mov r7, r0
+ svc #0
+ pop {r7, pc}
+ .fnend
+ .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
+
+ .section .text.rustix_syscall1_nr_last,"ax",%progbits
+ .p2align 4
+ .weak rustix_syscall1_nr_last
+ .hidden rustix_syscall1_nr_last
+ .type rustix_syscall1_nr_last, %function
+rustix_syscall1_nr_last:
+ .fnstart
+ .cantunwind
+ push {r7, lr}
+ mov r7, r1
+ svc #0
+ pop {r7, pc}
+ .fnend
+ .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
+
+ .section .text.rustix_syscall1_noreturn_nr_last,"ax",%progbits
+ .p2align 4
+ .weak rustix_syscall1_noreturn_nr_last
+ .hidden rustix_syscall1_noreturn_nr_last
+ .type rustix_syscall1_noreturn_nr_last, %function
+rustix_syscall1_noreturn_nr_last:
+ .fnstart
+ .cantunwind
+ // Don't save r7 and lr; this is noreturn, so we'll never restore them.
+ mov r7, r1
+ svc #0
+ udf #16 // Trap instruction
+ .fnend
+ .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
+
+ .section .text.rustix_syscall2_nr_last,"ax",%progbits
+ .p2align 4
+ .weak rustix_syscall2_nr_last
+ .hidden rustix_syscall2_nr_last
+ .type rustix_syscall2_nr_last, %function
+rustix_syscall2_nr_last:
+ .fnstart
+ .cantunwind
+ push {r7, lr}
+ mov r7, r2
+ svc #0
+ pop {r7, pc}
+ .fnend
+ .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
+
+ .section .text.rustix_syscall3_nr_last,"ax",%progbits
+ .p2align 4
+ .weak rustix_syscall3_nr_last
+ .hidden rustix_syscall3_nr_last
+ .type rustix_syscall3_nr_last, %function
+rustix_syscall3_nr_last:
+ .fnstart
+ .cantunwind
+ push {r7, lr}
+ mov r7, r3
+ svc #0
+ pop {r7, pc}
+ .fnend
+ .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
+
+ .section .text.rustix_syscall4_nr_last,"ax",%progbits
+ .p2align 4
+ .weak rustix_syscall4_nr_last
+ .hidden rustix_syscall4_nr_last
+ .type rustix_syscall4_nr_last, %function
+rustix_syscall4_nr_last:
+ .fnstart
+ .cantunwind
+ push {r7, lr}
+ ldr r7, [sp, #8]
+ svc #0
+ pop {r7, pc}
+ .fnend
+ .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
+
+ .section .text.rustix_syscall5_nr_last,"ax",%progbits
+ .p2align 4
+ .weak rustix_syscall5_nr_last
+ .hidden rustix_syscall5_nr_last
+ .type rustix_syscall5_nr_last, %function
+rustix_syscall5_nr_last:
+ .fnstart
+ .cantunwind
+ push {r4, r7, r11, lr}
+ ldr r7, [sp, #20]
+ ldr r4, [sp, #16]
+ svc #0
+ pop {r4, r7, r11, pc}
+ .fnend
+ .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
+
+ .section .text.rustix_syscall6_nr_last,"ax",%progbits
+ .p2align 4
+ .weak rustix_syscall6_nr_last
+ .hidden rustix_syscall6_nr_last
+ .type rustix_syscall6_nr_last, %function
+rustix_syscall6_nr_last:
+ .fnstart
+ .cantunwind
+ push {r4, r5, r7, lr}
+ add r7, sp, #16
+ ldm r7, {r4, r5, r7}
+ svc #0
+ pop {r4, r5, r7, pc}
+ .fnend
+ .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/mips.s b/vendor/rustix/src/imp/linux_raw/arch/outline/mips.s
new file mode 100644
index 000000000..ab1bbfa2d
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/mips.s
@@ -0,0 +1,213 @@
+# Assembly code for making mips64 syscalls.
+#
+# mips64 syscall argument register ordering is the same as the mips64
+# userspace argument register ordering except that the syscall number
+# (nr) is passed in v0.
+#
+# outline.rs takes care of reordering the nr argument to the end for us,
+# so we only need to move nr into v0.
+
+ .file "mips.s"
+ .section .mdebug.abi32
+ .previous
+ .abicalls
+
+ .section .text.rustix_syscall0_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall0_nr_last
+ .hidden rustix_syscall0_nr_last
+ .type rustix_syscall0_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall0_nr_last
+rustix_syscall0_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $4
+ syscall
+ negu $8, $2
+ jr $31
+ movn $2, $8, $7
+ .end rustix_syscall0_nr_last
+ .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
+
+ .section .text.rustix_syscall1_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall1_nr_last
+ .hidden rustix_syscall1_nr_last
+ .type rustix_syscall1_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall1_nr_last
+rustix_syscall1_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $5
+ syscall
+ negu $8, $2
+ jr $31
+ movn $2, $8, $7
+ .end rustix_syscall1_nr_last
+ .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
+
+ .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall1_noreturn_nr_last
+ .hidden rustix_syscall1_noreturn_nr_last
+ .type rustix_syscall1_noreturn_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall1_noreturn_nr_last
+rustix_syscall1_noreturn_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $5
+ syscall
+ teq $zero, $zero
+ .end rustix_syscall1_noreturn_nr_last
+ .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
+
+ .section .text.rustix_syscall2_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall2_nr_last
+ .hidden rustix_syscall2_nr_last
+ .type rustix_syscall2_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall2_nr_last
+rustix_syscall2_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $6
+ syscall
+ negu $8, $2
+ jr $31
+ movn $2, $8, $7
+ .end rustix_syscall2_nr_last
+ .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
+
+ .section .text.rustix_syscall3_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall3_nr_last
+ .hidden rustix_syscall3_nr_last
+ .type rustix_syscall3_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall3_nr_last
+rustix_syscall3_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $7
+ syscall
+ negu $8, $2
+ jr $31
+ movn $2, $8, $7
+ .end rustix_syscall3_nr_last
+ .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
+
+ .section .text.rustix_syscall4_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall4_nr_last
+ .hidden rustix_syscall4_nr_last
+ .type rustix_syscall4_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall4_nr_last
+rustix_syscall4_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ lw $2, 16($sp)
+ syscall
+ negu $8, $2
+ jr $31
+ movn $2, $8, $7
+ .end rustix_syscall4_nr_last
+ .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
+
+ .section .text.rustix_syscall5_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall5_nr_last
+ .hidden rustix_syscall5_nr_last
+ .type rustix_syscall5_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall5_nr_last
+rustix_syscall5_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ lw $2, 20($sp)
+ syscall
+ negu $8, $2
+ jr $31
+ movn $2, $8, $7
+ .end rustix_syscall5_nr_last
+ .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
+
+ .section .text.rustix_syscall6_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall6_nr_last
+ .hidden rustix_syscall6_nr_last
+ .type rustix_syscall6_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall6_nr_last
+rustix_syscall6_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ lw $2, 24($sp)
+ syscall
+ negu $8, $2
+ jr $31
+ movn $2, $8, $7
+ .end rustix_syscall6_nr_last
+ .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
+
+ .section .note.GNU-stack,"",@progbits
+
+ .section .text.rustix_syscall7_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall7_nr_last
+ .hidden rustix_syscall7_nr_last
+ .type rustix_syscall7_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall7_nr_last
+rustix_syscall7_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ lw $2, 28($sp)
+ syscall
+ negu $8, $2
+ jr $31
+ movn $2, $8, $7
+ .end rustix_syscall7_nr_last
+ .size rustix_syscall7_nr_last, .-rustix_syscall7_nr_last
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/mips64.s b/vendor/rustix/src/imp/linux_raw/arch/outline/mips64.s
new file mode 100644
index 000000000..3c5e76e36
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/mips64.s
@@ -0,0 +1,189 @@
+# Assembly code for making mips64 syscalls.
+#
+# mips64 syscall argument register ordering is the same as the mips64
+# userspace argument register ordering except that the syscall number
+# (nr) is passed in v0.
+#
+# outline.rs takes care of reordering the nr argument to the end for us,
+# so we only need to move nr into v0.
+
+ .file "mips.s"
+ .section .mdebug.abi64
+ .previous
+ .abicalls
+
+ .section .text.rustix_syscall0_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall0_nr_last
+ .hidden rustix_syscall0_nr_last
+ .type rustix_syscall0_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall0_nr_last
+rustix_syscall0_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $4
+ syscall
+ dnegu $12, $2
+ jr $31
+ movn $2, $12, $7
+ .end rustix_syscall0_nr_last
+ .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
+
+ .section .text.rustix_syscall1_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall1_nr_last
+ .hidden rustix_syscall1_nr_last
+ .type rustix_syscall1_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall1_nr_last
+rustix_syscall1_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $5
+ syscall
+ dnegu $12, $2
+ jr $31
+ movn $2, $12, $7
+ .end rustix_syscall1_nr_last
+ .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
+
+ .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall1_noreturn_nr_last
+ .hidden rustix_syscall1_noreturn_nr_last
+ .type rustix_syscall1_noreturn_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall1_noreturn_nr_last
+rustix_syscall1_noreturn_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $5
+ syscall
+ teq $0, $0
+ .end rustix_syscall1_noreturn_nr_last
+ .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
+
+ .section .text.rustix_syscall2_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall2_nr_last
+ .hidden rustix_syscall2_nr_last
+ .type rustix_syscall2_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall2_nr_last
+rustix_syscall2_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $6
+ syscall
+ dnegu $12, $2
+ jr $31
+ movn $2, $12, $7
+ .end rustix_syscall2_nr_last
+ .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
+
+ .section .text.rustix_syscall3_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall3_nr_last
+ .hidden rustix_syscall3_nr_last
+ .type rustix_syscall3_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall3_nr_last
+rustix_syscall3_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $7
+ syscall
+ dnegu $12, $2
+ jr $31
+ movn $2, $12, $7
+ .end rustix_syscall3_nr_last
+ .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
+
+ .section .text.rustix_syscall4_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall4_nr_last
+ .hidden rustix_syscall4_nr_last
+ .type rustix_syscall4_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall4_nr_last
+rustix_syscall4_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $8
+ syscall
+ dnegu $12, $2
+ jr $31
+ movn $2, $12, $7
+ .end rustix_syscall4_nr_last
+ .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
+
+ .section .text.rustix_syscall5_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall5_nr_last
+ .hidden rustix_syscall5_nr_last
+ .type rustix_syscall5_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall5_nr_last
+rustix_syscall5_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $9
+ syscall
+ dnegu $12, $2
+ jr $31
+ movn $2, $12, $7
+ .end rustix_syscall5_nr_last
+ .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
+
+ .section .text.rustix_syscall6_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall6_nr_last
+ .hidden rustix_syscall6_nr_last
+ .type rustix_syscall6_nr_last, @function
+ .set nomips16
+ .set nomicromips
+ .ent rustix_syscall6_nr_last
+rustix_syscall6_nr_last:
+ .frame $sp,0,$31
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ .set noreorder
+ .set nomacro
+ move $2, $10
+ syscall
+ dnegu $12, $2
+ jr $31
+ movn $2, $12, $7
+ .end rustix_syscall6_nr_last
+ .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/mod.rs b/vendor/rustix/src/imp/linux_raw/arch/outline/mod.rs
new file mode 100644
index 000000000..ce1352751
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/mod.rs
@@ -0,0 +1,33 @@
+//! Declare functions defined in out-of-line ("outline") asm files.
+//!
+//! Kernel calling conventions differ from userspace calling conventions,
+//! so we also define inline function wrappers which reorder the arguments
+//! so that they match with the kernel convention as closely as possible,
+//! to minimize the amount of out-of-line code we need.
+
+#[cfg(target_arch = "x86")]
+mod x86;
+// For these architectures, pass the `nr` argument last.
+#[cfg(any(
+ target_arch = "arm",
+ target_arch = "aarch64",
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ target_arch = "riscv64",
+ target_arch = "x86_64",
+))]
+mod nr_last;
+
+#[cfg(any(
+ target_arch = "arm",
+ target_arch = "aarch64",
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ target_arch = "riscv64",
+ target_arch = "x86_64",
+))]
+pub(in crate::imp) use nr_last::*;
+#[cfg(target_arch = "x86")]
+pub(in crate::imp) use x86::*;
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs b/vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs
new file mode 100644
index 000000000..fdcd11021
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs
@@ -0,0 +1,166 @@
+//! Syscall wrappers for platforms which pass the syscall number specially.
+//!
+//! Rustix aims to minimize the amount of assembly code it needs. To that end,
+//! this code reorders syscall arguments as close as feasible to the actual
+//! syscall convention before calling the assembly functions.
+//!
+//! Many architectures use a convention where the syscall number is passed in a
+//! special register, with the regular syscall arguments passed in either the
+//! same or similar registers as the platform C convention. This code
+//! approximates that order by passing the regular syscall arguments first, and
+//! the syscall number last. That way, the outline assembly code typically just
+//! needs to move the syscall number to its special register, and leave the
+//! other arguments mostly as they are.
+
+#[cfg(target_arch = "mips")]
+use crate::imp::reg::A6;
+use crate::imp::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
+
+// First we declare the actual assembly routines with `*_nr_last` names and
+// reordered arguments. If the signatures or calling conventions are ever
+// changed, the symbol names should also be updated accordingly, to avoid
+// collisions with other versions of this crate.
+//
+// We don't define `_readonly` versions of these because we have no way to tell
+// Rust that calls to our outline assembly are readonly.
+extern "C" {
+ fn rustix_syscall0_nr_last(nr: SyscallNumber<'_>) -> RetReg<R0>;
+ fn rustix_syscall1_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>;
+ fn rustix_syscall1_noreturn_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !;
+ fn rustix_syscall2_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall3_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall4_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall5_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall6_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ #[cfg(target_arch = "mips")]
+ fn rustix_syscall7_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ a6: ArgReg<'_, A6>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+}
+
+// Then we define inline wrapper functions that do the reordering.
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ rustix_syscall0_nr_last(nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ rustix_syscall1_nr_last(a0, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ rustix_syscall1_noreturn_nr_last(a0, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ rustix_syscall2_nr_last(a0, a1, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ rustix_syscall3_nr_last(a0, a1, a2, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ rustix_syscall4_nr_last(a0, a1, a2, a3, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ rustix_syscall5_nr_last(a0, a1, a2, a3, a4, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ rustix_syscall6_nr_last(a0, a1, a2, a3, a4, a5, nr)
+}
+#[cfg(target_arch = "mips")]
+#[inline]
+pub(in crate::imp) unsafe fn syscall7(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ a6: ArgReg<'_, A6>,
+) -> RetReg<R0> {
+ rustix_syscall7_nr_last(a0, a1, a2, a3, a4, a5, a6, nr)
+}
+
+// Then we define the `_readonly` versions of the wrappers. We don't have
+// separate `_readonly` implementations, so these can just be aliases to
+// their non-`_readonly` counterparts.
+#[cfg(target_arch = "mips")]
+pub(in crate::imp) use syscall7 as syscall7_readonly;
+pub(in crate::imp) use {
+ syscall0 as syscall0_readonly, syscall1 as syscall1_readonly, syscall2 as syscall2_readonly,
+ syscall3 as syscall3_readonly, syscall4 as syscall4_readonly, syscall5 as syscall5_readonly,
+ syscall6 as syscall6_readonly,
+};
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/powerpc64.s b/vendor/rustix/src/imp/linux_raw/arch/outline/powerpc64.s
new file mode 100644
index 000000000..29d4c0a95
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/powerpc64.s
@@ -0,0 +1,132 @@
+# Assembly code for making powerpc64le syscalls.
+#
+# powerpc64le syscall argument register ordering is the same as the
+# powerpc64le userspace argument register ordering except that the syscall
+# number (nr) is passed in r0.
+#
+# outline.rs takes care of reordering the nr argument to the end for us,
+# so we only need to move nr into r0.
+
+ .file "powerpc64le.s"
+ .machine power8
+ .abiversion 2
+
+ .section .text.rustix_syscall0_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall0_nr_last
+ .hidden rustix_syscall0_nr_last
+ .type rustix_syscall0_nr_last, @function
+rustix_syscall0_nr_last:
+ .cfi_startproc
+ mr 0, 3
+ sc
+ bnslr
+ neg 3, 3
+ blr
+ .cfi_endproc
+ .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
+
+ .section .text.rustix_syscall1_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall1_nr_last
+ .hidden rustix_syscall1_nr_last
+ .type rustix_syscall1_nr_last, @function
+rustix_syscall1_nr_last:
+ .cfi_startproc
+ mr 0, 4
+ sc
+ bnslr
+ neg 3, 3
+ blr
+ .cfi_endproc
+ .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
+
+ .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall1_noreturn_nr_last
+ .hidden rustix_syscall1_noreturn_nr_last
+ .type rustix_syscall1_noreturn_nr_last, @function
+rustix_syscall1_noreturn_nr_last:
+ .cfi_startproc
+ mr 0, 4
+ sc
+ trap
+ .cfi_endproc
+ .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
+
+ .section .text.rustix_syscall2_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall2_nr_last
+ .hidden rustix_syscall2_nr_last
+ .type rustix_syscall2_nr_last, @function
+rustix_syscall2_nr_last:
+ .cfi_startproc
+ mr 0, 5
+ sc
+ bnslr
+ neg 3, 3
+ blr
+ .cfi_endproc
+ .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
+
+ .section .text.rustix_syscall3_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall3_nr_last
+ .hidden rustix_syscall3_nr_last
+ .type rustix_syscall3_nr_last, @function
+rustix_syscall3_nr_last:
+ .cfi_startproc
+ mr 0, 6
+ sc
+ bnslr
+ neg 3, 3
+ blr
+ .cfi_endproc
+ .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
+
+ .section .text.rustix_syscall4_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall4_nr_last
+ .hidden rustix_syscall4_nr_last
+ .type rustix_syscall4_nr_last, @function
+rustix_syscall4_nr_last:
+ .cfi_startproc
+ mr 0, 7
+ sc
+ bnslr
+ neg 3, 3
+ blr
+ .cfi_endproc
+ .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
+
+ .section .text.rustix_syscall5_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall5_nr_last
+ .hidden rustix_syscall5_nr_last
+ .type rustix_syscall5_nr_last, @function
+rustix_syscall5_nr_last:
+ .cfi_startproc
+ mr 0, 8
+ sc
+ bnslr
+ neg 3, 3
+ blr
+ .cfi_endproc
+ .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
+
+ .section .text.rustix_syscall6_nr_last,"ax",@progbits
+ .p2align 2
+ .weak rustix_syscall6_nr_last
+ .hidden rustix_syscall6_nr_last
+ .type rustix_syscall6_nr_last, @function
+rustix_syscall6_nr_last:
+ .cfi_startproc
+ mr 0, 9
+ sc
+ bnslr
+ neg 3, 3
+ blr
+ .cfi_endproc
+ .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/riscv64.s b/vendor/rustix/src/imp/linux_raw/arch/outline/riscv64.s
new file mode 100644
index 000000000..28d692f7c
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/riscv64.s
@@ -0,0 +1,116 @@
+# Assembly code for making riscv64 syscalls.
+#
+# riscv64 syscall argument register ordering is the same as the riscv64
+# userspace argument register ordering except that the syscall number
+# (nr) is passed in a7.
+#
+# nr_last.rs takes care of reordering the nr argument to the end for us,
+# so we only need to move nr into a7.
+
+ .file "riscv64.s"
+
+ .section .text.rustix_syscall0_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall0_nr_last
+ .hidden rustix_syscall0_nr_last
+ .type rustix_syscall0_nr_last, @function
+rustix_syscall0_nr_last:
+ .cfi_startproc
+ mv a7, a0
+ ecall
+ ret
+ .cfi_endproc
+ .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
+
+ .section .text.rustix_syscall1_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall1_nr_last
+ .hidden rustix_syscall1_nr_last
+ .type rustix_syscall1_nr_last, @function
+rustix_syscall1_nr_last:
+ .cfi_startproc
+ mv a7, a1
+ ecall
+ ret
+ .cfi_endproc
+ .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
+
+ .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall1_noreturn_nr_last
+ .hidden rustix_syscall1_noreturn_nr_last
+ .type rustix_syscall1_noreturn_nr_last, @function
+rustix_syscall1_noreturn_nr_last:
+ .cfi_startproc
+ mv a7, a1
+ ecall
+ unimp
+ .cfi_endproc
+ .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
+
+ .section .text.rustix_syscall2_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall2_nr_last
+ .hidden rustix_syscall2_nr_last
+ .type rustix_syscall2_nr_last, @function
+rustix_syscall2_nr_last:
+ .cfi_startproc
+ mv a7, a2
+ ecall
+ ret
+ .cfi_endproc
+ .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
+
+ .section .text.rustix_syscall3_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall3_nr_last
+ .hidden rustix_syscall3_nr_last
+ .type rustix_syscall3_nr_last, @function
+rustix_syscall3_nr_last:
+ .cfi_startproc
+ mv a7, a3
+ ecall
+ ret
+ .cfi_endproc
+ .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
+
+ .section .text.rustix_syscall4_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall4_nr_last
+ .hidden rustix_syscall4_nr_last
+ .type rustix_syscall4_nr_last, @function
+rustix_syscall4_nr_last:
+ .cfi_startproc
+ mv a7, a4
+ ecall
+ ret
+ .cfi_endproc
+ .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
+
+ .section .text.rustix_syscall5_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall5_nr_last
+ .hidden rustix_syscall5_nr_last
+ .type rustix_syscall5_nr_last, @function
+rustix_syscall5_nr_last:
+ .cfi_startproc
+ mv a7, a5
+ ecall
+ ret
+ .cfi_endproc
+ .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
+
+ .section .text.rustix_syscall6_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall6_nr_last
+ .hidden rustix_syscall6_nr_last
+ .type rustix_syscall6_nr_last, @function
+rustix_syscall6_nr_last:
+ .cfi_startproc
+ mv a7, a6
+ ecall
+ ret
+ .cfi_endproc
+ .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/x86.rs b/vendor/rustix/src/imp/linux_raw/arch/outline/x86.rs
new file mode 100644
index 000000000..938a4a09d
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/x86.rs
@@ -0,0 +1,285 @@
+//! Syscall wrappers for 32-bit x86.
+//!
+//! This module is similar to the `nr_last` module, except specialized for
+//! 32-bit x86.
+//!
+//! The syscall convention passes all arguments in registers. The closest we
+//! can easily get to that from Rust is to use the fastcall convention which
+//! passes the first two arguments in `ecx` and `edx`, which are the second
+//! and third Linux syscall arguments. To line them up, this function passes
+//! the second and third syscall argument as the first and second argument to
+//! the outline assembly, followed by the first syscall argument, and then the
+//! rest of the syscall arguments. The assembly code still has to do some work,
+//! but at least we can get up to two arguments into the right place for it.
+
+#![allow(dead_code, unused_imports)]
+
+use crate::imp::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
+use crate::imp::vdso_wrappers::SyscallType;
+
+// First we declare the actual assembly routines with `*_nr_last_fastcall`
+// names and reordered arguments. If the signatures or calling conventions are
+// ever changed, the symbol names should also be updated accordingly, to avoid
+// collisions with other versions of this crate.
+//
+// We don't define `_readonly` versions of these because we have no way to tell
+// Rust that calls to our outline assembly are readonly.
+extern "fastcall" {
+ fn rustix_syscall0_nr_last_fastcall(nr: SyscallNumber<'_>) -> RetReg<R0>;
+ fn rustix_syscall1_nr_last_fastcall(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>;
+ fn rustix_syscall1_noreturn_nr_last_fastcall(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !;
+ fn rustix_syscall2_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a0: ArgReg<'_, A0>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall3_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a0: ArgReg<'_, A0>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall4_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a0: ArgReg<'_, A0>,
+ a3: ArgReg<'_, A3>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall5_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a0: ArgReg<'_, A0>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall6_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a0: ArgReg<'_, A0>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+}
+
+// Then we define inline wrapper functions that do the reordering.
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ rustix_syscall0_nr_last_fastcall(nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ rustix_syscall1_nr_last_fastcall(a0, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ rustix_syscall1_noreturn_nr_last_fastcall(a0, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ rustix_syscall2_nr_last_fastcall(a1, a0, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ rustix_syscall3_nr_last_fastcall(a1, a2, a0, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ rustix_syscall4_nr_last_fastcall(a1, a2, a0, a3, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ rustix_syscall5_nr_last_fastcall(a1, a2, a0, a3, a4, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ rustix_syscall6_nr_last_fastcall(a1, a2, a0, a3, a4, a5, nr)
+}
+
+// Then we define the `_readonly` versions of the wrappers. We don't have
+// separate `_readonly` implementations, so these can just be aliases to
+// their non-`_readonly` counterparts.
+pub(in crate::imp) use {
+ syscall0 as syscall0_readonly, syscall1 as syscall1_readonly, syscall2 as syscall2_readonly,
+ syscall3 as syscall3_readonly, syscall4 as syscall4_readonly, syscall5 as syscall5_readonly,
+ syscall6 as syscall6_readonly,
+};
+
+// x86 prefers to route all syscalls through the vDSO, though this isn't
+// always possible, so it also has a special form for doing the dispatch.
+//
+// First we declare the actual assembly routines with `*_nr_last_fastcall`
+// names and reordered arguments. If the signatures or calling conventions are
+// ever changed, the symbol names should also be updated accordingly, to avoid
+// collisions with other versions of this crate.
+extern "fastcall" {
+ fn rustix_indirect_syscall0_nr_last_fastcall(
+ nr: SyscallNumber<'_>,
+ callee: SyscallType,
+ ) -> RetReg<R0>;
+ fn rustix_indirect_syscall1_nr_last_fastcall(
+ a0: ArgReg<'_, A0>,
+ nr: SyscallNumber<'_>,
+ callee: SyscallType,
+ ) -> RetReg<R0>;
+ fn rustix_indirect_syscall1_noreturn_nr_last_fastcall(
+ a0: ArgReg<'_, A0>,
+ nr: SyscallNumber<'_>,
+ callee: SyscallType,
+ ) -> !;
+ fn rustix_indirect_syscall2_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a0: ArgReg<'_, A0>,
+ nr: SyscallNumber<'_>,
+ callee: SyscallType,
+ ) -> RetReg<R0>;
+ fn rustix_indirect_syscall3_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a0: ArgReg<'_, A0>,
+ nr: SyscallNumber<'_>,
+ callee: SyscallType,
+ ) -> RetReg<R0>;
+ fn rustix_indirect_syscall4_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a0: ArgReg<'_, A0>,
+ a3: ArgReg<'_, A3>,
+ nr: SyscallNumber<'_>,
+ callee: SyscallType,
+ ) -> RetReg<R0>;
+ fn rustix_indirect_syscall5_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a0: ArgReg<'_, A0>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ nr: SyscallNumber<'_>,
+ callee: SyscallType,
+ ) -> RetReg<R0>;
+ fn rustix_indirect_syscall6_nr_last_fastcall(
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a0: ArgReg<'_, A0>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ nr: SyscallNumber<'_>,
+ callee: SyscallType,
+ ) -> RetReg<R0>;
+}
+
+// Then we define inline wrapper functions that do the reordering.
+
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall0(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+) -> RetReg<R0> {
+ rustix_indirect_syscall0_nr_last_fastcall(nr, callee)
+}
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall1(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+ rustix_indirect_syscall1_nr_last_fastcall(a0, nr, callee)
+}
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall1_noreturn(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+) -> ! {
+ rustix_indirect_syscall1_noreturn_nr_last_fastcall(a0, nr, callee)
+}
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall2(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ rustix_indirect_syscall2_nr_last_fastcall(a1, a0, nr, callee)
+}
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall3(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ rustix_indirect_syscall3_nr_last_fastcall(a1, a2, a0, nr, callee)
+}
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall4(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ rustix_indirect_syscall4_nr_last_fastcall(a1, a2, a0, a3, nr, callee)
+}
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall5(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ rustix_indirect_syscall5_nr_last_fastcall(a1, a2, a0, a3, a4, nr, callee)
+}
+#[inline]
+pub(in crate::imp) unsafe fn indirect_syscall6(
+ callee: SyscallType,
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ rustix_indirect_syscall6_nr_last_fastcall(a1, a2, a0, a3, a4, a5, nr, callee)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/x86.s b/vendor/rustix/src/imp/linux_raw/arch/outline/x86.s
new file mode 100644
index 000000000..bda234e1a
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/x86.s
@@ -0,0 +1,381 @@
+// Assembly code for making x86 syscalls.
+//
+// On x86 we use the "fastcall" convention which passes the first two
+// arguments in ecx and edx. Outline.rs reorders the arguments to put
+// a1 and a2 in those registers so they we don't have to move them to
+// set up the kernel convention.
+//
+// "fastcall" expects callee to pop argument stack space, so we use
+// `ret imm` instructions to clean up the stack. We don't need callee
+// cleanup per se, it just comes along with using "fastcall".
+
+ .file "x86.s"
+ .intel_syntax noprefix
+
+ .section .text.rustix_indirect_syscall0_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_indirect_syscall0_nr_last_fastcall
+ .hidden rustix_indirect_syscall0_nr_last_fastcall
+ .type rustix_indirect_syscall0_nr_last_fastcall, @function
+rustix_indirect_syscall0_nr_last_fastcall:
+ .cfi_startproc
+ mov eax,ecx
+ call edx
+ ret
+ .cfi_endproc
+ .size rustix_indirect_syscall0_nr_last_fastcall, .-rustix_indirect_syscall0_nr_last_fastcall
+
+ .section .text.rustix_indirect_syscall1_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_indirect_syscall1_nr_last_fastcall
+ .hidden rustix_indirect_syscall1_nr_last_fastcall
+ .type rustix_indirect_syscall1_nr_last_fastcall, @function
+rustix_indirect_syscall1_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ .cfi_offset ebx, -8
+ mov ebx,ecx
+ mov eax,edx
+ call DWORD PTR [esp+0x8]
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0x4
+ .cfi_endproc
+ .size rustix_indirect_syscall1_nr_last_fastcall, .-rustix_indirect_syscall1_nr_last_fastcall
+
+ .section .text.rustix_indirect_syscall1_noreturn_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_indirect_syscall1_noreturn_nr_last_fastcall
+ .hidden rustix_indirect_syscall1_noreturn_nr_last_fastcall
+ .type rustix_indirect_syscall1_noreturn_nr_last_fastcall, @function
+rustix_indirect_syscall1_noreturn_nr_last_fastcall:
+ .cfi_startproc
+ mov ebx,ecx
+ mov eax,edx
+ call DWORD PTR [esp+0x4]
+ ud2
+ .cfi_endproc
+ .size rustix_indirect_syscall1_noreturn_nr_last_fastcall, .-rustix_indirect_syscall1_noreturn_nr_last_fastcall
+
+ .section .text.rustix_indirect_syscall2_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_indirect_syscall2_nr_last_fastcall
+ .hidden rustix_indirect_syscall2_nr_last_fastcall
+ .type rustix_indirect_syscall2_nr_last_fastcall, @function
+rustix_indirect_syscall2_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ .cfi_offset ebx, -8
+ mov ebx,edx
+ mov eax,DWORD PTR [esp+0x8]
+ call DWORD PTR [esp+0xc]
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0x8
+ .cfi_endproc
+ .size rustix_indirect_syscall2_nr_last_fastcall, .-rustix_indirect_syscall2_nr_last_fastcall
+
+ .section .text.rustix_indirect_syscall3_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_indirect_syscall3_nr_last_fastcall
+ .hidden rustix_indirect_syscall3_nr_last_fastcall
+ .type rustix_indirect_syscall3_nr_last_fastcall, @function
+rustix_indirect_syscall3_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ .cfi_offset ebx, -8
+ mov ebx,DWORD PTR [esp+0x8]
+ mov eax,DWORD PTR [esp+0xc]
+ call DWORD PTR [esp+0x10]
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0xc
+ .cfi_endproc
+ .size rustix_indirect_syscall3_nr_last_fastcall, .-rustix_indirect_syscall3_nr_last_fastcall
+
+ .section .text.rustix_indirect_syscall4_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_indirect_syscall4_nr_last_fastcall
+ .hidden rustix_indirect_syscall4_nr_last_fastcall
+ .type rustix_indirect_syscall4_nr_last_fastcall, @function
+rustix_indirect_syscall4_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ push esi
+ .cfi_def_cfa_offset 12
+ .cfi_offset esi, -12
+ .cfi_offset ebx, -8
+ mov ebx,DWORD PTR [esp+0xc]
+ mov esi,DWORD PTR [esp+0x10]
+ mov eax,DWORD PTR [esp+0x14]
+ call DWORD PTR [esp+0x18]
+ pop esi
+ .cfi_def_cfa_offset 8
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0x10
+ .cfi_endproc
+ .size rustix_indirect_syscall4_nr_last_fastcall, .-rustix_indirect_syscall4_nr_last_fastcall
+
+ .section .text.rustix_indirect_syscall5_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_indirect_syscall5_nr_last_fastcall
+ .hidden rustix_indirect_syscall5_nr_last_fastcall
+ .type rustix_indirect_syscall5_nr_last_fastcall, @function
+rustix_indirect_syscall5_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ push esi
+ .cfi_def_cfa_offset 12
+ push edi
+ .cfi_def_cfa_offset 16
+ .cfi_offset edi, -16
+ .cfi_offset esi, -12
+ .cfi_offset ebx, -8
+ mov ebx,DWORD PTR [esp+0x10]
+ mov esi,DWORD PTR [esp+0x14]
+ mov edi,DWORD PTR [esp+0x18]
+ mov eax,DWORD PTR [esp+0x1c]
+ call DWORD PTR [esp+0x20]
+ pop edi
+ .cfi_def_cfa_offset 12
+ pop esi
+ .cfi_def_cfa_offset 8
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0x14
+ .cfi_endproc
+ .size rustix_indirect_syscall5_nr_last_fastcall, .-rustix_indirect_syscall5_nr_last_fastcall
+
+ .section .text.rustix_indirect_syscall6_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_indirect_syscall6_nr_last_fastcall
+ .hidden rustix_indirect_syscall6_nr_last_fastcall
+ .type rustix_indirect_syscall6_nr_last_fastcall, @function
+rustix_indirect_syscall6_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ push esi
+ .cfi_def_cfa_offset 12
+ push edi
+ .cfi_def_cfa_offset 16
+ push ebp
+ .cfi_def_cfa_offset 20
+ .cfi_offset ebp, -20
+ .cfi_offset edi, -16
+ .cfi_offset esi, -12
+ .cfi_offset ebx, -8
+ mov ebx,DWORD PTR [esp+0x14]
+ mov esi,DWORD PTR [esp+0x18]
+ mov edi,DWORD PTR [esp+0x1c]
+ mov ebp,DWORD PTR [esp+0x20]
+ mov eax,DWORD PTR [esp+0x24]
+ call DWORD PTR [esp+0x28]
+ pop ebp
+ .cfi_def_cfa_offset 16
+ pop edi
+ .cfi_def_cfa_offset 12
+ pop esi
+ .cfi_def_cfa_offset 8
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0x18
+ .cfi_endproc
+ .size rustix_indirect_syscall6_nr_last_fastcall, .-rustix_indirect_syscall6_nr_last_fastcall
+
+ .section .text.rustix_syscall0_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall0_nr_last_fastcall
+ .hidden rustix_syscall0_nr_last_fastcall
+ .type rustix_syscall0_nr_last_fastcall, @function
+rustix_syscall0_nr_last_fastcall:
+ .cfi_startproc
+ mov eax,ecx
+ int 0x80
+ ret
+ .cfi_endproc
+ .size rustix_syscall0_nr_last_fastcall, .-rustix_syscall0_nr_last_fastcall
+
+ .section .text.rustix_syscall1_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall1_nr_last_fastcall
+ .hidden rustix_syscall1_nr_last_fastcall
+ .type rustix_syscall1_nr_last_fastcall, @function
+rustix_syscall1_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ .cfi_offset ebx, -8
+ mov eax,edx
+ mov ebx,ecx
+ int 0x80
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size rustix_syscall1_nr_last_fastcall, .-rustix_syscall1_nr_last_fastcall
+
+ .section .text.rustix_syscall1_noreturn_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall1_noreturn_nr_last_fastcall
+ .hidden rustix_syscall1_noreturn_nr_last_fastcall
+ .type rustix_syscall1_noreturn_nr_last_fastcall, @function
+rustix_syscall1_noreturn_nr_last_fastcall:
+ .cfi_startproc
+ mov eax,edx
+ mov ebx,ecx
+ int 0x80
+ ud2
+ .cfi_endproc
+ .size rustix_syscall1_noreturn_nr_last_fastcall, .-rustix_syscall1_noreturn_nr_last_fastcall
+
+ .section .text.rustix_syscall2_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall2_nr_last_fastcall
+ .hidden rustix_syscall2_nr_last_fastcall
+ .type rustix_syscall2_nr_last_fastcall, @function
+rustix_syscall2_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ .cfi_offset ebx, -8
+ mov ebx,edx
+ mov eax,DWORD PTR [esp+0x8]
+ int 0x80
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0x4
+ .cfi_endproc
+ .size rustix_syscall2_nr_last_fastcall, .-rustix_syscall2_nr_last_fastcall
+
+ .section .text.rustix_syscall3_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall3_nr_last_fastcall
+ .hidden rustix_syscall3_nr_last_fastcall
+ .type rustix_syscall3_nr_last_fastcall, @function
+rustix_syscall3_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ .cfi_offset ebx, -8
+ mov ebx,DWORD PTR [esp+0x8]
+ mov eax,DWORD PTR [esp+0xc]
+ int 0x80
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0x8
+ .cfi_endproc
+ .size rustix_syscall3_nr_last_fastcall, .-rustix_syscall3_nr_last_fastcall
+
+ .section .text.rustix_syscall4_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall4_nr_last_fastcall
+ .hidden rustix_syscall4_nr_last_fastcall
+ .type rustix_syscall4_nr_last_fastcall, @function
+rustix_syscall4_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ push esi
+ .cfi_def_cfa_offset 12
+ .cfi_offset esi, -12
+ .cfi_offset ebx, -8
+ mov ebx,DWORD PTR [esp+0xc]
+ mov esi,DWORD PTR [esp+0x10]
+ mov eax,DWORD PTR [esp+0x14]
+ int 0x80
+ pop esi
+ .cfi_def_cfa_offset 8
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0xc
+ .cfi_endproc
+ .size rustix_syscall4_nr_last_fastcall, .-rustix_syscall4_nr_last_fastcall
+
+ .section .text.rustix_syscall5_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall5_nr_last_fastcall
+ .hidden rustix_syscall5_nr_last_fastcall
+ .type rustix_syscall5_nr_last_fastcall, @function
+rustix_syscall5_nr_last_fastcall:
+ .cfi_startproc
+ push ebx
+ .cfi_def_cfa_offset 8
+ push edi
+ .cfi_def_cfa_offset 12
+ push esi
+ .cfi_def_cfa_offset 16
+ .cfi_offset esi, -16
+ .cfi_offset edi, -12
+ .cfi_offset ebx, -8
+ mov ebx,DWORD PTR [esp+0x10]
+ mov esi,DWORD PTR [esp+0x14]
+ mov edi,DWORD PTR [esp+0x18]
+ mov eax,DWORD PTR [esp+0x1c]
+ int 0x80
+ pop esi
+ .cfi_def_cfa_offset 12
+ pop edi
+ .cfi_def_cfa_offset 8
+ pop ebx
+ .cfi_def_cfa_offset 4
+ ret 0x10
+ .cfi_endproc
+ .size rustix_syscall5_nr_last_fastcall, .-rustix_syscall5_nr_last_fastcall
+
+ .section .text.rustix_syscall6_nr_last_fastcall,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall6_nr_last_fastcall
+ .hidden rustix_syscall6_nr_last_fastcall
+ .type rustix_syscall6_nr_last_fastcall, @function
+rustix_syscall6_nr_last_fastcall:
+ .cfi_startproc
+ push ebp
+ .cfi_def_cfa_offset 8
+ push ebx
+ .cfi_def_cfa_offset 12
+ push edi
+ .cfi_def_cfa_offset 16
+ push esi
+ .cfi_def_cfa_offset 20
+ .cfi_offset esi, -20
+ .cfi_offset edi, -16
+ .cfi_offset ebx, -12
+ .cfi_offset ebp, -8
+ mov ebx,DWORD PTR [esp+0x14]
+ mov esi,DWORD PTR [esp+0x18]
+ mov edi,DWORD PTR [esp+0x1c]
+ mov ebp,DWORD PTR [esp+0x20]
+ mov eax,DWORD PTR [esp+0x24]
+ int 0x80
+ pop esi
+ .cfi_def_cfa_offset 16
+ pop edi
+ .cfi_def_cfa_offset 12
+ pop ebx
+ .cfi_def_cfa_offset 8
+ pop ebp
+ .cfi_def_cfa_offset 4
+ ret 0x14
+ .cfi_endproc
+ .size rustix_syscall6_nr_last_fastcall, .-rustix_syscall6_nr_last_fastcall
+
+ .section .text.rustix_int_0x80,"ax",@progbits
+ .p2align 4
+ .weak rustix_int_0x80
+ .hidden rustix_int_0x80
+ .type rustix_int_0x80, @function
+rustix_int_0x80:
+ .cfi_startproc
+ int 0x80
+ ret
+ .cfi_endproc
+ .size rustix_int_0x80, .-rustix_int_0x80
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/x86_64.s b/vendor/rustix/src/imp/linux_raw/arch/outline/x86_64.s
new file mode 100644
index 000000000..2beda323b
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/x86_64.s
@@ -0,0 +1,122 @@
+// Assembly code for making x86-64 syscalls.
+//
+// x86-64 syscall argument register ordering is the same as the x86-64
+// userspace argument register ordering except that a3 is passed in r10
+// instead of rcx, and the syscall number (nr) is passed in eax.
+//
+// outline.rs takes care of reordering the nr argument to the end for us,
+// so we only need to move nr into eax and move rcx into r10 as needed.
+//
+// x32 is not yet supported.
+
+ .file "x86_64.s"
+ .intel_syntax noprefix
+
+ .section .text.rustix_syscall0_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall0_nr_last
+ .hidden rustix_syscall0_nr_last
+ .type rustix_syscall0_nr_last, @function
+rustix_syscall0_nr_last:
+ .cfi_startproc
+ mov eax,edi
+ syscall
+ ret
+ .cfi_endproc
+ .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
+
+ .section .text.rustix_syscall1_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall1_nr_last
+ .hidden rustix_syscall1_nr_last
+ .type rustix_syscall1_nr_last, @function
+rustix_syscall1_nr_last:
+ .cfi_startproc
+ mov eax,esi
+ syscall
+ ret
+ .cfi_endproc
+ .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
+
+ .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall1_noreturn_nr_last
+ .hidden rustix_syscall1_noreturn_nr_last
+ .type rustix_syscall1_noreturn_nr_last, @function
+rustix_syscall1_noreturn_nr_last:
+ .cfi_startproc
+ mov eax,esi
+ syscall
+ ud2
+ .cfi_endproc
+ .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
+
+ .section .text.rustix_syscall2_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall2_nr_last
+ .hidden rustix_syscall2_nr_last
+ .type rustix_syscall2_nr_last, @function
+rustix_syscall2_nr_last:
+ .cfi_startproc
+ mov eax,edx
+ syscall
+ ret
+ .cfi_endproc
+ .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
+
+ .section .text.rustix_syscall3_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall3_nr_last
+ .hidden rustix_syscall3_nr_last
+ .type rustix_syscall3_nr_last, @function
+rustix_syscall3_nr_last:
+ .cfi_startproc
+ mov eax,ecx
+ syscall
+ ret
+ .cfi_endproc
+ .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
+
+ .section .text.rustix_syscall4_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall4_nr_last
+ .hidden rustix_syscall4_nr_last
+ .type rustix_syscall4_nr_last, @function
+rustix_syscall4_nr_last:
+ .cfi_startproc
+ mov eax,r8d
+ mov r10,rcx
+ syscall
+ ret
+ .cfi_endproc
+ .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
+
+ .section .text.rustix_syscall5_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall5_nr_last
+ .hidden rustix_syscall5_nr_last
+ .type rustix_syscall5_nr_last, @function
+rustix_syscall5_nr_last:
+ .cfi_startproc
+ mov eax,r9d
+ mov r10,rcx
+ syscall
+ ret
+ .cfi_endproc
+ .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
+
+ .section .text.rustix_syscall6_nr_last,"ax",@progbits
+ .p2align 4
+ .weak rustix_syscall6_nr_last
+ .hidden rustix_syscall6_nr_last
+ .type rustix_syscall6_nr_last, @function
+rustix_syscall6_nr_last:
+ .cfi_startproc
+ mov eax,DWORD PTR [rsp+0x8]
+ mov r10,rcx
+ syscall
+ ret
+ .cfi_endproc
+ .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/vendor/rustix/src/imp/linux_raw/c.rs b/vendor/rustix/src/imp/linux_raw/c.rs
new file mode 100644
index 000000000..a6f0b8ff6
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/c.rs
@@ -0,0 +1,29 @@
+//! Adapt the Linux API to resemble a POSIX-style libc API.
+//!
+//! The linux_raw backend doesn't use actual libc; this just defines certain
+//! types that are convenient to have defined.
+
+#![allow(unused_imports)]
+
+pub(crate) use linux_raw_sys::ctypes::*;
+pub(crate) use linux_raw_sys::errno::EINVAL;
+pub(crate) use linux_raw_sys::general::{
+ AF_DECnet, __kernel_sa_family_t as sa_family_t, __kernel_sockaddr_storage as sockaddr_storage,
+ in6_addr, in_addr, iovec, ip_mreq, ipv6_mreq, linger, sockaddr, sockaddr_in, sockaddr_in6,
+ sockaddr_un, socklen_t, AF_APPLETALK, AF_ASH, AF_ATMPVC, AF_ATMSVC, AF_AX25, AF_BLUETOOTH,
+ AF_BRIDGE, AF_CAN, AF_ECONET, AF_IEEE802154, AF_INET, AF_INET6, AF_IPX, AF_IRDA, AF_ISDN,
+ AF_IUCV, AF_KEY, AF_LLC, AF_NETBEUI, AF_NETLINK, AF_NETROM, AF_PACKET, AF_PHONET, AF_PPPOX,
+ AF_RDS, AF_ROSE, AF_RXRPC, AF_SECURITY, AF_SNA, AF_TIPC, AF_UNIX, AF_UNSPEC, AF_WANPIPE,
+ AF_X25, IPPROTO_AH, IPPROTO_BEETPH, IPPROTO_COMP, IPPROTO_DCCP, IPPROTO_EGP, IPPROTO_ENCAP,
+ IPPROTO_ESP, IPPROTO_ETHERNET, IPPROTO_FRAGMENT, IPPROTO_GRE, IPPROTO_ICMP, IPPROTO_ICMPV6,
+ IPPROTO_IDP, IPPROTO_IGMP, IPPROTO_IP, IPPROTO_IPIP, IPPROTO_IPV6, IPPROTO_MH, IPPROTO_MPLS,
+ IPPROTO_MPTCP, IPPROTO_MTP, IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW, IPPROTO_ROUTING,
+ IPPROTO_RSVP, IPPROTO_SCTP, IPPROTO_TCP, IPPROTO_TP, IPPROTO_UDP, IPPROTO_UDPLITE,
+ IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY, IP_ADD_MEMBERSHIP,
+ IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL, MSG_CMSG_CLOEXEC, MSG_CONFIRM,
+ MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_ERRQUEUE, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PEEK,
+ MSG_TRUNC, MSG_WAITALL, O_CLOEXEC, O_NONBLOCK, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM,
+ SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_LINGER,
+ SO_PASSCRED, SO_RCVTIMEO_NEW, SO_RCVTIMEO_OLD, SO_REUSEADDR, SO_SNDTIMEO_NEW, SO_SNDTIMEO_OLD,
+ SO_TYPE, TCP_NODELAY,
+};
diff --git a/vendor/rustix/src/imp/linux_raw/conv.rs b/vendor/rustix/src/imp/linux_raw/conv.rs
new file mode 100644
index 000000000..c80ad58cc
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/conv.rs
@@ -0,0 +1,770 @@
+//! Convert values to [`ArgReg`] and from [`RetReg`].
+//!
+//! System call arguments and return values are all communicated with inline
+//! asm and FFI as `*mut Opaque`. To protect these raw pointers from escaping
+//! or being accidentally misused as they travel through the code, we wrap
+//! them in [`ArgReg`] and [`RetReg`] structs. This file provides `From`
+//! implementations and explicit conversion functions for converting values
+//! into and out of these wrapper structs.
+//!
+//! # Safety
+//!
+//! Some of this code is `unsafe` in order to work with raw file descriptors,
+//! and some is `unsafe` to interpret the values in a `RetReg`.
+#![allow(unsafe_code)]
+
+use super::c;
+use super::fd::{AsRawFd, BorrowedFd, FromRawFd, RawFd};
+#[cfg(not(debug_assertions))]
+use super::io::errno::decode_usize_infallible;
+#[cfg(feature = "runtime")]
+use super::io::errno::try_decode_error;
+#[cfg(target_pointer_width = "64")]
+use super::io::errno::try_decode_u64;
+use super::io::errno::{
+ try_decode_c_int, try_decode_c_uint, try_decode_raw_fd, try_decode_usize, try_decode_void,
+ try_decode_void_star,
+};
+use super::reg::{raw_arg, ArgNumber, ArgReg, RetReg, R0};
+#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
+use super::time::types::ClockId;
+#[cfg(feature = "time")]
+use super::time::types::TimerfdClockId;
+use crate::ffi::CStr;
+use crate::fs::{FileType, Mode, OFlags};
+use crate::io::{self, OwnedFd};
+use crate::process::{Pid, Resource, Signal};
+use crate::utils::{as_mut_ptr, as_ptr};
+use core::mem::MaybeUninit;
+use core::ptr::null_mut;
+#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
+use linux_raw_sys::general::__kernel_clockid_t;
+#[cfg(target_pointer_width = "64")]
+use linux_raw_sys::general::__kernel_loff_t;
+#[cfg(feature = "net")]
+use linux_raw_sys::general::socklen_t;
+#[cfg(target_pointer_width = "32")]
+use linux_raw_sys::general::O_LARGEFILE;
+
+/// Convert `SYS_*` constants for socketcall.
+#[cfg(target_arch = "x86")]
+#[inline]
+pub(super) fn x86_sys<'a, Num: ArgNumber>(sys: u32) -> ArgReg<'a, Num> {
+ pass_usize(sys as usize)
+}
+
+/// Pass the "low" half of the endian-specific memory encoding of a `u64`, for
+/// 32-bit architectures.
+#[cfg(target_pointer_width = "32")]
+#[inline]
+pub(super) fn lo<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num> {
+ #[cfg(target_endian = "little")]
+ let x = x >> 32;
+ #[cfg(target_endian = "big")]
+ let x = x & 0xffff_ffff;
+
+ pass_usize(x as usize)
+}
+
+/// Pass the "high" half of the endian-specific memory encoding of a `u64`, for
+/// 32-bit architectures.
+#[cfg(target_pointer_width = "32")]
+#[inline]
+pub(super) fn hi<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num> {
+ #[cfg(target_endian = "little")]
+ let x = x & 0xffff_ffff;
+ #[cfg(target_endian = "big")]
+ let x = x >> 32;
+
+ pass_usize(x as usize)
+}
+
+/// Pass a zero, or null, argument.
+#[inline]
+pub(super) fn zero<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
+ raw_arg(null_mut())
+}
+
+/// Pass the `mem::size_of` of a type.
+#[inline]
+pub(super) fn size_of<'a, T: Sized, Num: ArgNumber>() -> ArgReg<'a, Num> {
+ pass_usize(core::mem::size_of::<T>())
+}
+
+/// Pass an arbitrary `usize` value.
+///
+/// For passing pointers, use `void_star` or other functions which take a raw
+/// pointer instead of casting to `usize`, so that provenance is preserved.
+#[inline]
+pub(super) fn pass_usize<'a, Num: ArgNumber>(t: usize) -> ArgReg<'a, Num> {
+ raw_arg(t as *mut _)
+}
+
+impl<'a, Num: ArgNumber, T> From<*mut T> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(c: *mut T) -> ArgReg<'a, Num> {
+ raw_arg(c.cast())
+ }
+}
+
+impl<'a, Num: ArgNumber, T> From<*const T> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(c: *const T) -> ArgReg<'a, Num> {
+ let mut_ptr = c as *mut T;
+ raw_arg(mut_ptr.cast())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<&'a CStr> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(c: &'a CStr) -> Self {
+ let mut_ptr = c.as_ptr() as *mut u8;
+ raw_arg(mut_ptr.cast())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<Option<&'a CStr>> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(t: Option<&'a CStr>) -> Self {
+ raw_arg(match t {
+ Some(s) => {
+ let mut_ptr = s.as_ptr() as *mut u8;
+ mut_ptr.cast()
+ }
+ None => null_mut(),
+ })
+ }
+}
+
+/// Pass a borrowed file-descriptor argument.
+impl<'a, Num: ArgNumber> From<BorrowedFd<'a>> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(fd: BorrowedFd<'a>) -> Self {
+ // Safety: `BorrowedFd` ensures that the file descriptor is valid, and the
+ // lifetime parameter on the resulting `ArgReg` ensures that the result is
+ // bounded by the `BorrowedFd`'s lifetime.
+ unsafe { raw_fd(fd.as_raw_fd()) }
+ }
+}
+
+/// Pass a raw file-descriptor argument. Most users should use [`ArgReg::from`]
+/// instead, to preserve I/O safety as long as possible.
+///
+/// # Safety
+///
+/// `fd` must be a valid open file descriptor.
+#[inline]
+pub(super) unsafe fn raw_fd<'a, Num: ArgNumber>(fd: RawFd) -> ArgReg<'a, Num> {
+ // Use `no_fd` when passing `-1` is intended.
+ debug_assert!(fd == crate::fs::cwd().as_raw_fd() || fd >= 0);
+
+ // Don't pass the `io_uring_register_files_skip` sentry value this way.
+ #[cfg(feature = "io_uring")]
+ debug_assert_ne!(
+ fd,
+ crate::io_uring::io_uring_register_files_skip().as_raw_fd()
+ );
+
+ // Linux doesn't look at the high bits beyond the `c_int`, so use
+ // zero-extension rather than sign-extension because it's a smaller
+ // instruction.
+ let fd: c::c_int = fd;
+ pass_usize(fd as c::c_uint as usize)
+}
+
+/// Deliberately pass `-1` to a file-descriptor argument, for system calls
+/// like `mmap` where this indicates the argument is omitted.
+#[inline]
+pub(super) fn no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
+ pass_usize(!0_usize)
+}
+
+#[inline]
+pub(super) fn slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<Num> {
+ let mut_ptr = v.as_ptr() as *mut T;
+ raw_arg(mut_ptr.cast())
+}
+
+#[inline]
+pub(super) fn slice<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
+ v: &[T],
+) -> (ArgReg<Num0>, ArgReg<Num1>) {
+ (slice_just_addr(v), pass_usize(v.len()))
+}
+
+#[inline]
+pub(super) fn slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
+ v: &mut [T],
+) -> (ArgReg<Num0>, ArgReg<Num1>) {
+ (raw_arg(v.as_mut_ptr().cast()), pass_usize(v.len()))
+}
+
+#[inline]
+pub(super) fn by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<Num> {
+ let mut_ptr = as_ptr(t) as *mut T;
+ raw_arg(mut_ptr.cast())
+}
+
+#[inline]
+pub(super) fn by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<Num> {
+ raw_arg(as_mut_ptr(t).cast())
+}
+
+/// Convert an optional mutable reference into a `usize` for passing to a
+/// syscall.
+#[inline]
+pub(super) fn opt_mut<T: Sized, Num: ArgNumber>(t: Option<&mut T>) -> ArgReg<Num> {
+ // This optimizes into the equivalent of `transmute(t)`, and has the
+ // advantage of not requiring `unsafe`.
+ match t {
+ Some(t) => by_mut(t),
+ None => raw_arg(null_mut()),
+ }
+}
+
+/// Convert an optional immutable reference into a `usize` for passing to a
+/// syscall.
+#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
+#[inline]
+pub(super) fn opt_ref<'a, T: Sized, Num: ArgNumber>(t: Option<&'a T>) -> ArgReg<'a, Num> {
+ // This optimizes into the equivalent of `transmute(t)`, and has the
+ // advantage of not requiring `unsafe`.
+ match t {
+ Some(t) => by_ref(t),
+ None => raw_arg(null_mut()),
+ }
+}
+
+/// Convert a `c_int` into an `ArgReg`.
+///
+/// Be sure to use `raw_fd` to pass `RawFd` values.
+#[inline]
+pub(super) fn c_int<'a, Num: ArgNumber>(i: c::c_int) -> ArgReg<'a, Num> {
+ pass_usize(i as usize)
+}
+
+/// Convert a `c_uint` into an `ArgReg`.
+#[inline]
+pub(super) fn c_uint<'a, Num: ArgNumber>(i: c::c_uint) -> ArgReg<'a, Num> {
+ pass_usize(i as usize)
+}
+
+#[cfg(target_pointer_width = "64")]
+#[inline]
+pub(super) fn loff_t<'a, Num: ArgNumber>(i: __kernel_loff_t) -> ArgReg<'a, Num> {
+ pass_usize(i as usize)
+}
+
+#[cfg(target_pointer_width = "64")]
+#[inline]
+pub(super) fn loff_t_from_u64<'a, Num: ArgNumber>(i: u64) -> ArgReg<'a, Num> {
+ // `loff_t` is signed, but syscalls which expect `loff_t` return `EINVAL`
+ // if it's outside the signed `i64` range, so we can silently cast.
+ pass_usize(i as usize)
+}
+
+#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
+impl<'a, Num: ArgNumber> From<ClockId> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(i: ClockId) -> Self {
+ pass_usize(i as __kernel_clockid_t as usize)
+ }
+}
+
+#[cfg(feature = "time")]
+impl<'a, Num: ArgNumber> From<TimerfdClockId> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(i: TimerfdClockId) -> Self {
+ pass_usize(i as __kernel_clockid_t as usize)
+ }
+}
+
+#[cfg(feature = "net")]
+#[inline]
+pub(super) fn socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num> {
+ pass_usize(i as usize)
+}
+
+impl<'a, Num: ArgNumber> From<Mode> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(mode: Mode) -> Self {
+ pass_usize(mode.bits() as usize)
+ }
+}
+
+impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(pair: (Mode, FileType)) -> Self {
+ pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize)
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::AtFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::AtFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::MemfdFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::MemfdFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::RenameFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::RenameFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::StatxFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::StatxFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::FdFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::FdFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::io::PipeFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::io::PipeFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::io::DupFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::io::DupFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::io::ReadWriteFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::io::ReadWriteFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::io::EventfdFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::io::EventfdFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::io::epoll::CreateFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::io::epoll::CreateFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+impl<'a, Num: ArgNumber> From<crate::imp::mm::types::ProtFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::imp::mm::types::ProtFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+impl<'a, Num: ArgNumber> From<crate::imp::mm::types::MsyncFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::imp::mm::types::MsyncFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+impl<'a, Num: ArgNumber> From<crate::imp::mm::types::MremapFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::imp::mm::types::MremapFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+impl<'a, Num: ArgNumber> From<crate::imp::mm::types::MlockFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::imp::mm::types::MlockFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+impl<'a, Num: ArgNumber> From<crate::imp::mm::types::MapFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::imp::mm::types::MapFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+impl<'a, Num: ArgNumber> From<crate::imp::mm::types::MprotectFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::imp::mm::types::MprotectFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+impl<'a, Num: ArgNumber> From<crate::imp::mm::types::UserfaultfdFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::imp::mm::types::UserfaultfdFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::imp::process::types::MembarrierCommand> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(cmd: crate::imp::process::types::MembarrierCommand) -> Self {
+ c_uint(cmd as u32)
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::process::Cpuid> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(cpuid: crate::process::Cpuid) -> Self {
+ c_uint(cpuid.as_raw())
+ }
+}
+
+#[cfg(target_pointer_width = "64")]
+#[inline]
+pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> ArgReg<'a, Num> {
+ pass_usize(dev as usize)
+}
+
+#[cfg(target_pointer_width = "32")]
+#[inline]
+pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> io::Result<ArgReg<'a, Num>> {
+ use core::convert::TryInto;
+ Ok(pass_usize(dev.try_into().map_err(|_err| io::Errno::INVAL)?))
+}
+
+#[cfg(target_pointer_width = "32")]
+#[inline]
+fn oflags_bits(oflags: OFlags) -> c::c_uint {
+ let mut bits = oflags.bits();
+ // Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL`
+ // when both are set.
+ if !oflags.contains(OFlags::PATH) {
+ bits |= O_LARGEFILE;
+ }
+ bits
+}
+
+#[cfg(target_pointer_width = "64")]
+#[inline]
+const fn oflags_bits(oflags: OFlags) -> c::c_uint {
+ oflags.bits()
+}
+
+impl<'a, Num: ArgNumber> From<OFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(oflags: OFlags) -> Self {
+ pass_usize(oflags_bits(oflags) as usize)
+ }
+}
+
+/// Convert an `OFlags` into a `u64` for use in the `open_how` struct.
+#[inline]
+pub(super) fn oflags_for_open_how(oflags: OFlags) -> u64 {
+ u64::from(oflags_bits(oflags))
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::FallocateFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::FallocateFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+/// Convert a `Resource` into a syscall argument.
+impl<'a, Num: ArgNumber> From<Resource> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(resource: Resource) -> Self {
+ c_uint(resource as c::c_uint)
+ }
+}
+
+impl<'a, Num: ArgNumber> From<Pid> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(pid: Pid) -> Self {
+ pass_usize(pid.as_raw_nonzero().get() as usize)
+ }
+}
+
+#[inline]
+pub(super) fn negative_pid<'a, Num: ArgNumber>(pid: Pid) -> ArgReg<'a, Num> {
+ pass_usize(pid.as_raw_nonzero().get().wrapping_neg() as usize)
+}
+
+impl<'a, Num: ArgNumber> From<Signal> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(sig: Signal) -> Self {
+ pass_usize(sig as usize)
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::Advice> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(advice: crate::fs::Advice) -> Self {
+ c_uint(advice as c::c_uint)
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::SealFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::SealFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "io_uring")]
+impl<'a, Num: ArgNumber> From<crate::io_uring::IoringEnterFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::io_uring::IoringEnterFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "time")]
+impl<'a, Num: ArgNumber> From<crate::time::TimerfdFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::time::TimerfdFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "time")]
+impl<'a, Num: ArgNumber> From<crate::time::TimerfdTimerFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::time::TimerfdTimerFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "rand")]
+impl<'a, Num: ArgNumber> From<crate::rand::GetRandomFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::rand::GetRandomFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "net")]
+impl<'a, Num: ArgNumber> From<crate::net::RecvFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::net::RecvFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "net")]
+impl<'a, Num: ArgNumber> From<crate::net::SendFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::net::SendFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "net")]
+impl<'a, Num: ArgNumber> From<crate::net::AcceptFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::net::AcceptFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "net")]
+impl<'a, Num: ArgNumber> From<crate::net::AddressFamily> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(family: crate::net::AddressFamily) -> Self {
+ c_uint(family.0.into())
+ }
+}
+
+#[cfg(feature = "net")]
+impl<'a, Num: ArgNumber> From<(crate::net::SocketType, crate::net::SocketFlags)>
+ for ArgReg<'a, Num>
+{
+ #[inline]
+ fn from(pair: (crate::net::SocketType, crate::net::SocketFlags)) -> Self {
+ c_uint(pair.0 .0 | pair.1.bits())
+ }
+}
+
+#[cfg(feature = "thread")]
+impl<'a, Num: ArgNumber> From<(crate::thread::FutexOperation, crate::thread::FutexFlags)>
+ for ArgReg<'a, Num>
+{
+ #[inline]
+ fn from(pair: (crate::thread::FutexOperation, crate::thread::FutexFlags)) -> Self {
+ c_uint(pair.0 as u32 | pair.1.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::fs::Access> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(access: crate::fs::Access) -> Self {
+ c_uint(access.bits())
+ }
+}
+
+#[cfg(feature = "net")]
+impl<'a, Num: ArgNumber> From<crate::net::SocketType> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(type_: crate::net::SocketType) -> Self {
+ c_uint(type_.0)
+ }
+}
+
+#[cfg(feature = "net")]
+impl<'a, Num: ArgNumber> From<crate::net::Protocol> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(protocol: crate::net::Protocol) -> Self {
+ c_uint(protocol.0)
+ }
+}
+
+impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(t: &'a mut MaybeUninit<T>) -> Self {
+ raw_arg(t.as_mut_ptr().cast())
+ }
+}
+
+/// Convert a `usize` returned from a syscall that effectively returns `()` on
+/// success.
+///
+/// # Safety
+///
+/// The caller must ensure that this is the return value of a syscall which
+/// just returns 0 on success.
+#[inline]
+pub(super) unsafe fn ret(raw: RetReg<R0>) -> io::Result<()> {
+ try_decode_void(raw)
+}
+
+/// Convert a `usize` returned from a syscall that doesn't return on success.
+///
+/// # Safety
+///
+/// The caller must ensure that this is the return value of a syscall which
+/// doesn't return on success.
+#[cfg(feature = "runtime")]
+#[inline]
+pub(super) unsafe fn ret_error(raw: RetReg<R0>) -> io::Errno {
+ try_decode_error(raw)
+}
+
+/// Convert a `usize` returned from a syscall that effectively always returns
+/// `()`.
+///
+/// # Safety
+///
+/// The caller must ensure that this is the return value of a syscall which
+/// always returns `()`.
+#[inline]
+pub(super) unsafe fn ret_infallible(raw: RetReg<R0>) {
+ #[cfg(debug_assertions)]
+ {
+ try_decode_void(raw).unwrap()
+ }
+ #[cfg(not(debug_assertions))]
+ drop(raw);
+}
+
+/// Convert a `usize` returned from a syscall that effectively returns a
+/// `c_int` on success.
+#[inline]
+pub(super) fn ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int> {
+ try_decode_c_int(raw)
+}
+
+/// Convert a `usize` returned from a syscall that effectively returns a
+/// `c_uint` on success.
+#[inline]
+pub(super) fn ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint> {
+ try_decode_c_uint(raw)
+}
+
+/// Convert a `usize` returned from a syscall that effectively returns a `u64`
+/// on success.
+#[cfg(target_pointer_width = "64")]
+#[inline]
+pub(super) fn ret_u64(raw: RetReg<R0>) -> io::Result<u64> {
+ try_decode_u64(raw)
+}
+
+/// Convert a `usize` returned from a syscall that effectively returns a
+/// `usize` on success.
+#[inline]
+pub(super) fn ret_usize(raw: RetReg<R0>) -> io::Result<usize> {
+ try_decode_usize(raw)
+}
+
+/// Convert a `usize` returned from a syscall that effectively always
+/// returns a `usize`.
+///
+/// # Safety
+///
+/// This function must only be used with return values from infallible
+/// syscalls.
+#[inline]
+pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize {
+ #[cfg(debug_assertions)]
+ {
+ try_decode_usize(raw).unwrap()
+ }
+ #[cfg(not(debug_assertions))]
+ {
+ decode_usize_infallible(raw)
+ }
+}
+
+/// Convert a `usize` returned from a syscall that effectively returns an
+/// `OwnedFd` on success.
+///
+/// # Safety
+///
+/// The caller must ensure that this is the return value of a syscall which
+/// returns an owned file descriptor.
+#[inline]
+pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> {
+ let raw_fd = try_decode_raw_fd(raw)?;
+ Ok(OwnedFd::from(crate::imp::fd::OwnedFd::from_raw_fd(raw_fd)))
+}
+
+/// Convert the return value of `dup2` and `dup3`.
+///
+/// When these functions succeed, they return the same value as their second
+/// argument, so we don't construct a new `OwnedFd`.
+///
+/// # Safety
+///
+/// The caller must ensure that this is the return value of a syscall which
+/// returns a file descriptor.
+#[inline]
+pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> {
+ let _raw_fd = try_decode_raw_fd(raw)?;
+ Ok(())
+}
+
+/// Convert a `usize` returned from a syscall that effectively returns a
+/// `*mut c_void` on success.
+#[inline]
+pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> {
+ try_decode_void_star(raw)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/elf.rs b/vendor/rustix/src/imp/linux_raw/elf.rs
new file mode 100644
index 000000000..7b9bb3245
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/elf.rs
@@ -0,0 +1,172 @@
+//! The ELF ABI.
+
+#![allow(non_snake_case)]
+
+pub(super) const SELFMAG: usize = 4;
+pub(super) const ELFMAG: [u8; SELFMAG] = [0x7f, b'E', b'L', b'F'];
+pub(super) const EI_CLASS: usize = 4;
+pub(super) const EI_DATA: usize = 5;
+pub(super) const EI_VERSION: usize = 6;
+pub(super) const EI_OSABI: usize = 7;
+pub(super) const EI_ABIVERSION: usize = 8;
+pub(super) const EV_CURRENT: u8 = 1;
+#[cfg(target_pointer_width = "32")]
+pub(super) const ELFCLASS: u8 = 1; // ELFCLASS32
+#[cfg(target_pointer_width = "64")]
+pub(super) const ELFCLASS: u8 = 2; // ELFCLASS64
+#[cfg(target_endian = "little")]
+pub(super) const ELFDATA: u8 = 1; // ELFDATA2LSB
+#[cfg(target_endian = "big")]
+pub(super) const ELFDATA: u8 = 2; // ELFDATA2MSB
+pub(super) const ELFOSABI_SYSV: u8 = 0;
+pub(super) const ELFOSABI_LINUX: u8 = 3;
+// At present all of our supported platforms use 0.
+pub(super) const ELFABIVERSION: u8 = 0;
+pub(super) const ET_DYN: u16 = 3;
+pub(super) const EI_NIDENT: usize = 16;
+pub(super) const SHN_UNDEF: u16 = 0;
+pub(super) const SHN_ABS: u16 = 0xfff1;
+pub(super) const PN_XNUM: u16 = 0xffff;
+pub(super) const PT_LOAD: u32 = 1;
+pub(super) const PT_DYNAMIC: u32 = 2;
+pub(super) const PT_INTERP: u32 = 3;
+pub(super) const PT_PHDR: u32 = 6;
+pub(super) const PT_TLS: u32 = 7;
+pub(super) const PT_GNU_STACK: u32 = 0x6474_e551;
+pub(super) const PT_GNU_RELRO: u32 = 0x6474_e552;
+pub(super) const PF_X: u32 = 1;
+pub(super) const PF_W: u32 = 2;
+pub(super) const PF_R: u32 = 4;
+pub(super) const DT_NULL: i32 = 0;
+pub(super) const DT_HASH: i32 = 4;
+pub(super) const DT_STRTAB: i32 = 5;
+pub(super) const DT_SYMTAB: i32 = 6;
+pub(super) const DT_SYMENT: i32 = 11;
+pub(super) const DT_VERSYM: i32 = 0x6fff_fff0;
+pub(super) const DT_VERDEF: i32 = 0x6fff_fffc;
+pub(super) const STB_WEAK: u8 = 2;
+pub(super) const STB_GLOBAL: u8 = 1;
+pub(super) const STT_NOTYPE: u8 = 0;
+pub(super) const STT_FUNC: u8 = 2;
+pub(super) const STN_UNDEF: u32 = 0;
+pub(super) const VER_FLG_BASE: u16 = 0x1;
+pub(super) const VER_DEF_CURRENT: u16 = 1;
+pub(super) const STV_DEFAULT: u8 = 0;
+#[cfg(target_arch = "arm")]
+pub(super) const EM_CURRENT: u16 = 40; // EM_ARM
+#[cfg(target_arch = "x86")]
+pub(super) const EM_CURRENT: u16 = 3; // EM_386
+#[cfg(target_arch = "powerpc64")]
+pub(super) const EM_CURRENT: u16 = 21; // EM_PPC64
+#[cfg(any(target_arch = "mips", target_arch = "mips64"))]
+pub(super) const EM_CURRENT: u16 = 8; // EM_MIPS
+#[cfg(target_arch = "x86_64")]
+pub(super) const EM_CURRENT: u16 = 62; // EM_X86_64
+#[cfg(target_arch = "aarch64")]
+pub(super) const EM_CURRENT: u16 = 183; // EM_AARCH64
+#[cfg(target_arch = "riscv64")]
+pub(super) const EM_CURRENT: u16 = 243; // EM_RISCV
+
+#[inline]
+pub(super) const fn ELF_ST_VISIBILITY(o: u8) -> u8 {
+ o & 0x03
+}
+
+#[inline]
+pub(super) const fn ELF_ST_BIND(val: u8) -> u8 {
+ val >> 4
+}
+
+#[inline]
+pub(super) const fn ELF_ST_TYPE(val: u8) -> u8 {
+ val & 0xf
+}
+
+#[repr(C)]
+pub(super) struct Elf_Ehdr {
+ pub(super) e_ident: [u8; EI_NIDENT],
+ pub(super) e_type: u16,
+ pub(super) e_machine: u16,
+ pub(super) e_version: u32,
+ pub(super) e_entry: usize,
+ pub(super) e_phoff: usize,
+ pub(super) e_shoff: usize,
+ pub(super) e_flags: u32,
+ pub(super) e_ehsize: u16,
+ pub(super) e_phentsize: u16,
+ pub(super) e_phnum: u16,
+ pub(super) e_shentsize: u16,
+ pub(super) e_shnum: u16,
+ pub(super) e_shstrndx: u16,
+}
+
+#[cfg(target_pointer_width = "32")]
+#[repr(C)]
+pub(super) struct Elf_Phdr {
+ pub(super) p_type: u32,
+ pub(super) p_offset: usize,
+ pub(super) p_vaddr: usize,
+ pub(super) p_paddr: usize,
+ pub(super) p_filesz: usize,
+ pub(super) p_memsz: usize,
+ pub(super) p_flags: u32,
+ pub(super) p_align: usize,
+}
+
+#[cfg(target_pointer_width = "64")]
+#[repr(C)]
+pub(super) struct Elf_Phdr {
+ pub(super) p_type: u32,
+ pub(super) p_flags: u32,
+ pub(super) p_offset: usize,
+ pub(super) p_vaddr: usize,
+ pub(super) p_paddr: usize,
+ pub(super) p_filesz: usize,
+ pub(super) p_memsz: usize,
+ pub(super) p_align: usize,
+}
+
+#[cfg(target_pointer_width = "32")]
+#[repr(C)]
+pub(super) struct Elf_Sym {
+ pub(super) st_name: u32,
+ pub(super) st_value: usize,
+ pub(super) st_size: usize,
+ pub(super) st_info: u8,
+ pub(super) st_other: u8,
+ pub(super) st_shndx: u16,
+}
+
+#[cfg(target_pointer_width = "64")]
+#[repr(C)]
+pub(super) struct Elf_Sym {
+ pub(super) st_name: u32,
+ pub(super) st_info: u8,
+ pub(super) st_other: u8,
+ pub(super) st_shndx: u16,
+ pub(super) st_value: usize,
+ pub(super) st_size: usize,
+}
+
+#[repr(C)]
+pub(super) struct Elf_Dyn {
+ pub(super) d_tag: i32,
+ pub(super) d_val: usize,
+}
+
+#[repr(C)]
+pub(super) struct Elf_Verdef {
+ pub(super) vd_version: u16,
+ pub(super) vd_flags: u16,
+ pub(super) vd_ndx: u16,
+ pub(super) vd_cnt: u16,
+ pub(super) vd_hash: u32,
+ pub(super) vd_aux: u32,
+ pub(super) vd_next: u32,
+}
+
+#[repr(C)]
+pub(super) struct Elf_Verdaux {
+ pub(super) vda_name: u32,
+ pub(super) _vda_next: u32,
+}
diff --git a/vendor/rustix/src/imp/linux_raw/fs/dir.rs b/vendor/rustix/src/imp/linux_raw/fs/dir.rs
new file mode 100644
index 000000000..64f5aa652
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/fs/dir.rs
@@ -0,0 +1,213 @@
+use crate::fd::{AsFd, BorrowedFd};
+use crate::ffi::{CStr, CString};
+use crate::fs::{fcntl_getfl, fstat, fstatfs, openat, FileType, Mode, OFlags, Stat, StatFs};
+use crate::io::{self, OwnedFd};
+use crate::process::fchdir;
+use crate::utils::as_ptr;
+use alloc::borrow::ToOwned;
+use alloc::vec::Vec;
+use core::fmt;
+use core::mem::size_of;
+use linux_raw_sys::general::{linux_dirent64, SEEK_SET};
+
+/// `DIR*`
+pub struct Dir {
+ /// The `OwnedFd` that we read directory entries from.
+ fd: OwnedFd,
+
+ buf: Vec<u8>,
+ pos: usize,
+ next: Option<u64>,
+}
+
+impl Dir {
+ /// Construct a `Dir` that reads entries from the given directory
+ /// file descriptor.
+ #[inline]
+ pub fn read_from<Fd: AsFd>(fd: Fd) -> io::Result<Self> {
+ Self::_read_from(fd.as_fd())
+ }
+
+ #[inline]
+ fn _read_from(fd: BorrowedFd<'_>) -> io::Result<Self> {
+ let flags = fcntl_getfl(fd)?;
+ let fd_for_dir = openat(fd, cstr!("."), flags | OFlags::CLOEXEC, Mode::empty())?;
+
+ Ok(Self {
+ fd: fd_for_dir,
+ buf: Vec::new(),
+ pos: 0,
+ next: None,
+ })
+ }
+
+ /// `rewinddir(self)`
+ #[inline]
+ pub fn rewind(&mut self) {
+ self.pos = self.buf.len();
+ self.next = Some(0);
+ }
+
+ /// `readdir(self)`, where `None` means the end of the directory.
+ pub fn read(&mut self) -> Option<io::Result<DirEntry>> {
+ if let Some(next) = self.next.take() {
+ match crate::imp::fs::syscalls::_seek(self.fd.as_fd(), next as i64, SEEK_SET) {
+ Ok(_) => (),
+ Err(err) => return Some(Err(err)),
+ }
+ }
+
+ // Compute linux_dirent64 field offsets.
+ let z = linux_dirent64 {
+ d_ino: 0_u64,
+ d_off: 0_i64,
+ d_type: 0_u8,
+ d_reclen: 0_u16,
+ d_name: Default::default(),
+ };
+ let base = as_ptr(&z) as usize;
+ let offsetof_d_reclen = (as_ptr(&z.d_reclen) as usize) - base;
+ let offsetof_d_name = (as_ptr(&z.d_name) as usize) - base;
+ let offsetof_d_ino = (as_ptr(&z.d_ino) as usize) - base;
+ let offsetof_d_type = (as_ptr(&z.d_type) as usize) - base;
+
+ // Test if we need more entries, and if so, read more.
+ if self.buf.len() - self.pos < size_of::<linux_dirent64>() {
+ match self.read_more()? {
+ Ok(()) => (),
+ Err(e) => return Some(Err(e)),
+ }
+ }
+
+ // We successfully read an entry. Extract the fields.
+ let pos = self.pos;
+
+ // Do an unaligned u16 load.
+ let d_reclen = u16::from_ne_bytes([
+ self.buf[pos + offsetof_d_reclen],
+ self.buf[pos + offsetof_d_reclen + 1],
+ ]);
+ assert!(self.buf.len() - pos >= d_reclen as usize);
+ self.pos += d_reclen as usize;
+
+ // Read the NUL-terminated name from the `d_name` field. Without
+ // `unsafe`, we need to scan for the NUL twice: once to obtain a size
+ // for the slice, and then once within `CStr::from_bytes_with_nul`.
+ let name_start = pos + offsetof_d_name;
+ let name_len = self.buf[name_start..]
+ .iter()
+ .position(|x| *x == b'\0')
+ .unwrap();
+ let name =
+ CStr::from_bytes_with_nul(&self.buf[name_start..name_start + name_len + 1]).unwrap();
+ let name = name.to_owned();
+ assert!(name.as_bytes().len() <= self.buf.len() - name_start);
+
+ // Do an unaligned u64 load.
+ let d_ino = u64::from_ne_bytes([
+ self.buf[pos + offsetof_d_ino],
+ self.buf[pos + offsetof_d_ino + 1],
+ self.buf[pos + offsetof_d_ino + 2],
+ self.buf[pos + offsetof_d_ino + 3],
+ self.buf[pos + offsetof_d_ino + 4],
+ self.buf[pos + offsetof_d_ino + 5],
+ self.buf[pos + offsetof_d_ino + 6],
+ self.buf[pos + offsetof_d_ino + 7],
+ ]);
+
+ let d_type = self.buf[pos + offsetof_d_type];
+
+ // Check that our types correspond to the `linux_dirent64` types.
+ let _ = linux_dirent64 {
+ d_ino,
+ d_off: 0,
+ d_type,
+ d_reclen,
+ d_name: Default::default(),
+ };
+
+ Some(Ok(DirEntry {
+ d_ino,
+ d_type,
+ name,
+ }))
+ }
+
+ fn read_more(&mut self) -> Option<io::Result<()>> {
+ // Capacity increment currently chosen by wild guess.
+ self.buf
+ .resize(self.buf.capacity() + 32 * size_of::<linux_dirent64>(), 0);
+ self.pos = 0;
+ let nread = match crate::imp::fs::syscalls::getdents(self.fd.as_fd(), &mut self.buf) {
+ Ok(nread) => nread,
+ Err(err) => return Some(Err(err)),
+ };
+ self.buf.resize(nread, 0);
+ if nread == 0 {
+ None
+ } else {
+ Some(Ok(()))
+ }
+ }
+
+ /// `fstat(self)`
+ #[inline]
+ pub fn stat(&self) -> io::Result<Stat> {
+ fstat(&self.fd)
+ }
+
+ /// `fstatfs(self)`
+ #[inline]
+ pub fn statfs(&self) -> io::Result<StatFs> {
+ fstatfs(&self.fd)
+ }
+
+ /// `fchdir(self)`
+ #[inline]
+ pub fn chdir(&self) -> io::Result<()> {
+ fchdir(&self.fd)
+ }
+}
+
+impl Iterator for Dir {
+ type Item = io::Result<DirEntry>;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ Self::read(self)
+ }
+}
+
+impl fmt::Debug for Dir {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Dir").field("fd", &self.fd).finish()
+ }
+}
+
+/// `struct dirent`
+#[derive(Debug)]
+pub struct DirEntry {
+ d_ino: u64,
+ d_type: u8,
+ name: CString,
+}
+
+impl DirEntry {
+ /// Returns the file name of this directory entry.
+ #[inline]
+ pub fn file_name(&self) -> &CStr {
+ &self.name
+ }
+
+ /// Returns the type of this directory entry.
+ #[inline]
+ pub fn file_type(&self) -> FileType {
+ FileType::from_dirent_d_type(self.d_type)
+ }
+
+ /// Return the inode number of this directory entry.
+ #[inline]
+ pub fn ino(&self) -> u64 {
+ self.d_ino
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/fs/makedev.rs b/vendor/rustix/src/imp/linux_raw/fs/makedev.rs
new file mode 100644
index 000000000..284ba2f10
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/fs/makedev.rs
@@ -0,0 +1,19 @@
+use crate::fs::Dev;
+
+#[inline]
+pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
+ ((u64::from(maj) & 0xffff_f000_u64) << 32)
+ | ((u64::from(maj) & 0x0000_0fff_u64) << 8)
+ | ((u64::from(min) & 0xffff_ff00_u64) << 12)
+ | (u64::from(min) & 0x0000_00ff_u64)
+}
+
+#[inline]
+pub(crate) fn major(dev: Dev) -> u32 {
+ (((dev >> 31 >> 1) & 0xffff_f000) | ((dev >> 8) & 0x0000_0fff)) as u32
+}
+
+#[inline]
+pub(crate) fn minor(dev: Dev) -> u32 {
+ (((dev >> 12) & 0xffff_ff00) | (dev & 0x0000_00ff)) as u32
+}
diff --git a/vendor/rustix/src/imp/linux_raw/fs/mod.rs b/vendor/rustix/src/imp/linux_raw/fs/mod.rs
new file mode 100644
index 000000000..641e65744
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/fs/mod.rs
@@ -0,0 +1,5 @@
+#[cfg(any(feature = "fs", feature = "procfs"))]
+pub(crate) mod dir;
+pub(crate) mod makedev;
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/linux_raw/fs/syscalls.rs b/vendor/rustix/src/imp/linux_raw/fs/syscalls.rs
new file mode 100644
index 000000000..db1ecaaf6
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/fs/syscalls.rs
@@ -0,0 +1,1391 @@
+//! linux_raw syscalls supporting `rustix::fs`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(dead_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::c;
+use super::super::conv::{
+ by_ref, c_int, c_uint, dev_t, oflags_for_open_how, opt_mut, pass_usize, raw_fd, ret, ret_c_int,
+ ret_c_uint, ret_owned_fd, ret_usize, size_of, slice_mut, zero,
+};
+#[cfg(target_pointer_width = "64")]
+use super::super::conv::{loff_t, loff_t_from_u64, ret_u64};
+#[cfg(any(
+ target_arch = "aarch64",
+ target_arch = "riscv64",
+ target_arch = "mips64",
+ target_pointer_width = "32",
+))]
+use crate::fd::AsFd;
+use crate::fd::{BorrowedFd, RawFd};
+use crate::ffi::CStr;
+use crate::fs::{
+ Access, Advice, AtFlags, FallocateFlags, FdFlags, FileType, FlockOperation, MemfdFlags, Mode,
+ OFlags, RenameFlags, ResolveFlags, SealFlags, Stat, StatFs, StatxFlags, Timestamps,
+};
+use crate::io::{self, OwnedFd, SeekFrom};
+use crate::process::{Gid, Uid};
+use core::convert::TryInto;
+use core::mem::MaybeUninit;
+#[cfg(target_arch = "mips64")]
+use linux_raw_sys::general::stat as linux_stat64;
+use linux_raw_sys::general::{
+ __kernel_timespec, open_how, statx, AT_EACCESS, AT_FDCWD, AT_REMOVEDIR, AT_SYMLINK_NOFOLLOW,
+ F_ADD_SEALS, F_DUPFD, F_DUPFD_CLOEXEC, F_GETFD, F_GETFL, F_GETLEASE, F_GETOWN, F_GETPIPE_SZ,
+ F_GETSIG, F_GET_SEALS, F_SETFD, F_SETFL, F_SETPIPE_SZ, SEEK_CUR, SEEK_END, SEEK_SET,
+};
+#[cfg(target_pointer_width = "32")]
+use {
+ super::super::conv::{hi, lo, slice_just_addr},
+ linux_raw_sys::general::stat64 as linux_stat64,
+ linux_raw_sys::general::timespec as __kernel_old_timespec,
+};
+
+#[inline]
+pub(crate) fn open(filename: &CStr, flags: OFlags, mode: Mode) -> io::Result<OwnedFd> {
+ #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
+ {
+ openat(crate::fs::cwd().as_fd(), filename, flags, mode)
+ }
+ #[cfg(all(
+ target_pointer_width = "32",
+ not(any(target_arch = "aarch64", target_arch = "riscv64")),
+ ))]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(__NR_open, filename, flags, mode))
+ }
+ #[cfg(all(
+ target_pointer_width = "64",
+ not(any(target_arch = "aarch64", target_arch = "riscv64")),
+ ))]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(__NR_open, filename, flags, mode))
+ }
+}
+
+#[inline]
+pub(crate) fn openat(
+ dirfd: BorrowedFd<'_>,
+ filename: &CStr,
+ flags: OFlags,
+ mode: Mode,
+) -> io::Result<OwnedFd> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(__NR_openat, dirfd, filename, flags, mode))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(__NR_openat, dirfd, filename, flags, mode))
+ }
+}
+
+#[inline]
+pub(crate) fn openat2(
+ dirfd: BorrowedFd<'_>,
+ pathname: &CStr,
+ flags: OFlags,
+ mode: Mode,
+ resolve: ResolveFlags,
+) -> io::Result<OwnedFd> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_openat2,
+ dirfd,
+ pathname,
+ by_ref(&open_how {
+ flags: oflags_for_open_how(flags),
+ mode: u64::from(mode.bits()),
+ resolve: resolve.bits(),
+ }),
+ size_of::<open_how, _>()
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_openat2,
+ dirfd,
+ pathname,
+ by_ref(&open_how {
+ flags: oflags_for_open_how(flags),
+ mode: u64::from(mode.bits()),
+ resolve: resolve.bits(),
+ }),
+ size_of::<open_how, _>()
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn chmod(filename: &CStr, mode: Mode) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fchmodat,
+ raw_fd(AT_FDCWD),
+ filename,
+ mode
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn chmodat(dirfd: BorrowedFd<'_>, filename: &CStr, mode: Mode) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_fchmodat, dirfd, filename, mode)) }
+}
+
+#[inline]
+pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_fchmod, fd, mode)) }
+}
+
+#[inline]
+pub(crate) fn chownat(
+ dirfd: BorrowedFd<'_>,
+ filename: &CStr,
+ owner: Option<Uid>,
+ group: Option<Gid>,
+ flags: AtFlags,
+) -> io::Result<()> {
+ unsafe {
+ let (ow, gr) = crate::process::translate_fchown_args(owner, group);
+ ret(syscall_readonly!(
+ __NR_fchownat,
+ dirfd,
+ filename,
+ c_uint(ow),
+ c_uint(gr),
+ flags
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
+ unsafe {
+ let (ow, gr) = crate::process::translate_fchown_args(owner, group);
+ ret(syscall_readonly!(__NR_fchown, fd, c_uint(ow), c_uint(gr)))
+ }
+}
+
+#[inline]
+pub(crate) fn mknodat(
+ dirfd: BorrowedFd<'_>,
+ filename: &CStr,
+ file_type: FileType,
+ mode: Mode,
+ dev: u64,
+) -> io::Result<()> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_mknodat,
+ dirfd,
+ filename,
+ (mode, file_type),
+ dev_t(dev)?
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_mknodat,
+ dirfd,
+ filename,
+ (mode, file_type),
+ dev_t(dev)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result<u64> {
+ let (whence, offset) = match pos {
+ SeekFrom::Start(pos) => {
+ let pos: u64 = pos;
+ // Silently cast; we'll get `EINVAL` if the value is negative.
+ (SEEK_SET, pos as i64)
+ }
+ SeekFrom::End(offset) => (SEEK_END, offset),
+ SeekFrom::Current(offset) => (SEEK_CUR, offset),
+ };
+ _seek(fd, offset, whence)
+}
+
+#[inline]
+pub(crate) fn _seek(fd: BorrowedFd<'_>, offset: i64, whence: c::c_uint) -> io::Result<u64> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ let mut result = MaybeUninit::<u64>::uninit();
+ ret(syscall!(
+ __NR__llseek,
+ fd,
+ // Don't use the hi/lo functions here because Linux's llseek
+ // takes its 64-bit argument differently from everything else.
+ pass_usize((offset >> 32) as usize),
+ pass_usize(offset as usize),
+ &mut result,
+ c_uint(whence)
+ ))
+ .map(|()| result.assume_init())
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_u64(syscall_readonly!(
+ __NR_lseek,
+ fd,
+ loff_t(offset),
+ c_uint(whence)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn tell(fd: BorrowedFd<'_>) -> io::Result<u64> {
+ _seek(fd, 0, SEEK_CUR).map(|x| x as u64)
+}
+
+#[inline]
+pub(crate) fn ftruncate(fd: BorrowedFd<'_>, length: u64) -> io::Result<()> {
+ // <https://github.com/torvalds/linux/blob/fcadab740480e0e0e9fa9bd272acd409884d431a/arch/arm64/kernel/sys32.c#L81-L83>
+ #[cfg(all(
+ target_pointer_width = "32",
+ any(target_arch = "arm", target_arch = "mips", target_arch = "powerpc"),
+ ))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_ftruncate64,
+ fd,
+ zero(),
+ hi(length),
+ lo(length)
+ ))
+ }
+ #[cfg(all(
+ target_pointer_width = "32",
+ not(any(target_arch = "arm", target_arch = "mips", target_arch = "powerpc")),
+ ))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_ftruncate64,
+ fd,
+ hi(length),
+ lo(length)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_ftruncate,
+ fd,
+ loff_t_from_u64(length)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn fallocate(
+ fd: BorrowedFd<'_>,
+ mode: FallocateFlags,
+ offset: u64,
+ len: u64,
+) -> io::Result<()> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fallocate,
+ fd,
+ mode,
+ hi(offset),
+ lo(offset),
+ hi(len),
+ lo(len)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fallocate,
+ fd,
+ mode,
+ loff_t_from_u64(offset),
+ loff_t_from_u64(len)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn fadvise(fd: BorrowedFd<'_>, pos: u64, len: u64, advice: Advice) -> io::Result<()> {
+ // On ARM, the arguments are reordered so that the len and pos argument
+ // pairs are aligned. And ARM has a custom syscall code for this.
+ #[cfg(target_arch = "arm")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_arm_fadvise64_64,
+ fd,
+ advice,
+ hi(pos),
+ lo(pos),
+ hi(len),
+ lo(len)
+ ))
+ }
+
+ // On powerpc, the arguments are reordered as on ARM.
+ #[cfg(target_arch = "powerpc")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fadvise64_64,
+ fd,
+ advice,
+ hi(pos),
+ lo(pos),
+ hi(len),
+ lo(len)
+ ))
+ }
+ // On mips, the arguments are not reordered, and padding is inserted
+ // instead to ensure alignment.
+ #[cfg(target_arch = "mips")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fadvise64,
+ fd,
+ zero(),
+ hi(pos),
+ lo(pos),
+ hi(len),
+ lo(len),
+ advice
+ ))
+ }
+ #[cfg(all(
+ target_pointer_width = "32",
+ not(any(target_arch = "arm", target_arch = "mips", target_arch = "powerpc")),
+ ))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fadvise64_64,
+ fd,
+ hi(pos),
+ lo(pos),
+ hi(len),
+ lo(len),
+ advice
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fadvise64,
+ fd,
+ loff_t_from_u64(pos),
+ loff_t_from_u64(len),
+ advice
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn fsync(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_fsync, fd)) }
+}
+
+#[inline]
+pub(crate) fn fdatasync(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_fdatasync, fd)) }
+}
+
+#[inline]
+pub(crate) fn flock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::Result<()> {
+ unsafe { ret(syscall!(__NR_flock, fd, c_uint(operation as c::c_uint))) }
+}
+
+#[inline]
+pub(crate) fn fstat(fd: BorrowedFd<'_>) -> io::Result<Stat> {
+ #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+ {
+ match statx(fd, cstr!(""), AtFlags::EMPTY_PATH, StatxFlags::BASIC_STATS) {
+ Ok(x) => statx_to_stat(x),
+ Err(io::Errno::NOSYS) => fstat_old(fd),
+ Err(e) => Err(e),
+ }
+ }
+
+ #[cfg(all(target_pointer_width = "64", not(target_arch = "mips64")))]
+ unsafe {
+ let mut result = MaybeUninit::<Stat>::uninit();
+ ret(syscall!(__NR_fstat, fd, &mut result)).map(|()| result.assume_init())
+ }
+}
+
+#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+fn fstat_old(fd: BorrowedFd<'_>) -> io::Result<Stat> {
+ let mut result = MaybeUninit::<linux_stat64>::uninit();
+
+ #[cfg(target_arch = "mips64")]
+ unsafe {
+ ret(syscall!(__NR_fstat, fd, &mut result))?;
+ stat_to_stat(result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall!(__NR_fstat64, fd, &mut result))?;
+ stat_to_stat(result.assume_init())
+ }
+}
+
+#[inline]
+pub(crate) fn stat(filename: &CStr) -> io::Result<Stat> {
+ #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+ {
+ match statx(
+ crate::fs::cwd().as_fd(),
+ filename,
+ AtFlags::empty(),
+ StatxFlags::BASIC_STATS,
+ ) {
+ Ok(x) => return statx_to_stat(x),
+ Err(io::Errno::NOSYS) => stat_old(filename),
+ Err(e) => return Err(e),
+ }
+ }
+
+ #[cfg(all(target_pointer_width = "64", not(target_arch = "mips64")))]
+ unsafe {
+ let mut result = MaybeUninit::<Stat>::uninit();
+ ret(syscall!(
+ __NR_newfstatat,
+ raw_fd(AT_FDCWD),
+ filename,
+ &mut result,
+ c_uint(0)
+ ))
+ .map(|()| result.assume_init())
+ }
+}
+
+#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+fn stat_old(filename: &CStr) -> io::Result<Stat> {
+ let mut result = MaybeUninit::<linux_stat64>::uninit();
+
+ #[cfg(target_arch = "mips64")]
+ unsafe {
+ ret(syscall!(
+ __NR_newfstatat,
+ raw_fd(AT_FDCWD),
+ filename,
+ &mut result,
+ c_uint(0)
+ ))?;
+ stat_to_stat(result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall!(
+ __NR_fstatat64,
+ raw_fd(AT_FDCWD),
+ filename,
+ &mut result,
+ c_uint(0)
+ ))?;
+ stat_to_stat(result.assume_init())
+ }
+}
+
+#[inline]
+pub(crate) fn statat(dirfd: BorrowedFd<'_>, filename: &CStr, flags: AtFlags) -> io::Result<Stat> {
+ #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+ {
+ match statx(dirfd, filename, flags, StatxFlags::BASIC_STATS) {
+ Ok(x) => return statx_to_stat(x),
+ Err(io::Errno::NOSYS) => statat_old(dirfd, filename, flags),
+ Err(e) => return Err(e),
+ }
+ }
+
+ #[cfg(all(target_pointer_width = "64", not(target_arch = "mips64")))]
+ unsafe {
+ let mut result = MaybeUninit::<Stat>::uninit();
+ ret(syscall!(
+ __NR_newfstatat,
+ dirfd,
+ filename,
+ &mut result,
+ flags
+ ))
+ .map(|()| result.assume_init())
+ }
+}
+
+#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+fn statat_old(dirfd: BorrowedFd<'_>, filename: &CStr, flags: AtFlags) -> io::Result<Stat> {
+ let mut result = MaybeUninit::<linux_stat64>::uninit();
+
+ #[cfg(target_arch = "mips64")]
+ unsafe {
+ ret(syscall!(
+ __NR_newfstatat,
+ dirfd,
+ filename,
+ &mut result,
+ flags
+ ))?;
+ stat_to_stat(result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall!(
+ __NR_fstatat64,
+ dirfd,
+ filename,
+ &mut result,
+ flags
+ ))?;
+ stat_to_stat(result.assume_init())
+ }
+}
+
+#[inline]
+pub(crate) fn lstat(filename: &CStr) -> io::Result<Stat> {
+ #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+ {
+ match statx(
+ crate::fs::cwd().as_fd(),
+ filename,
+ AtFlags::SYMLINK_NOFOLLOW,
+ StatxFlags::BASIC_STATS,
+ ) {
+ Ok(x) => return statx_to_stat(x),
+ Err(io::Errno::NOSYS) => lstat_old(filename),
+ Err(e) => return Err(e),
+ }
+ }
+
+ #[cfg(all(target_pointer_width = "64", not(target_arch = "mips64")))]
+ unsafe {
+ let mut result = MaybeUninit::<Stat>::uninit();
+ ret(syscall!(
+ __NR_newfstatat,
+ raw_fd(AT_FDCWD),
+ filename,
+ &mut result,
+ c_uint(AT_SYMLINK_NOFOLLOW)
+ ))
+ .map(|()| result.assume_init())
+ }
+}
+
+#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+fn lstat_old(filename: &CStr) -> io::Result<Stat> {
+ let mut result = MaybeUninit::<linux_stat64>::uninit();
+
+ #[cfg(target_arch = "mips64")]
+ unsafe {
+ ret(syscall!(
+ __NR_newfstatat,
+ raw_fd(AT_FDCWD),
+ filename,
+ &mut result,
+ c_uint(AT_SYMLINK_NOFOLLOW)
+ ))?;
+ stat_to_stat(result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall!(
+ __NR_fstatat64,
+ raw_fd(AT_FDCWD),
+ filename,
+ &mut result,
+ c_uint(AT_SYMLINK_NOFOLLOW)
+ ))?;
+ stat_to_stat(result.assume_init())
+ }
+}
+
+/// Convert from a Linux `statx` value to rustix's `Stat`.
+#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
+ Ok(Stat {
+ st_dev: crate::fs::makedev(x.stx_dev_major, x.stx_dev_minor),
+ st_mode: x.stx_mode.into(),
+ st_nlink: x.stx_nlink.into(),
+ st_uid: x.stx_uid.into(),
+ st_gid: x.stx_gid.into(),
+ st_rdev: crate::fs::makedev(x.stx_rdev_major, x.stx_rdev_minor),
+ st_size: x.stx_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_blksize: x.stx_blksize.into(),
+ st_blocks: x.stx_blocks.into(),
+ st_atime: x
+ .stx_atime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_atime_nsec: x.stx_atime.tv_nsec.into(),
+ st_mtime: x
+ .stx_mtime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_mtime_nsec: x.stx_mtime.tv_nsec.into(),
+ st_ctime: x
+ .stx_ctime
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_ctime_nsec: x.stx_ctime.tv_nsec.into(),
+ st_ino: x.stx_ino.into(),
+ })
+}
+
+/// Convert from a Linux `stat64` value to rustix's `Stat`.
+#[cfg(target_pointer_width = "32")]
+fn stat_to_stat(s64: linux_raw_sys::general::stat64) -> io::Result<Stat> {
+ Ok(Stat {
+ st_dev: s64.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_mode: s64.st_mode.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_nlink: s64.st_nlink.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_uid: s64.st_uid.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_gid: s64.st_gid.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_rdev: s64.st_rdev.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_size: s64.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_blksize: s64.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_blocks: s64.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_atime: s64.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_atime_nsec: s64
+ .st_atime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_mtime: s64.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_mtime_nsec: s64
+ .st_mtime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_ctime: s64.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_ctime_nsec: s64
+ .st_ctime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_ino: s64.st_ino.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ })
+}
+
+/// Convert from a Linux `stat` value to rustix's `Stat`.
+#[cfg(target_arch = "mips64")]
+fn stat_to_stat(s: linux_raw_sys::general::stat) -> io::Result<Stat> {
+ Ok(Stat {
+ st_dev: s.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_mode: s.st_mode.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_nlink: s.st_nlink.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_uid: s.st_uid.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_gid: s.st_gid.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_rdev: s.st_rdev.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_size: s.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_blksize: s.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_blocks: s.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_atime: s.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_atime_nsec: s
+ .st_atime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_mtime: s.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_mtime_nsec: s
+ .st_mtime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_ctime: s.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ st_ctime_nsec: s
+ .st_ctime_nsec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ st_ino: s.st_ino.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+ })
+}
+
+#[inline]
+pub(crate) fn statx(
+ dirfd: BorrowedFd<'_>,
+ pathname: &CStr,
+ flags: AtFlags,
+ mask: StatxFlags,
+) -> io::Result<statx> {
+ unsafe {
+ let mut statx_buf = MaybeUninit::<statx>::uninit();
+ ret(syscall!(
+ __NR_statx,
+ dirfd,
+ pathname,
+ flags,
+ mask,
+ &mut statx_buf
+ ))
+ .map(|()| statx_buf.assume_init())
+ }
+}
+
+#[inline]
+pub(crate) fn is_statx_available() -> bool {
+ unsafe {
+ // Call `statx` with null pointers so that if it fails for any reason
+ // other than `EFAULT`, we know it's not supported.
+ matches!(
+ ret(syscall!(
+ __NR_statx,
+ raw_fd(AT_FDCWD),
+ zero(),
+ zero(),
+ zero(),
+ zero()
+ )),
+ Err(io::Errno::FAULT)
+ )
+ }
+}
+
+#[inline]
+pub(crate) fn fstatfs(fd: BorrowedFd<'_>) -> io::Result<StatFs> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ let mut result = MaybeUninit::<StatFs>::uninit();
+ ret(syscall!(
+ __NR_fstatfs64,
+ fd,
+ size_of::<StatFs, _>(),
+ &mut result
+ ))
+ .map(|()| result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ let mut result = MaybeUninit::<StatFs>::uninit();
+ ret(syscall!(__NR_fstatfs, fd, &mut result)).map(|()| result.assume_init())
+ }
+}
+
+#[inline]
+pub(crate) fn statfs(filename: &CStr) -> io::Result<StatFs> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ let mut result = MaybeUninit::<StatFs>::uninit();
+ ret(syscall!(
+ __NR_statfs64,
+ filename,
+ size_of::<StatFs, _>(),
+ &mut result
+ ))
+ .map(|()| result.assume_init())
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ let mut result = MaybeUninit::<StatFs>::uninit();
+ ret(syscall!(__NR_statfs, filename, &mut result)).map(|()| result.assume_init())
+ }
+}
+
+#[inline]
+pub(crate) fn readlink(path: &CStr, buf: &mut [u8]) -> io::Result<usize> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+ unsafe {
+ ret_usize(syscall!(
+ __NR_readlinkat,
+ raw_fd(AT_FDCWD),
+ path,
+ buf_addr_mut,
+ buf_len
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, buf: &mut [u8]) -> io::Result<usize> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+ unsafe {
+ ret_usize(syscall!(
+ __NR_readlinkat,
+ dirfd,
+ path,
+ buf_addr_mut,
+ buf_len
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_dupfd(fd: BorrowedFd<'_>, min: RawFd) -> io::Result<OwnedFd> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_fcntl64,
+ fd,
+ c_uint(F_DUPFD),
+ raw_fd(min)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_fcntl,
+ fd,
+ c_uint(F_DUPFD),
+ raw_fd(min)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_dupfd_cloexec(fd: BorrowedFd<'_>, min: RawFd) -> io::Result<OwnedFd> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_fcntl64,
+ fd,
+ c_uint(F_DUPFD_CLOEXEC),
+ raw_fd(min)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_fcntl,
+ fd,
+ c_uint(F_DUPFD_CLOEXEC),
+ raw_fd(min)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_getfd(fd: BorrowedFd<'_>) -> io::Result<FdFlags> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_c_uint(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETFD)))
+ .map(FdFlags::from_bits_truncate)
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_c_uint(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETFD)))
+ .map(FdFlags::from_bits_truncate)
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_setfd(fd: BorrowedFd<'_>, flags: FdFlags) -> io::Result<()> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_SETFD), flags))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(__NR_fcntl, fd, c_uint(F_SETFD), flags))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_getfl(fd: BorrowedFd<'_>) -> io::Result<OFlags> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_c_uint(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETFL)))
+ .map(OFlags::from_bits_truncate)
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_c_uint(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETFL)))
+ .map(OFlags::from_bits_truncate)
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_setfl(fd: BorrowedFd<'_>, flags: OFlags) -> io::Result<()> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_SETFL), flags))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(__NR_fcntl, fd, c_uint(F_SETFL), flags))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_getlease(fd: BorrowedFd<'_>) -> io::Result<c::c_int> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_c_int(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETLEASE)))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_c_int(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETLEASE)))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_getown(fd: BorrowedFd<'_>) -> io::Result<c::c_int> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_c_int(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETOWN)))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_c_int(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETOWN)))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_getsig(fd: BorrowedFd<'_>) -> io::Result<c::c_int> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_c_int(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETSIG)))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_c_int(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETSIG)))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result<usize> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_usize(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETPIPE_SZ)))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETPIPE_SZ)))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_setpipe_sz(fd: BorrowedFd<'_>, size: c::c_int) -> io::Result<usize> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_fcntl64,
+ fd,
+ c_uint(F_SETPIPE_SZ),
+ c_int(size)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_fcntl,
+ fd,
+ c_uint(F_SETPIPE_SZ),
+ c_int(size)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_get_seals(fd: BorrowedFd<'_>) -> io::Result<SealFlags> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_c_int(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GET_SEALS)))
+ .map(|seals| SealFlags::from_bits_unchecked(seals as u32))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_c_int(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GET_SEALS)))
+ .map(|seals| SealFlags::from_bits_unchecked(seals as u32))
+ }
+}
+
+#[inline]
+pub(crate) fn fcntl_add_seals(fd: BorrowedFd<'_>, seals: SealFlags) -> io::Result<()> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fcntl64,
+ fd,
+ c_uint(F_ADD_SEALS),
+ seals
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_fcntl,
+ fd,
+ c_uint(F_ADD_SEALS),
+ seals
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn rename(oldname: &CStr, newname: &CStr) -> io::Result<()> {
+ #[cfg(target_arch = "riscv64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_renameat2,
+ raw_fd(AT_FDCWD),
+ oldname,
+ raw_fd(AT_FDCWD),
+ newname,
+ c_uint(0)
+ ))
+ }
+ #[cfg(not(target_arch = "riscv64"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_renameat,
+ raw_fd(AT_FDCWD),
+ oldname,
+ raw_fd(AT_FDCWD),
+ newname
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn renameat(
+ old_dirfd: BorrowedFd<'_>,
+ oldname: &CStr,
+ new_dirfd: BorrowedFd<'_>,
+ newname: &CStr,
+) -> io::Result<()> {
+ #[cfg(target_arch = "riscv64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_renameat2,
+ old_dirfd,
+ oldname,
+ new_dirfd,
+ newname,
+ c_uint(0)
+ ))
+ }
+ #[cfg(not(target_arch = "riscv64"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_renameat,
+ old_dirfd,
+ oldname,
+ new_dirfd,
+ newname
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn renameat2(
+ old_dirfd: BorrowedFd<'_>,
+ oldname: &CStr,
+ new_dirfd: BorrowedFd<'_>,
+ newname: &CStr,
+ flags: RenameFlags,
+) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_renameat2,
+ old_dirfd,
+ oldname,
+ new_dirfd,
+ newname,
+ flags
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn unlink(pathname: &CStr) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_unlinkat,
+ raw_fd(AT_FDCWD),
+ pathname,
+ c_uint(0)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn unlinkat(dirfd: BorrowedFd<'_>, pathname: &CStr, flags: AtFlags) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_unlinkat, dirfd, pathname, flags)) }
+}
+
+#[inline]
+pub(crate) fn rmdir(pathname: &CStr) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_unlinkat,
+ raw_fd(AT_FDCWD),
+ pathname,
+ c_uint(AT_REMOVEDIR)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn link(oldname: &CStr, newname: &CStr) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_linkat,
+ raw_fd(AT_FDCWD),
+ oldname,
+ raw_fd(AT_FDCWD),
+ newname,
+ c_uint(0)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn linkat(
+ old_dirfd: BorrowedFd<'_>,
+ oldname: &CStr,
+ new_dirfd: BorrowedFd<'_>,
+ newname: &CStr,
+ flags: AtFlags,
+) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_linkat,
+ old_dirfd,
+ oldname,
+ new_dirfd,
+ newname,
+ flags
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn symlink(oldname: &CStr, newname: &CStr) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_symlinkat,
+ oldname,
+ raw_fd(AT_FDCWD),
+ newname
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn symlinkat(oldname: &CStr, dirfd: BorrowedFd<'_>, newname: &CStr) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_symlinkat, oldname, dirfd, newname)) }
+}
+
+#[inline]
+pub(crate) fn mkdir(pathname: &CStr, mode: Mode) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_mkdirat,
+ raw_fd(AT_FDCWD),
+ pathname,
+ mode
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn mkdirat(dirfd: BorrowedFd<'_>, pathname: &CStr, mode: Mode) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_mkdirat, dirfd, pathname, mode)) }
+}
+
+#[inline]
+pub(crate) fn getdents(fd: BorrowedFd<'_>, dirent: &mut [u8]) -> io::Result<usize> {
+ let (dirent_addr_mut, dirent_len) = slice_mut(dirent);
+
+ unsafe { ret_usize(syscall!(__NR_getdents64, fd, dirent_addr_mut, dirent_len)) }
+}
+
+#[inline]
+pub(crate) fn utimensat(
+ dirfd: BorrowedFd<'_>,
+ pathname: &CStr,
+ times: &Timestamps,
+ flags: AtFlags,
+) -> io::Result<()> {
+ _utimensat(dirfd, Some(pathname), times, flags)
+}
+
+#[inline]
+fn _utimensat(
+ dirfd: BorrowedFd<'_>,
+ pathname: Option<&CStr>,
+ times: &Timestamps,
+ flags: AtFlags,
+) -> io::Result<()> {
+ // Assert that `Timestamps` has the expected layout.
+ let _ = unsafe { core::mem::transmute::<Timestamps, [__kernel_timespec; 2]>(times.clone()) };
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ match ret(syscall_readonly!(
+ __NR_utimensat_time64,
+ dirfd,
+ pathname,
+ by_ref(times),
+ flags
+ )) {
+ Err(io::Errno::NOSYS) => _utimensat_old(dirfd, pathname, times, flags),
+ otherwise => otherwise,
+ }
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_utimensat,
+ dirfd,
+ pathname,
+ by_ref(times),
+ flags
+ ))
+ }
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn _utimensat_old(
+ dirfd: BorrowedFd<'_>,
+ pathname: Option<&CStr>,
+ times: &Timestamps,
+ flags: AtFlags,
+) -> io::Result<()> {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ let old_times = [
+ __kernel_old_timespec {
+ tv_sec: times
+ .last_access
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: times
+ .last_access
+ .tv_nsec
+ .try_into()
+ .map_err(|_| io::Errno::INVAL)?,
+ },
+ __kernel_old_timespec {
+ tv_sec: times
+ .last_modification
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: times
+ .last_modification
+ .tv_nsec
+ .try_into()
+ .map_err(|_| io::Errno::INVAL)?,
+ },
+ ];
+ // The length of the array is fixed and not passed into the syscall.
+ let old_times_addr = slice_just_addr(&old_times);
+ ret(syscall_readonly!(
+ __NR_utimensat,
+ dirfd,
+ pathname,
+ old_times_addr,
+ flags
+ ))
+}
+
+#[inline]
+pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> {
+ _utimensat(fd, None, times, AtFlags::empty())
+}
+
+pub(crate) fn accessat(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ access: Access,
+ flags: AtFlags,
+) -> io::Result<()> {
+ // Linux's `faccessat` doesn't have a flags parameter. If we have
+ // `AT_EACCESS` and we're not setuid or setgid, we can emulate it.
+ if flags.is_empty()
+ || (flags.bits() == AT_EACCESS
+ && crate::process::getuid() == crate::process::geteuid()
+ && crate::process::getgid() == crate::process::getegid())
+ {
+ return unsafe { ret(syscall_readonly!(__NR_faccessat, dirfd, path, access)) };
+ }
+
+ if flags.bits() != AT_EACCESS {
+ return Err(io::Errno::INVAL);
+ }
+
+ // TODO: Use faccessat2 in newer Linux versions.
+ Err(io::Errno::NOSYS)
+}
+
+#[inline]
+pub(crate) fn copy_file_range(
+ fd_in: BorrowedFd<'_>,
+ off_in: Option<&mut u64>,
+ fd_out: BorrowedFd<'_>,
+ off_out: Option<&mut u64>,
+ len: u64,
+) -> io::Result<u64> {
+ let len: usize = len.try_into().unwrap_or(usize::MAX);
+ _copy_file_range(fd_in, off_in, fd_out, off_out, len, 0).map(|result| result as u64)
+}
+
+#[inline]
+fn _copy_file_range(
+ fd_in: BorrowedFd<'_>,
+ off_in: Option<&mut u64>,
+ fd_out: BorrowedFd<'_>,
+ off_out: Option<&mut u64>,
+ len: usize,
+ flags: c::c_uint,
+) -> io::Result<usize> {
+ unsafe {
+ ret_usize(syscall!(
+ __NR_copy_file_range,
+ fd_in,
+ opt_mut(off_in),
+ fd_out,
+ opt_mut(off_out),
+ pass_usize(len),
+ c_uint(flags)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn memfd_create(name: &CStr, flags: MemfdFlags) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(syscall_readonly!(__NR_memfd_create, name, flags)) }
+}
+
+#[inline]
+pub(crate) fn sendfile(
+ out_fd: BorrowedFd<'_>,
+ in_fd: BorrowedFd<'_>,
+ offset: Option<&mut u64>,
+ count: usize,
+) -> io::Result<usize> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_sendfile64,
+ out_fd,
+ in_fd,
+ opt_mut(offset),
+ pass_usize(count)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_sendfile,
+ out_fd,
+ in_fd,
+ opt_mut(offset),
+ pass_usize(count)
+ ))
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/fs/types.rs b/vendor/rustix/src/imp/linux_raw/fs/types.rs
new file mode 100644
index 000000000..959a5ee27
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/fs/types.rs
@@ -0,0 +1,613 @@
+use super::super::c;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `FD_*` constants for use with [`fcntl_getfd`] and [`fcntl_setfd`].
+ ///
+ /// [`fcntl_getfd`]: crate::fs::fcntl_getfd
+ /// [`fcntl_setfd`]: crate::fs::fcntl_setfd
+ pub struct FdFlags: c::c_uint {
+ /// `FD_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::FD_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `*_OK` constants for use with [`accessat`].
+ ///
+ /// [`accessat`]: fn.accessat.html
+ pub struct Access: c::c_uint {
+ /// `R_OK`
+ const READ_OK = linux_raw_sys::general::R_OK;
+
+ /// `W_OK`
+ const WRITE_OK = linux_raw_sys::general::W_OK;
+
+ /// `X_OK`
+ const EXEC_OK = linux_raw_sys::general::X_OK;
+
+ /// `F_OK`
+ const EXISTS = linux_raw_sys::general::F_OK;
+ }
+}
+
+bitflags! {
+ /// `AT_*` constants for use with [`openat`], [`statat`], and other `*at`
+ /// functions.
+ ///
+ /// [`openat`]: crate::fs::openat
+ /// [`statat`]: crate::fs::statat
+ pub struct AtFlags: c::c_uint {
+ /// `AT_REMOVEDIR`
+ const REMOVEDIR = linux_raw_sys::general::AT_REMOVEDIR;
+
+ /// `AT_SYMLINK_FOLLOW`
+ const SYMLINK_FOLLOW = linux_raw_sys::general::AT_SYMLINK_FOLLOW;
+
+ /// `AT_SYMLINK_NOFOLLOW`
+ const SYMLINK_NOFOLLOW = linux_raw_sys::general::AT_SYMLINK_NOFOLLOW;
+
+ /// `AT_EMPTY_PATH`
+ const EMPTY_PATH = linux_raw_sys::general::AT_EMPTY_PATH;
+
+ /// `AT_EACCESS`
+ const EACCESS = linux_raw_sys::general::AT_EACCESS;
+
+ /// `AT_STATX_SYNC_AS_STAT`
+ const STATX_SYNC_AS_STAT = linux_raw_sys::general::AT_STATX_SYNC_AS_STAT;
+
+ /// `AT_STATX_FORCE_SYNC`
+ const STATX_FORCE_SYNC = linux_raw_sys::general::AT_STATX_FORCE_SYNC;
+
+ /// `AT_STATX_DONT_SYNC`
+ const STATX_DONT_SYNC = linux_raw_sys::general::AT_STATX_DONT_SYNC;
+ }
+}
+
+bitflags! {
+ /// `S_I*` constants for use with [`openat`], [`chmodat`], and [`fchmod`].
+ ///
+ /// [`openat`]: crate::fs::openat
+ /// [`chmodat`]: crate::fs::chmodat
+ /// [`fchmod`]: crate::fs::fchmod
+ pub struct Mode: RawMode {
+ /// `S_IRWXU`
+ const RWXU = linux_raw_sys::general::S_IRWXU;
+
+ /// `S_IRUSR`
+ const RUSR = linux_raw_sys::general::S_IRUSR;
+
+ /// `S_IWUSR`
+ const WUSR = linux_raw_sys::general::S_IWUSR;
+
+ /// `S_IXUSR`
+ const XUSR = linux_raw_sys::general::S_IXUSR;
+
+ /// `S_IRWXG`
+ const RWXG = linux_raw_sys::general::S_IRWXG;
+
+ /// `S_IRGRP`
+ const RGRP = linux_raw_sys::general::S_IRGRP;
+
+ /// `S_IWGRP`
+ const WGRP = linux_raw_sys::general::S_IWGRP;
+
+ /// `S_IXGRP`
+ const XGRP = linux_raw_sys::general::S_IXGRP;
+
+ /// `S_IRWXO`
+ const RWXO = linux_raw_sys::general::S_IRWXO;
+
+ /// `S_IROTH`
+ const ROTH = linux_raw_sys::general::S_IROTH;
+
+ /// `S_IWOTH`
+ const WOTH = linux_raw_sys::general::S_IWOTH;
+
+ /// `S_IXOTH`
+ const XOTH = linux_raw_sys::general::S_IXOTH;
+
+ /// `S_ISUID`
+ const SUID = linux_raw_sys::general::S_ISUID;
+
+ /// `S_ISGID`
+ const SGID = linux_raw_sys::general::S_ISGID;
+
+ /// `S_ISVTX`
+ const SVTX = linux_raw_sys::general::S_ISVTX;
+ }
+}
+
+impl Mode {
+ /// Construct a `Mode` from the mode bits of the `st_mode` field of a
+ /// `Stat`.
+ #[inline]
+ pub const fn from_raw_mode(st_mode: RawMode) -> Self {
+ Self::from_bits_truncate(st_mode)
+ }
+
+ /// Construct an `st_mode` value from `Stat`.
+ #[inline]
+ pub const fn as_raw_mode(self) -> RawMode {
+ self.bits()
+ }
+}
+
+bitflags! {
+ /// `O_*` constants for use with [`openat`].
+ ///
+ /// [`openat`]: crate::fs::openat
+ pub struct OFlags: c::c_uint {
+ /// `O_ACCMODE`
+ const ACCMODE = linux_raw_sys::general::O_ACCMODE;
+
+ /// Similar to `ACCMODE`, but just includes the read/write flags, and
+ /// no other flags.
+ ///
+ /// Some implementations include `O_PATH` in `O_ACCMODE`, when
+ /// sometimes we really just want the read/write bits. Caution is
+ /// indicated, as the presence of `O_PATH` may mean that the read/write
+ /// bits don't have their usual meaning.
+ const RWMODE = linux_raw_sys::general::O_RDONLY |
+ linux_raw_sys::general::O_WRONLY |
+ linux_raw_sys::general::O_RDWR;
+
+ /// `O_APPEND`
+ const APPEND = linux_raw_sys::general::O_APPEND;
+
+ /// `O_CREAT`
+ #[doc(alias = "CREAT")]
+ const CREATE = linux_raw_sys::general::O_CREAT;
+
+ /// `O_DIRECTORY`
+ const DIRECTORY = linux_raw_sys::general::O_DIRECTORY;
+
+ /// `O_DSYNC`. Linux 2.6.32 only supports `O_SYNC`.
+ const DSYNC = linux_raw_sys::general::O_SYNC;
+
+ /// `O_EXCL`
+ const EXCL = linux_raw_sys::general::O_EXCL;
+
+ /// `O_FSYNC`. Linux 2.6.32 only supports `O_SYNC`.
+ const FSYNC = linux_raw_sys::general::O_SYNC;
+
+ /// `O_NOFOLLOW`
+ const NOFOLLOW = linux_raw_sys::general::O_NOFOLLOW;
+
+ /// `O_NONBLOCK`
+ const NONBLOCK = linux_raw_sys::general::O_NONBLOCK;
+
+ /// `O_RDONLY`
+ const RDONLY = linux_raw_sys::general::O_RDONLY;
+
+ /// `O_WRONLY`
+ const WRONLY = linux_raw_sys::general::O_WRONLY;
+
+ /// `O_RDWR`
+ const RDWR = linux_raw_sys::general::O_RDWR;
+
+ /// `O_NOCTTY`
+ const NOCTTY = linux_raw_sys::general::O_NOCTTY;
+
+ /// `O_RSYNC`. Linux 2.6.32 only supports `O_SYNC`.
+ const RSYNC = linux_raw_sys::general::O_SYNC;
+
+ /// `O_SYNC`
+ const SYNC = linux_raw_sys::general::O_SYNC;
+
+ /// `O_TRUNC`
+ const TRUNC = linux_raw_sys::general::O_TRUNC;
+
+ /// `O_PATH`
+ const PATH = linux_raw_sys::general::O_PATH;
+
+ /// `O_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::O_CLOEXEC;
+
+ /// `O_TMPFILE`
+ const TMPFILE = linux_raw_sys::general::O_TMPFILE;
+
+ /// `O_NOATIME`
+ const NOATIME = linux_raw_sys::general::O_NOATIME;
+ }
+}
+
+bitflags! {
+ /// `RESOLVE_*` constants for use with [`openat2`].
+ ///
+ /// [`openat2`]: crate::fs::openat2
+ #[derive(Default)]
+ pub struct ResolveFlags: u64 {
+ /// `RESOLVE_NO_XDEV`
+ const NO_XDEV = linux_raw_sys::general::RESOLVE_NO_XDEV as u64;
+
+ /// `RESOLVE_NO_MAGICLINKS`
+ const NO_MAGICLINKS = linux_raw_sys::general::RESOLVE_NO_MAGICLINKS as u64;
+
+ /// `RESOLVE_NO_SYMLINKS`
+ const NO_SYMLINKS = linux_raw_sys::general::RESOLVE_NO_SYMLINKS as u64;
+
+ /// `RESOLVE_BENEATH`
+ const BENEATH = linux_raw_sys::general::RESOLVE_BENEATH as u64;
+
+ /// `RESOLVE_IN_ROOT`
+ const IN_ROOT = linux_raw_sys::general::RESOLVE_IN_ROOT as u64;
+
+ /// `RESOLVE_CACHED` (since Linux 5.12)
+ const CACHED = linux_raw_sys::general::RESOLVE_CACHED as u64;
+ }
+}
+
+bitflags! {
+ /// `RENAME_*` constants for use with [`renameat_with`].
+ ///
+ /// [`renameat_with`]: crate::fs::renameat_with
+ pub struct RenameFlags: c::c_uint {
+ /// `RENAME_EXCHANGE`
+ const EXCHANGE = linux_raw_sys::general::RENAME_EXCHANGE;
+
+ /// `RENAME_NOREPLACE`
+ const NOREPLACE = linux_raw_sys::general::RENAME_NOREPLACE;
+
+ /// `RENAME_WHITEOUT`
+ const WHITEOUT = linux_raw_sys::general::RENAME_WHITEOUT;
+ }
+}
+
+/// `S_IF*` constants for use with [`mknodat`] and [`Stat`]'s `st_mode` field.
+///
+/// [`mknodat`]: crate::fs::mknodat
+/// [`Stat`]: crate::fs::Stat
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum FileType {
+ /// `S_IFREG`
+ RegularFile = linux_raw_sys::general::S_IFREG as isize,
+
+ /// `S_IFDIR`
+ Directory = linux_raw_sys::general::S_IFDIR as isize,
+
+ /// `S_IFLNK`
+ Symlink = linux_raw_sys::general::S_IFLNK as isize,
+
+ /// `S_IFIFO`
+ Fifo = linux_raw_sys::general::S_IFIFO as isize,
+
+ /// `S_IFSOCK`
+ Socket = linux_raw_sys::general::S_IFSOCK as isize,
+
+ /// `S_IFCHR`
+ CharacterDevice = linux_raw_sys::general::S_IFCHR as isize,
+
+ /// `S_IFBLK`
+ BlockDevice = linux_raw_sys::general::S_IFBLK as isize,
+
+ /// An unknown filesystem object.
+ Unknown,
+}
+
+impl FileType {
+ /// Construct a `FileType` from the `S_IFMT` bits of the `st_mode` field of
+ /// a `Stat`.
+ #[inline]
+ pub const fn from_raw_mode(st_mode: RawMode) -> Self {
+ match st_mode & linux_raw_sys::general::S_IFMT {
+ linux_raw_sys::general::S_IFREG => Self::RegularFile,
+ linux_raw_sys::general::S_IFDIR => Self::Directory,
+ linux_raw_sys::general::S_IFLNK => Self::Symlink,
+ linux_raw_sys::general::S_IFIFO => Self::Fifo,
+ linux_raw_sys::general::S_IFSOCK => Self::Socket,
+ linux_raw_sys::general::S_IFCHR => Self::CharacterDevice,
+ linux_raw_sys::general::S_IFBLK => Self::BlockDevice,
+ _ => Self::Unknown,
+ }
+ }
+
+ /// Construct an `st_mode` value from `Stat`.
+ #[inline]
+ pub const fn as_raw_mode(self) -> RawMode {
+ match self {
+ Self::RegularFile => linux_raw_sys::general::S_IFREG,
+ Self::Directory => linux_raw_sys::general::S_IFDIR,
+ Self::Symlink => linux_raw_sys::general::S_IFLNK,
+ Self::Fifo => linux_raw_sys::general::S_IFIFO,
+ Self::Socket => linux_raw_sys::general::S_IFSOCK,
+ Self::CharacterDevice => linux_raw_sys::general::S_IFCHR,
+ Self::BlockDevice => linux_raw_sys::general::S_IFBLK,
+ Self::Unknown => linux_raw_sys::general::S_IFMT,
+ }
+ }
+
+ /// Construct a `FileType` from the `d_type` field of a `dirent`.
+ #[inline]
+ pub(crate) const fn from_dirent_d_type(d_type: u8) -> Self {
+ match d_type as u32 {
+ linux_raw_sys::general::DT_REG => Self::RegularFile,
+ linux_raw_sys::general::DT_DIR => Self::Directory,
+ linux_raw_sys::general::DT_LNK => Self::Symlink,
+ linux_raw_sys::general::DT_SOCK => Self::Socket,
+ linux_raw_sys::general::DT_FIFO => Self::Fifo,
+ linux_raw_sys::general::DT_CHR => Self::CharacterDevice,
+ linux_raw_sys::general::DT_BLK => Self::BlockDevice,
+ // linux_raw_sys::general::DT_UNKNOWN |
+ _ => Self::Unknown,
+ }
+ }
+}
+
+/// `POSIX_FADV_*` constants for use with [`fadvise`].
+///
+/// [`fadvise`]: crate::fs::fadvise
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[repr(u32)]
+pub enum Advice {
+ /// `POSIX_FADV_NORMAL`
+ Normal = linux_raw_sys::general::POSIX_FADV_NORMAL,
+
+ /// `POSIX_FADV_SEQUENTIAL`
+ Sequential = linux_raw_sys::general::POSIX_FADV_SEQUENTIAL,
+
+ /// `POSIX_FADV_RANDOM`
+ Random = linux_raw_sys::general::POSIX_FADV_RANDOM,
+
+ /// `POSIX_FADV_NOREUSE`
+ NoReuse = linux_raw_sys::general::POSIX_FADV_NOREUSE,
+
+ /// `POSIX_FADV_WILLNEED`
+ WillNeed = linux_raw_sys::general::POSIX_FADV_WILLNEED,
+
+ /// `POSIX_FADV_DONTNEED`
+ DontNeed = linux_raw_sys::general::POSIX_FADV_DONTNEED,
+}
+
+bitflags! {
+ /// `MFD_*` constants for use with [`memfd_create`].
+ ///
+ /// [`memfd_create`]: crate::fs::memfd_create
+ pub struct MemfdFlags: c::c_uint {
+ /// `MFD_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::MFD_CLOEXEC;
+
+ /// `MFD_ALLOW_SEALING`
+ const ALLOW_SEALING = linux_raw_sys::general::MFD_ALLOW_SEALING;
+
+ /// `MFD_HUGETLB` (since Linux 4.14)
+ const HUGETLB = linux_raw_sys::general::MFD_HUGETLB;
+
+ /// `MFD_HUGE_64KB`
+ const HUGE_64KB = linux_raw_sys::general::MFD_HUGE_64KB;
+ /// `MFD_HUGE_512JB`
+ const HUGE_512KB = linux_raw_sys::general::MFD_HUGE_512KB;
+ /// `MFD_HUGE_1MB`
+ const HUGE_1MB = linux_raw_sys::general::MFD_HUGE_1MB;
+ /// `MFD_HUGE_2MB`
+ const HUGE_2MB = linux_raw_sys::general::MFD_HUGE_2MB;
+ /// `MFD_HUGE_8MB`
+ const HUGE_8MB = linux_raw_sys::general::MFD_HUGE_8MB;
+ /// `MFD_HUGE_16MB`
+ const HUGE_16MB = linux_raw_sys::general::MFD_HUGE_16MB;
+ /// `MFD_HUGE_32MB`
+ const HUGE_32MB = linux_raw_sys::general::MFD_HUGE_32MB;
+ /// `MFD_HUGE_256MB`
+ const HUGE_256MB = linux_raw_sys::general::MFD_HUGE_256MB;
+ /// `MFD_HUGE_512MB`
+ const HUGE_512MB = linux_raw_sys::general::MFD_HUGE_512MB;
+ /// `MFD_HUGE_1GB`
+ const HUGE_1GB = linux_raw_sys::general::MFD_HUGE_1GB;
+ /// `MFD_HUGE_2GB`
+ const HUGE_2GB = linux_raw_sys::general::MFD_HUGE_2GB;
+ /// `MFD_HUGE_16GB`
+ const HUGE_16GB = linux_raw_sys::general::MFD_HUGE_16GB;
+ }
+}
+
+bitflags! {
+ /// `F_SEAL_*` constants for use with [`fcntl_add_seals`] and
+ /// [`fcntl_get_seals`].
+ ///
+ /// [`fcntl_add_seals`]: crate::fs::fcntl_add_seals
+ /// [`fcntl_get_seals`]: crate::fs::fcntl_get_seals
+ pub struct SealFlags: u32 {
+ /// `F_SEAL_SEAL`.
+ const SEAL = linux_raw_sys::general::F_SEAL_SEAL;
+ /// `F_SEAL_SHRINK`.
+ const SHRINK = linux_raw_sys::general::F_SEAL_SHRINK;
+ /// `F_SEAL_GROW`.
+ const GROW = linux_raw_sys::general::F_SEAL_GROW;
+ /// `F_SEAL_WRITE`.
+ const WRITE = linux_raw_sys::general::F_SEAL_WRITE;
+ /// `F_SEAL_FUTURE_WRITE` (since Linux 5.1)
+ const FUTURE_WRITE = linux_raw_sys::general::F_SEAL_FUTURE_WRITE;
+ }
+}
+
+bitflags! {
+ /// `STATX_*` constants for use with [`statx`].
+ ///
+ /// [`statx`]: crate::fs::statx
+ pub struct StatxFlags: u32 {
+ /// `STATX_TYPE`
+ const TYPE = linux_raw_sys::general::STATX_TYPE;
+
+ /// `STATX_MODE`
+ const MODE = linux_raw_sys::general::STATX_MODE;
+
+ /// `STATX_NLINK`
+ const NLINK = linux_raw_sys::general::STATX_NLINK;
+
+ /// `STATX_UID`
+ const UID = linux_raw_sys::general::STATX_UID;
+
+ /// `STATX_GID`
+ const GID = linux_raw_sys::general::STATX_GID;
+
+ /// `STATX_ATIME`
+ const ATIME = linux_raw_sys::general::STATX_ATIME;
+
+ /// `STATX_MTIME`
+ const MTIME = linux_raw_sys::general::STATX_MTIME;
+
+ /// `STATX_CTIME`
+ const CTIME = linux_raw_sys::general::STATX_CTIME;
+
+ /// `STATX_INO`
+ const INO = linux_raw_sys::general::STATX_INO;
+
+ /// `STATX_SIZE`
+ const SIZE = linux_raw_sys::general::STATX_SIZE;
+
+ /// `STATX_BLOCKS`
+ const BLOCKS = linux_raw_sys::general::STATX_BLOCKS;
+
+ /// `STATX_BASIC_STATS`
+ const BASIC_STATS = linux_raw_sys::general::STATX_BASIC_STATS;
+
+ /// `STATX_BTIME`
+ const BTIME = linux_raw_sys::general::STATX_BTIME;
+
+ /// `STATX_MNT_ID` (since Linux 5.8)
+ const MNT_ID = linux_raw_sys::general::STATX_MNT_ID;
+
+ /// `STATX_ALL`
+ const ALL = linux_raw_sys::general::STATX_ALL;
+ }
+}
+
+bitflags! {
+ /// `FALLOC_FL_*` constants for use with [`fallocate`].
+ ///
+ /// [`fallocate`]: crate::fs::fallocate
+ pub struct FallocateFlags: u32 {
+ /// `FALLOC_FL_KEEP_SIZE`
+ const KEEP_SIZE = linux_raw_sys::general::FALLOC_FL_KEEP_SIZE;
+ /// `FALLOC_FL_PUNCH_HOLE`
+ const PUNCH_HOLE = linux_raw_sys::general::FALLOC_FL_PUNCH_HOLE;
+ /// `FALLOC_FL_NO_HIDE_STALE`
+ const NO_HIDE_STALE = linux_raw_sys::general::FALLOC_FL_NO_HIDE_STALE;
+ /// `FALLOC_FL_COLLAPSE_RANGE`
+ const COLLAPSE_RANGE = linux_raw_sys::general::FALLOC_FL_COLLAPSE_RANGE;
+ /// `FALLOC_FL_ZERO_RANGE`
+ const ZERO_RANGE = linux_raw_sys::general::FALLOC_FL_ZERO_RANGE;
+ /// `FALLOC_FL_INSERT_RANGE`
+ const INSERT_RANGE = linux_raw_sys::general::FALLOC_FL_INSERT_RANGE;
+ /// `FALLOC_FL_UNSHARE_RANGE`
+ const UNSHARE_RANGE = linux_raw_sys::general::FALLOC_FL_UNSHARE_RANGE;
+ }
+}
+
+/// `LOCK_*` constants for use with [`flock`]
+///
+/// [`flock`]: crate::fs::flock
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[repr(u32)]
+pub enum FlockOperation {
+ /// `LOCK_SH`
+ LockShared = linux_raw_sys::general::LOCK_SH,
+ /// `LOCK_EX`
+ LockExclusive = linux_raw_sys::general::LOCK_EX,
+ /// `LOCK_UN`
+ Unlock = linux_raw_sys::general::LOCK_UN,
+ /// `LOCK_SH | LOCK_NB`
+ NonBlockingLockShared = linux_raw_sys::general::LOCK_SH | linux_raw_sys::general::LOCK_NB,
+ /// `LOCK_EX | LOCK_NB`
+ NonBlockingLockExclusive = linux_raw_sys::general::LOCK_EX | linux_raw_sys::general::LOCK_NB,
+ /// `LOCK_UN | LOCK_NB`
+ NonBlockingUnlock = linux_raw_sys::general::LOCK_UN | linux_raw_sys::general::LOCK_NB,
+}
+
+/// `struct stat` for use with [`statat`] and [`fstat`].
+///
+/// [`statat`]: crate::fs::statat
+/// [`fstat`]: crate::fs::fstat
+// On 32-bit, and mips64, Linux's `struct stat64` has a 32-bit `st_mtime` and
+// friends, so we use our own struct, populated from `statx` where possible, to
+// avoid the y2038 bug.
+#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+#[allow(missing_docs)]
+pub struct Stat {
+ pub st_dev: u64,
+ pub st_mode: u32,
+ pub st_nlink: u32,
+ pub st_uid: u32,
+ pub st_gid: u32,
+ pub st_rdev: u64,
+ pub st_size: i64,
+ pub st_blksize: u32,
+ pub st_blocks: u64,
+ pub st_atime: u64,
+ pub st_atime_nsec: u32,
+ pub st_mtime: u64,
+ pub st_mtime_nsec: u32,
+ pub st_ctime: u64,
+ pub st_ctime_nsec: u32,
+ pub st_ino: u64,
+}
+
+/// `struct stat` for use with [`statat`] and [`fstat`].
+///
+/// [`statat`]: crate::fs::statat
+/// [`fstat`]: crate::fs::fstat
+#[cfg(all(target_pointer_width = "64", not(target_arch = "mips64")))]
+pub type Stat = linux_raw_sys::general::stat;
+
+/// `struct statfs` for use with [`fstatfs`].
+///
+/// [`fstatfs`]: crate::fs::fstatfs
+#[cfg(target_pointer_width = "32")]
+#[allow(clippy::module_name_repetitions)]
+pub type StatFs = linux_raw_sys::general::statfs64;
+
+/// `struct statfs` for use with [`fstatfs`].
+///
+/// [`fstatfs`]: crate::fs::fstatfs
+#[cfg(target_pointer_width = "64")]
+#[allow(clippy::module_name_repetitions)]
+pub type StatFs = linux_raw_sys::general::statfs64;
+
+/// `struct statx` for use with [`statx`].
+///
+/// [`statx`]: crate::fs::statx
+pub type Statx = linux_raw_sys::general::statx;
+
+/// `struct statx_timestamp` for use with [`Statx`].
+pub type StatxTimestamp = linux_raw_sys::general::statx_timestamp;
+
+/// `mode_t`
+#[cfg(not(any(
+ target_arch = "x86",
+ target_arch = "sparc",
+ target_arch = "avr",
+ target_arch = "arm",
+)))]
+pub type RawMode = linux_raw_sys::general::__kernel_mode_t;
+
+/// `mode_t
+#[cfg(any(
+ target_arch = "x86",
+ target_arch = "sparc",
+ target_arch = "avr",
+ target_arch = "arm",
+))]
+// Don't use `__kernel_mode_t` since it's `u16` which differs from `st_size`.
+pub type RawMode = c::c_uint;
+
+/// `dev_t`
+// Within the kernel the dev_t is 32-bit, but userspace uses a 64-bit field.
+pub type Dev = u64;
+
+/// `__fsword_t`
+#[cfg(not(target_arch = "mips64"))]
+pub type FsWord = linux_raw_sys::general::__fsword_t;
+
+/// `__fsword_t`
+#[cfg(target_arch = "mips64")]
+pub type FsWord = i64;
+
+pub use linux_raw_sys::general::{UTIME_NOW, UTIME_OMIT};
+
+/// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem.
+pub const PROC_SUPER_MAGIC: FsWord = linux_raw_sys::general::PROC_SUPER_MAGIC as FsWord;
+
+/// `NFS_SUPER_MAGIC`—The magic number for the NFS filesystem.
+pub const NFS_SUPER_MAGIC: FsWord = linux_raw_sys::general::NFS_SUPER_MAGIC as FsWord;
diff --git a/vendor/rustix/src/imp/linux_raw/io/epoll.rs b/vendor/rustix/src/imp/linux_raw/io/epoll.rs
new file mode 100644
index 000000000..4362e40fb
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io/epoll.rs
@@ -0,0 +1,551 @@
+//! epoll support.
+//!
+//! This is an experiment, and it isn't yet clear whether epoll is the right
+//! level of abstraction at which to introduce safety. But it works fairly well
+//! in simple examples 🙂.
+//!
+//! # Examples
+//!
+//! ```rust,no_run
+//! # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+//! # #[cfg(feature = "net")]
+//! # fn main() -> std::io::Result<()> {
+//! use io_lifetimes::AsFd;
+//! use rustix::io::epoll::{self, Epoll};
+//! use rustix::io::{ioctl_fionbio, read, write};
+//! use rustix::net::{
+//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4,
+//! SocketType,
+//! };
+//! use std::os::unix::io::AsRawFd;
+//!
+//! // Create a socket and listen on it.
+//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?;
+//! listen(&listen_sock, 1)?;
+//!
+//! // Create an epoll object. Using `Owning` here means the epoll object will
+//! // take ownership of the file descriptors registered with it.
+//! let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC, epoll::Owning::new())?;
+//!
+//! // Remember the socket raw fd, which we use for comparisons only.
+//! let raw_listen_sock = listen_sock.as_fd().as_raw_fd();
+//!
+//! // Register the socket with the epoll object.
+//! epoll.add(listen_sock, epoll::EventFlags::IN)?;
+//!
+//! // Process events.
+//! let mut event_list = epoll::EventVec::with_capacity(4);
+//! loop {
+//! epoll.wait(&mut event_list, -1)?;
+//! for (_event_flags, target) in &event_list {
+//! if target.as_raw_fd() == raw_listen_sock {
+//! // Accept a new connection, set it to non-blocking, and
+//! // register to be notified when it's ready to write to.
+//! let conn_sock = accept(&*target)?;
+//! ioctl_fionbio(&conn_sock, true)?;
+//! epoll.add(conn_sock, epoll::EventFlags::OUT | epoll::EventFlags::ET)?;
+//! } else {
+//! // Write a message to the stream and then unregister it.
+//! write(&*target, b"hello\n")?;
+//! let _ = epoll.del(target)?;
+//! }
+//! }
+//! }
+//! # }
+//! # #[cfg(not(feature = "net"))]
+//! # fn main() {}
+//! ```
+
+#![allow(unsafe_code)]
+
+use super::super::c;
+use crate::fd::{AsFd, AsRawFd, BorrowedFd, RawFd};
+#[cfg(feature = "std")]
+use crate::fd::{FromFd, FromRawFd, IntoFd, IntoRawFd};
+use crate::imp::io::syscalls::{epoll_add, epoll_create, epoll_del, epoll_mod, epoll_wait};
+use crate::io::{self, OwnedFd};
+use alloc::vec::Vec;
+use bitflags::bitflags;
+use core::fmt;
+use core::marker::PhantomData;
+use core::ops::Deref;
+use core::ptr::null;
+
+bitflags! {
+ /// `EPOLL_*` for use with [`Epoll::new`].
+ pub struct CreateFlags: c::c_uint {
+ /// `EPOLL_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::EPOLL_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `EPOLL*` for use with [`Epoll::add`].
+ #[derive(Default)]
+ pub struct EventFlags: u32 {
+ /// `EPOLLIN`
+ const IN = linux_raw_sys::general::EPOLLIN as u32;
+
+ /// `EPOLLOUT`
+ const OUT = linux_raw_sys::general::EPOLLOUT as u32;
+
+ /// `EPOLLPRI`
+ const PRI = linux_raw_sys::general::EPOLLPRI as u32;
+
+ /// `EPOLLERR`
+ const ERR = linux_raw_sys::general::EPOLLERR as u32;
+
+ /// `EPOLLHUP`
+ const HUP = linux_raw_sys::general::EPOLLHUP as u32;
+
+ /// `EPOLLET`
+ const ET = linux_raw_sys::general::EPOLLET as u32;
+
+ /// `EPOLLONESHOT`
+ const ONESHOT = linux_raw_sys::general::EPOLLONESHOT as u32;
+
+ /// `EPOLLWAKEUP`
+ const WAKEUP = linux_raw_sys::general::EPOLLWAKEUP as u32;
+
+ /// `EPOLLEXCLUSIVE`
+ const EXCLUSIVE = linux_raw_sys::general::EPOLLEXCLUSIVE as u32;
+ }
+}
+
+/// A reference to a `T`.
+pub struct Ref<'a, T> {
+ t: T,
+ _phantom: PhantomData<&'a T>,
+}
+
+impl<'a, T> Ref<'a, T> {
+ #[inline]
+ fn new(t: T) -> Self {
+ Self {
+ t,
+ _phantom: PhantomData,
+ }
+ }
+
+ #[inline]
+ fn consume(self) -> T {
+ self.t
+ }
+}
+
+impl<'a, T> Deref for Ref<'a, T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ &self.t
+ }
+}
+
+impl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.t.fmt(fmt)
+ }
+}
+
+/// A trait for data stored within an [`Epoll`] instance.
+pub trait Context {
+ /// The type of an element owned by this context.
+ type Data;
+
+ /// The type of a value used to refer to an element owned by this context.
+ type Target: AsFd;
+
+ /// Assume ownership of `data`, and returning a `Target`.
+ fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target>;
+
+ /// Encode `target` as a `u64`. The only requirement on this value is that
+ /// it be decodable by `decode`.
+ fn encode(&self, target: Ref<'_, Self::Target>) -> u64;
+
+ /// Decode `raw`, which is a value encoded by `encode`, into a `Target`.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be a `u64` value returned from `encode`, from the same
+ /// context, and within the context's lifetime.
+ unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target>;
+
+ /// Release ownership of the value referred to by `target` and return it.
+ fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data;
+}
+
+/// A type implementing [`Context`] where the `Data` type is `BorrowedFd<'a>`.
+pub struct Borrowing<'a> {
+ _phantom: PhantomData<BorrowedFd<'a>>,
+}
+
+impl<'a> Context for Borrowing<'a> {
+ type Data = BorrowedFd<'a>;
+ type Target = BorrowedFd<'a>;
+
+ #[inline]
+ fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
+ Ref::new(data)
+ }
+
+ #[inline]
+ fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
+ target.as_raw_fd() as u64
+ }
+
+ #[inline]
+ unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
+ Ref::new(BorrowedFd::<'a>::borrow_raw(raw as RawFd))
+ }
+
+ #[inline]
+ fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
+ target.consume()
+ }
+}
+
+/// A type implementing [`Context`] where the `Data` type is `T`, a type
+/// implementing `IntoFd` and `FromFd`.
+///
+/// This may be used with [`OwnedFd`], or higher-level types like
+/// [`std::fs::File`] or [`std::net::TcpStream`].
+#[cfg(feature = "std")]
+pub struct Owning<'context, T: IntoFd + FromFd> {
+ _phantom: PhantomData<&'context T>,
+}
+
+#[cfg(feature = "std")]
+impl<'context, T: IntoFd + FromFd> Owning<'context, T> {
+ /// Creates a new empty `Owning`.
+ #[allow(clippy::new_without_default)] // This is a specialized type that doesn't need to be generically constructible.
+ #[inline]
+ pub fn new() -> Self {
+ Self {
+ _phantom: PhantomData,
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'context, T: AsFd + IntoFd + FromFd> Context for Owning<'context, T> {
+ type Data = T;
+ type Target = BorrowedFd<'context>;
+
+ #[inline]
+ fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
+ let raw_fd = data.into_fd().into_raw_fd();
+ // Safety: `epoll` will assign ownership of the file descriptor to the
+ // kernel epoll object. We use `IntoFd`+`IntoRawFd` to consume the
+ // `Data` and extract the raw file descriptor and then "borrow" it
+ // with `borrow_raw` knowing that the borrow won't outlive the
+ // kernel epoll object.
+ unsafe { Ref::new(BorrowedFd::<'context>::borrow_raw(raw_fd)) }
+ }
+
+ #[inline]
+ fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
+ target.as_fd().as_raw_fd() as u64
+ }
+
+ #[inline]
+ unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
+ Ref::new(BorrowedFd::<'context>::borrow_raw(raw as RawFd))
+ }
+
+ #[inline]
+ fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
+ let raw_fd = target.consume().as_raw_fd();
+
+ // Safety: The file descriptor was held by the kernel epoll object and
+ // is now being released, so we can create a new `OwnedFd` that assumes
+ // ownership.
+ unsafe { T::from_fd(io_lifetimes::OwnedFd::from_raw_fd(raw_fd)) }
+ }
+}
+
+/// An "epoll", an interface to an OS object allowing one to repeatedly wait
+/// for events from a set of file descriptors efficiently.
+pub struct Epoll<Context: self::Context> {
+ epoll_fd: OwnedFd,
+ context: Context,
+}
+
+impl<Context: self::Context> Epoll<Context> {
+ /// `epoll_create1(flags)`—Creates a new `Epoll`.
+ ///
+ /// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
+ /// descriptor from being implicitly passed across `exec` boundaries.
+ #[inline]
+ #[doc(alias = "epoll_create1")]
+ pub fn new(flags: CreateFlags, context: Context) -> io::Result<Self> {
+ // Safety: We're calling `epoll_create1` via FFI and we know how it
+ // behaves.
+ Ok(Self {
+ epoll_fd: epoll_create(flags)?,
+ context,
+ })
+ }
+
+ /// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an
+ /// `Epoll`.
+ ///
+ /// This registers interest in any of the events set in `events` occurring
+ /// on the file descriptor associated with `data`.
+ #[doc(alias = "epoll_ctl")]
+ pub fn add(
+ &self,
+ data: Context::Data,
+ event_flags: EventFlags,
+ ) -> io::Result<Ref<'_, Context::Target>> {
+ // Safety: We're calling `epoll_ctl` via FFI and we know how it
+ // behaves.
+ unsafe {
+ let target = self.context.acquire(data);
+ let raw_fd = target.as_fd().as_raw_fd();
+ let encoded = self.context.encode(target);
+ epoll_add(
+ self.epoll_fd.as_fd(),
+ raw_fd,
+ &linux_raw_sys::general::epoll_event {
+ events: event_flags.bits(),
+ data: encoded,
+ },
+ )?;
+ Ok(self.context.decode(encoded))
+ }
+ }
+
+ /// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in
+ /// this `Epoll`.
+ ///
+ /// This sets the events of interest with `target` to `events`.
+ #[doc(alias = "epoll_ctl")]
+ pub fn mod_(
+ &self,
+ target: Ref<'_, Context::Target>,
+ event_flags: EventFlags,
+ ) -> io::Result<()> {
+ let raw_fd = target.as_fd().as_raw_fd();
+ let encoded = self.context.encode(target);
+ // Safety: We're calling `epoll_ctl` via FFI and we know how it
+ // behaves.
+ unsafe {
+ epoll_mod(
+ self.epoll_fd.as_fd(),
+ raw_fd,
+ &linux_raw_sys::general::epoll_event {
+ events: event_flags.bits(),
+ data: encoded,
+ },
+ )
+ }
+ }
+
+ /// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in
+ /// this `Epoll`.
+ ///
+ /// This also returns the owning `Data`.
+ #[doc(alias = "epoll_ctl")]
+ pub fn del(&self, target: Ref<'_, Context::Target>) -> io::Result<Context::Data> {
+ // Safety: We're calling `epoll_ctl` via FFI and we know how it
+ // behaves.
+ unsafe {
+ let raw_fd = target.as_fd().as_raw_fd();
+ epoll_del(self.epoll_fd.as_fd(), raw_fd)?;
+ }
+ Ok(self.context.release(target))
+ }
+
+ /// `epoll_wait(self, events, timeout)`—Waits for registered events of
+ /// interest.
+ ///
+ /// For each event of interest, an element is written to `events`. On
+ /// success, this returns the number of written elements.
+ #[doc(alias = "epoll_wait")]
+ pub fn wait<'context>(
+ &'context self,
+ event_list: &mut EventVec<'context, Context>,
+ timeout: c::c_int,
+ ) -> io::Result<()> {
+ // Safety: We're calling `epoll_wait` via FFI and we know how it
+ // behaves.
+ unsafe {
+ event_list.events.set_len(0);
+ let nfds = epoll_wait(
+ self.epoll_fd.as_fd(),
+ event_list.events[..].as_mut_ptr().cast(),
+ event_list.events.capacity(),
+ timeout,
+ )?;
+ event_list.events.set_len(nfds);
+ event_list.context = &self.context;
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'context, T: AsFd + IntoFd + FromFd> AsRawFd for Epoll<Owning<'context, T>> {
+ fn as_raw_fd(&self) -> RawFd {
+ self.epoll_fd.as_raw_fd()
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'context, T: AsFd + IntoFd + FromFd> IntoRawFd for Epoll<Owning<'context, T>> {
+ fn into_raw_fd(self) -> RawFd {
+ self.epoll_fd.into_raw_fd()
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'context, T: AsFd + IntoFd + FromFd> FromRawFd for Epoll<Owning<'context, T>> {
+ unsafe fn from_raw_fd(fd: RawFd) -> Self {
+ Self {
+ epoll_fd: OwnedFd::from_raw_fd(fd),
+ context: Owning::new(),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'context, T: AsFd + IntoFd + FromFd> AsFd for Epoll<Owning<'context, T>> {
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.epoll_fd.as_fd()
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'context, T: AsFd + IntoFd + FromFd> From<Epoll<Owning<'context, T>>> for OwnedFd {
+ fn from(epoll: Epoll<Owning<'context, T>>) -> Self {
+ epoll.epoll_fd
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'context, T: AsFd + IntoFd + FromFd> From<OwnedFd> for Epoll<Owning<'context, T>> {
+ fn from(fd: OwnedFd) -> Self {
+ Self {
+ epoll_fd: fd,
+ context: Owning::new(),
+ }
+ }
+}
+
+/// An iterator over the `Event`s in an `EventVec`.
+pub struct Iter<'context, Context: self::Context> {
+ iter: core::slice::Iter<'context, Event>,
+ context: *const Context,
+ _phantom: PhantomData<&'context Context>,
+}
+
+impl<'context, Context: self::Context> Iterator for Iter<'context, Context> {
+ type Item = (EventFlags, Ref<'context, Context::Target>);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|event| {
+ // Safety: `self.context` is guaranteed to be valid because we hold
+ // `'context` for it. And we know this event is associated with this
+ // context because `wait` sets both.
+ let decoded = unsafe { (*self.context).decode(event.encoded) };
+
+ (event.event_flags, decoded)
+ })
+ }
+}
+
+/// A record of an event that occurred.
+#[repr(C)]
+#[cfg_attr(target_arch = "x86_64", repr(packed))]
+struct Event {
+ // Match the layout of `linux_raw_sys::general::epoll_event`. We just use a
+ // `u64` instead of the full union; `Context` implementations will simply
+ // need to deal with casting the value into and out of the `u64`
+ // themselves.
+ event_flags: EventFlags,
+ encoded: u64,
+}
+
+/// A vector of `Event`s, plus context for interpreting them.
+pub struct EventVec<'context, Context: self::Context> {
+ events: Vec<Event>,
+ context: *const Context,
+ _phantom: PhantomData<&'context Context>,
+}
+
+impl<'context, Context: self::Context> EventVec<'context, Context> {
+ /// Constructs an `EventVec` with memory for `capacity` `Event`s.
+ #[inline]
+ pub fn with_capacity(capacity: usize) -> Self {
+ Self {
+ events: Vec::with_capacity(capacity),
+ context: null(),
+ _phantom: PhantomData,
+ }
+ }
+
+ /// Returns the current `Event` capacity of this `EventVec`.
+ #[inline]
+ pub fn capacity(&self) -> usize {
+ self.events.capacity()
+ }
+
+ /// Reserves enough memory for at least `additional` more `Event`s.
+ #[inline]
+ pub fn reserve(&mut self, additional: usize) {
+ self.events.reserve(additional);
+ }
+
+ /// Reserves enough memory for exactly `additional` more `Event`s.
+ #[inline]
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.events.reserve_exact(additional);
+ }
+
+ /// Clears all the `Events` out of this `EventVec`.
+ #[inline]
+ pub fn clear(&mut self) {
+ self.events.clear();
+ }
+
+ /// Shrinks the capacity of this `EventVec` as much as possible.
+ #[inline]
+ pub fn shrink_to_fit(&mut self) {
+ self.events.shrink_to_fit();
+ }
+
+ /// Returns an iterator over the `Event`s in this `EventVec`.
+ #[inline]
+ pub fn iter(&self) -> Iter<'_, Context> {
+ Iter {
+ iter: self.events.iter(),
+ context: self.context,
+ _phantom: PhantomData,
+ }
+ }
+
+ /// Returns the number of `Event`s logically contained in this `EventVec`.
+ #[inline]
+ pub fn len(&mut self) -> usize {
+ self.events.len()
+ }
+
+ /// Tests whether this `EventVec` is logically empty.
+ #[inline]
+ pub fn is_empty(&mut self) -> bool {
+ self.events.is_empty()
+ }
+}
+
+impl<'context, Context: self::Context> IntoIterator for &'context EventVec<'context, Context> {
+ type IntoIter = Iter<'context, Context>;
+ type Item = (EventFlags, Ref<'context, Context::Target>);
+
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/io/errno.rs b/vendor/rustix/src/imp/linux_raw/io/errno.rs
new file mode 100644
index 000000000..2637ae02e
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io/errno.rs
@@ -0,0 +1,511 @@
+//! The `rustix` `Errno` type.
+//!
+//! This type holds an OS error code, which conceptually corresponds to an
+//! `errno` value.
+//!
+//! # Safety
+//!
+//! Linux uses error codes in `-4095..0`; we use rustc attributes to describe
+//! this restricted range of values.
+#![allow(unsafe_code)]
+#![cfg_attr(not(rustc_attrs), allow(unused_unsafe))]
+
+use super::super::c;
+use crate::imp::fd::RawFd;
+use crate::imp::reg::{RetNumber, RetReg};
+use crate::io;
+use linux_raw_sys::errno;
+
+/// The error type for `rustix` APIs.
+///
+/// This is similar to `std::io::Error`, but only holds an OS error code,
+/// and no extra error value.
+#[repr(transparent)]
+#[doc(alias = "errno")]
+#[derive(Eq, PartialEq, Hash, Copy, Clone)]
+// Linux returns negated error codes, and we leave them in negated form, so
+// error codes are in `-4095..0`.
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0xf001))]
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xffff))]
+pub struct Errno(u16);
+
+impl Errno {
+ /// Extract an `Errno` value from a `std::io::Error`.
+ ///
+ /// This isn't a `From` conversion because it's expected to be relatively
+ /// uncommon.
+ #[cfg(feature = "std")]
+ #[inline]
+ pub fn from_io_error(io_err: &std::io::Error) -> Option<Self> {
+ io_err.raw_os_error().and_then(|raw| {
+ // `std::io::Error` could theoretically have arbitrary "OS error"
+ // values, so check that they're in Linux's range.
+ if (1..4096).contains(&raw) {
+ Some(Self::from_errno(raw as u32))
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Extract the raw OS error number from this error.
+ #[inline]
+ pub const fn raw_os_error(self) -> i32 {
+ (self.0 as i16 as i32).wrapping_neg()
+ }
+
+ /// Construct an `Errno` from a raw OS error number.
+ #[inline]
+ pub const fn from_raw_os_error(raw: i32) -> Self {
+ Self::from_errno(raw as u32)
+ }
+
+ /// Convert from a C errno value (which is positive) to an `Errno`.
+ const fn from_errno(raw: u32) -> Self {
+ // We store error values in negated form, so that we don't have to negate
+ // them after every syscall.
+ let encoded = raw.wrapping_neg() as u16;
+
+ // TODO: Use Range::contains, once that's `const`.
+ const_assert!(encoded >= 0xf001);
+
+ // Safety: Linux syscalls return negated error values in the range
+ // `-4095..0`, which we just asserted.
+ unsafe { Self(encoded) }
+ }
+}
+
+/// Check for an error from the result of a syscall which encodes a
+/// `c::c_int` on success.
+#[inline]
+pub(in crate::imp) fn try_decode_c_int<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<c::c_int> {
+ if raw.is_in_range(-4095..0) {
+ // Safety: `raw` must be in `-4095..0`, and we just checked that raw is
+ // in that range.
+ return Err(unsafe { Errno(raw.decode_error_code()) });
+ }
+
+ Ok(raw.decode_c_int())
+}
+
+/// Check for an error from the result of a syscall which encodes a
+/// `c::c_uint` on success.
+#[inline]
+pub(in crate::imp) fn try_decode_c_uint<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<c::c_uint> {
+ if raw.is_in_range(-4095..0) {
+ // Safety: `raw` must be in `-4095..0`, and we just checked that raw is
+ // in that range.
+ return Err(unsafe { Errno(raw.decode_error_code()) });
+ }
+
+ Ok(raw.decode_c_uint())
+}
+
+/// Check for an error from the result of a syscall which encodes a `usize` on
+/// success.
+#[inline]
+pub(in crate::imp) fn try_decode_usize<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<usize> {
+ if raw.is_in_range(-4095..0) {
+ // Safety: `raw` must be in `-4095..0`, and we just checked that raw is
+ // in that range.
+ return Err(unsafe { Errno(raw.decode_error_code()) });
+ }
+
+ Ok(raw.decode_usize())
+}
+
+/// Check for an error from the result of a syscall which encodes a
+/// `*mut c_void` on success.
+#[inline]
+pub(in crate::imp) fn try_decode_void_star<Num: RetNumber>(
+ raw: RetReg<Num>,
+) -> io::Result<*mut c::c_void> {
+ if raw.is_in_range(-4095..0) {
+ // Safety: `raw` must be in `-4095..0`, and we just checked that raw is
+ // in that range.
+ return Err(unsafe { Errno(raw.decode_error_code()) });
+ }
+
+ Ok(raw.decode_void_star())
+}
+
+/// Check for an error from the result of a syscall which encodes a
+/// `u64` on success.
+#[cfg(target_pointer_width = "64")]
+#[inline]
+pub(in crate::imp) fn try_decode_u64<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<u64> {
+ if raw.is_in_range(-4095..0) {
+ // Safety: `raw` must be in `-4095..0`, and we just checked that raw is
+ // in that range.
+ return Err(unsafe { Errno(raw.decode_error_code()) });
+ }
+
+ Ok(raw.decode_u64())
+}
+
+/// Check for an error from the result of a syscall which encodes a file
+/// descriptor on success.
+///
+/// # Safety
+///
+/// This must only be used with syscalls which return file descriptors on
+/// success.
+#[inline]
+pub(in crate::imp) unsafe fn try_decode_raw_fd<Num: RetNumber>(
+ raw: RetReg<Num>,
+) -> io::Result<RawFd> {
+ // Instead of using `check_result` here, we just check for negative, since
+ // this function is only used for system calls which return file
+ // descriptors, and this produces smaller code.
+ if raw.is_negative() {
+ debug_assert!(raw.is_in_range(-4095..0));
+
+ // Tell the optimizer that we know the value is in the error range.
+ // This helps it avoid unnecessary integer conversions.
+ #[cfg(core_intrinsics)]
+ {
+ core::intrinsics::assume(raw.is_in_range(-4095..0));
+ }
+
+ return Err(Errno(raw.decode_error_code()));
+ }
+
+ Ok(raw.decode_raw_fd())
+}
+
+/// Check for an error from the result of a syscall which encodes no value on
+/// success. On success, return the unconsumed `raw` value.
+///
+/// # Safety
+///
+/// This must only be used with syscalls which return no value on success.
+#[inline]
+pub(in crate::imp) unsafe fn try_decode_void<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<()> {
+ // Instead of using `check_result` here, we just check for zero, since this
+ // function is only used for system calls which have no other return value,
+ // and this produces smaller code.
+ if raw.is_nonzero() {
+ debug_assert!(raw.is_in_range(-4095..0));
+
+ // Tell the optimizer that we know the value is in the error range.
+ // This helps it avoid unnecessary integer conversions.
+ #[cfg(core_intrinsics)]
+ {
+ core::intrinsics::assume(raw.is_in_range(-4095..0));
+ }
+
+ return Err(Errno(raw.decode_error_code()));
+ }
+
+ raw.decode_void();
+
+ Ok(())
+}
+
+/// Check for an error from the result of a syscall which does not return on
+/// success. On success, return the unconsumed `raw` value.
+///
+/// # Safety
+///
+/// This must only be used with syscalls which do not return on success.
+#[cfg(feature = "runtime")]
+#[inline]
+pub(in crate::imp) unsafe fn try_decode_error<Num: RetNumber>(raw: RetReg<Num>) -> io::Errno {
+ debug_assert!(raw.is_in_range(-4095..0));
+
+ // Tell the optimizer that we know the value is in the error range.
+ // This helps it avoid unnecessary integer conversions.
+ #[cfg(core_intrinsics)]
+ {
+ core::intrinsics::assume(raw.is_in_range(-4095..0));
+ }
+
+ Errno(raw.decode_error_code())
+}
+
+/// Return the contained `usize` value.
+#[cfg(not(debug_assertions))]
+#[inline]
+pub(in crate::imp) fn decode_usize_infallible<Num: RetNumber>(raw: RetReg<Num>) -> usize {
+ raw.decode_usize()
+}
+
+impl Errno {
+ /// `EACCES`
+ #[doc(alias = "ACCES")]
+ pub const ACCESS: Self = Self::from_errno(errno::EACCES);
+ /// `EADDRINUSE`
+ pub const ADDRINUSE: Self = Self::from_errno(errno::EADDRINUSE);
+ /// `EADDRNOTAVAIL`
+ pub const ADDRNOTAVAIL: Self = Self::from_errno(errno::EADDRNOTAVAIL);
+ /// `EADV`
+ pub const ADV: Self = Self::from_errno(errno::EADV);
+ /// `EAFNOSUPPORT`
+ pub const AFNOSUPPORT: Self = Self::from_errno(errno::EAFNOSUPPORT);
+ /// `EAGAIN`
+ pub const AGAIN: Self = Self::from_errno(errno::EAGAIN);
+ /// `EALREADY`
+ pub const ALREADY: Self = Self::from_errno(errno::EALREADY);
+ /// `EBADE`
+ pub const BADE: Self = Self::from_errno(errno::EBADE);
+ /// `EBADF`
+ pub const BADF: Self = Self::from_errno(errno::EBADF);
+ /// `EBADFD`
+ pub const BADFD: Self = Self::from_errno(errno::EBADFD);
+ /// `EBADMSG`
+ pub const BADMSG: Self = Self::from_errno(errno::EBADMSG);
+ /// `EBADR`
+ pub const BADR: Self = Self::from_errno(errno::EBADR);
+ /// `EBADRQC`
+ pub const BADRQC: Self = Self::from_errno(errno::EBADRQC);
+ /// `EBADSLT`
+ pub const BADSLT: Self = Self::from_errno(errno::EBADSLT);
+ /// `EBFONT`
+ pub const BFONT: Self = Self::from_errno(errno::EBFONT);
+ /// `EBUSY`
+ pub const BUSY: Self = Self::from_errno(errno::EBUSY);
+ /// `ECANCELED`
+ pub const CANCELED: Self = Self::from_errno(errno::ECANCELED);
+ /// `ECHILD`
+ pub const CHILD: Self = Self::from_errno(errno::ECHILD);
+ /// `ECHRNG`
+ pub const CHRNG: Self = Self::from_errno(errno::ECHRNG);
+ /// `ECOMM`
+ pub const COMM: Self = Self::from_errno(errno::ECOMM);
+ /// `ECONNABORTED`
+ pub const CONNABORTED: Self = Self::from_errno(errno::ECONNABORTED);
+ /// `ECONNREFUSED`
+ pub const CONNREFUSED: Self = Self::from_errno(errno::ECONNREFUSED);
+ /// `ECONNRESET`
+ pub const CONNRESET: Self = Self::from_errno(errno::ECONNRESET);
+ /// `EDEADLK`
+ pub const DEADLK: Self = Self::from_errno(errno::EDEADLK);
+ /// `EDEADLOCK`
+ pub const DEADLOCK: Self = Self::from_errno(errno::EDEADLOCK);
+ /// `EDESTADDRREQ`
+ pub const DESTADDRREQ: Self = Self::from_errno(errno::EDESTADDRREQ);
+ /// `EDOM`
+ pub const DOM: Self = Self::from_errno(errno::EDOM);
+ /// `EDOTDOT`
+ pub const DOTDOT: Self = Self::from_errno(errno::EDOTDOT);
+ /// `EDQUOT`
+ pub const DQUOT: Self = Self::from_errno(errno::EDQUOT);
+ /// `EEXIST`
+ pub const EXIST: Self = Self::from_errno(errno::EEXIST);
+ /// `EFAULT`
+ pub const FAULT: Self = Self::from_errno(errno::EFAULT);
+ /// `EFBIG`
+ pub const FBIG: Self = Self::from_errno(errno::EFBIG);
+ /// `EHOSTDOWN`
+ pub const HOSTDOWN: Self = Self::from_errno(errno::EHOSTDOWN);
+ /// `EHOSTUNREACH`
+ pub const HOSTUNREACH: Self = Self::from_errno(errno::EHOSTUNREACH);
+ /// `EHWPOISON`
+ pub const HWPOISON: Self = Self::from_errno(errno::EHWPOISON);
+ /// `EIDRM`
+ pub const IDRM: Self = Self::from_errno(errno::EIDRM);
+ /// `EILSEQ`
+ pub const ILSEQ: Self = Self::from_errno(errno::EILSEQ);
+ /// `EINPROGRESS`
+ pub const INPROGRESS: Self = Self::from_errno(errno::EINPROGRESS);
+ /// `EINTR`.
+ ///
+ /// For a convenient way to retry system calls that exit with `INTR`, use
+ /// [`retry_on_intr`].
+ ///
+ /// [`retry_on_intr`]: io::retry_on_intr
+ pub const INTR: Self = Self::from_errno(errno::EINTR);
+ /// `EINVAL`
+ pub const INVAL: Self = Self::from_errno(errno::EINVAL);
+ /// `EIO`
+ pub const IO: Self = Self::from_errno(errno::EIO);
+ /// `EISCONN`
+ pub const ISCONN: Self = Self::from_errno(errno::EISCONN);
+ /// `EISDIR`
+ pub const ISDIR: Self = Self::from_errno(errno::EISDIR);
+ /// `EISNAM`
+ pub const ISNAM: Self = Self::from_errno(errno::EISNAM);
+ /// `EKEYEXPIRED`
+ pub const KEYEXPIRED: Self = Self::from_errno(errno::EKEYEXPIRED);
+ /// `EKEYREJECTED`
+ pub const KEYREJECTED: Self = Self::from_errno(errno::EKEYREJECTED);
+ /// `EKEYREVOKED`
+ pub const KEYREVOKED: Self = Self::from_errno(errno::EKEYREVOKED);
+ /// `EL2HLT`
+ pub const L2HLT: Self = Self::from_errno(errno::EL2HLT);
+ /// `EL2NSYNC`
+ pub const L2NSYNC: Self = Self::from_errno(errno::EL2NSYNC);
+ /// `EL3HLT`
+ pub const L3HLT: Self = Self::from_errno(errno::EL3HLT);
+ /// `EL3RST`
+ pub const L3RST: Self = Self::from_errno(errno::EL3RST);
+ /// `ELIBACC`
+ pub const LIBACC: Self = Self::from_errno(errno::ELIBACC);
+ /// `ELIBBAD`
+ pub const LIBBAD: Self = Self::from_errno(errno::ELIBBAD);
+ /// `ELIBEXEC`
+ pub const LIBEXEC: Self = Self::from_errno(errno::ELIBEXEC);
+ /// `ELIBMAX`
+ pub const LIBMAX: Self = Self::from_errno(errno::ELIBMAX);
+ /// `ELIBSCN`
+ pub const LIBSCN: Self = Self::from_errno(errno::ELIBSCN);
+ /// `ELNRNG`
+ pub const LNRNG: Self = Self::from_errno(errno::ELNRNG);
+ /// `ELOOP`
+ pub const LOOP: Self = Self::from_errno(errno::ELOOP);
+ /// `EMEDIUMTYPE`
+ pub const MEDIUMTYPE: Self = Self::from_errno(errno::EMEDIUMTYPE);
+ /// `EMFILE`
+ pub const MFILE: Self = Self::from_errno(errno::EMFILE);
+ /// `EMLINK`
+ pub const MLINK: Self = Self::from_errno(errno::EMLINK);
+ /// `EMSGSIZE`
+ pub const MSGSIZE: Self = Self::from_errno(errno::EMSGSIZE);
+ /// `EMULTIHOP`
+ pub const MULTIHOP: Self = Self::from_errno(errno::EMULTIHOP);
+ /// `ENAMETOOLONG`
+ pub const NAMETOOLONG: Self = Self::from_errno(errno::ENAMETOOLONG);
+ /// `ENAVAIL`
+ pub const NAVAIL: Self = Self::from_errno(errno::ENAVAIL);
+ /// `ENETDOWN`
+ pub const NETDOWN: Self = Self::from_errno(errno::ENETDOWN);
+ /// `ENETRESET`
+ pub const NETRESET: Self = Self::from_errno(errno::ENETRESET);
+ /// `ENETUNREACH`
+ pub const NETUNREACH: Self = Self::from_errno(errno::ENETUNREACH);
+ /// `ENFILE`
+ pub const NFILE: Self = Self::from_errno(errno::ENFILE);
+ /// `ENOANO`
+ pub const NOANO: Self = Self::from_errno(errno::ENOANO);
+ /// `ENOBUFS`
+ pub const NOBUFS: Self = Self::from_errno(errno::ENOBUFS);
+ /// `ENOCSI`
+ pub const NOCSI: Self = Self::from_errno(errno::ENOCSI);
+ /// `ENODATA`
+ #[doc(alias = "NOATTR")]
+ pub const NODATA: Self = Self::from_errno(errno::ENODATA);
+ /// `ENODEV`
+ pub const NODEV: Self = Self::from_errno(errno::ENODEV);
+ /// `ENOENT`
+ pub const NOENT: Self = Self::from_errno(errno::ENOENT);
+ /// `ENOEXEC`
+ pub const NOEXEC: Self = Self::from_errno(errno::ENOEXEC);
+ /// `ENOKEY`
+ pub const NOKEY: Self = Self::from_errno(errno::ENOKEY);
+ /// `ENOLCK`
+ pub const NOLCK: Self = Self::from_errno(errno::ENOLCK);
+ /// `ENOLINK`
+ pub const NOLINK: Self = Self::from_errno(errno::ENOLINK);
+ /// `ENOMEDIUM`
+ pub const NOMEDIUM: Self = Self::from_errno(errno::ENOMEDIUM);
+ /// `ENOMEM`
+ pub const NOMEM: Self = Self::from_errno(errno::ENOMEM);
+ /// `ENOMSG`
+ pub const NOMSG: Self = Self::from_errno(errno::ENOMSG);
+ /// `ENONET`
+ pub const NONET: Self = Self::from_errno(errno::ENONET);
+ /// `ENOPKG`
+ pub const NOPKG: Self = Self::from_errno(errno::ENOPKG);
+ /// `ENOPROTOOPT`
+ pub const NOPROTOOPT: Self = Self::from_errno(errno::ENOPROTOOPT);
+ /// `ENOSPC`
+ pub const NOSPC: Self = Self::from_errno(errno::ENOSPC);
+ /// `ENOSR`
+ pub const NOSR: Self = Self::from_errno(errno::ENOSR);
+ /// `ENOSTR`
+ pub const NOSTR: Self = Self::from_errno(errno::ENOSTR);
+ /// `ENOSYS`
+ pub const NOSYS: Self = Self::from_errno(errno::ENOSYS);
+ /// `ENOTBLK`
+ pub const NOTBLK: Self = Self::from_errno(errno::ENOTBLK);
+ /// `ENOTCONN`
+ pub const NOTCONN: Self = Self::from_errno(errno::ENOTCONN);
+ /// `ENOTDIR`
+ pub const NOTDIR: Self = Self::from_errno(errno::ENOTDIR);
+ /// `ENOTEMPTY`
+ pub const NOTEMPTY: Self = Self::from_errno(errno::ENOTEMPTY);
+ /// `ENOTNAM`
+ pub const NOTNAM: Self = Self::from_errno(errno::ENOTNAM);
+ /// `ENOTRECOVERABLE`
+ pub const NOTRECOVERABLE: Self = Self::from_errno(errno::ENOTRECOVERABLE);
+ /// `ENOTSOCK`
+ pub const NOTSOCK: Self = Self::from_errno(errno::ENOTSOCK);
+ /// `ENOTSUP`
+ // On Linux, `ENOTSUP` has the same value as `EOPNOTSUPP`.
+ pub const NOTSUP: Self = Self::from_errno(errno::EOPNOTSUPP);
+ /// `ENOTTY`
+ pub const NOTTY: Self = Self::from_errno(errno::ENOTTY);
+ /// `ENOTUNIQ`
+ pub const NOTUNIQ: Self = Self::from_errno(errno::ENOTUNIQ);
+ /// `ENXIO`
+ pub const NXIO: Self = Self::from_errno(errno::ENXIO);
+ /// `EOPNOTSUPP`
+ pub const OPNOTSUPP: Self = Self::from_errno(errno::EOPNOTSUPP);
+ /// `EOVERFLOW`
+ pub const OVERFLOW: Self = Self::from_errno(errno::EOVERFLOW);
+ /// `EOWNERDEAD`
+ pub const OWNERDEAD: Self = Self::from_errno(errno::EOWNERDEAD);
+ /// `EPERM`
+ pub const PERM: Self = Self::from_errno(errno::EPERM);
+ /// `EPFNOSUPPORT`
+ pub const PFNOSUPPORT: Self = Self::from_errno(errno::EPFNOSUPPORT);
+ /// `EPIPE`
+ pub const PIPE: Self = Self::from_errno(errno::EPIPE);
+ /// `EPROTO`
+ pub const PROTO: Self = Self::from_errno(errno::EPROTO);
+ /// `EPROTONOSUPPORT`
+ pub const PROTONOSUPPORT: Self = Self::from_errno(errno::EPROTONOSUPPORT);
+ /// `EPROTOTYPE`
+ pub const PROTOTYPE: Self = Self::from_errno(errno::EPROTOTYPE);
+ /// `ERANGE`
+ pub const RANGE: Self = Self::from_errno(errno::ERANGE);
+ /// `EREMCHG`
+ pub const REMCHG: Self = Self::from_errno(errno::EREMCHG);
+ /// `EREMOTE`
+ pub const REMOTE: Self = Self::from_errno(errno::EREMOTE);
+ /// `EREMOTEIO`
+ pub const REMOTEIO: Self = Self::from_errno(errno::EREMOTEIO);
+ /// `ERESTART`
+ pub const RESTART: Self = Self::from_errno(errno::ERESTART);
+ /// `ERFKILL`
+ pub const RFKILL: Self = Self::from_errno(errno::ERFKILL);
+ /// `EROFS`
+ pub const ROFS: Self = Self::from_errno(errno::EROFS);
+ /// `ESHUTDOWN`
+ pub const SHUTDOWN: Self = Self::from_errno(errno::ESHUTDOWN);
+ /// `ESOCKTNOSUPPORT`
+ pub const SOCKTNOSUPPORT: Self = Self::from_errno(errno::ESOCKTNOSUPPORT);
+ /// `ESPIPE`
+ pub const SPIPE: Self = Self::from_errno(errno::ESPIPE);
+ /// `ESRCH`
+ pub const SRCH: Self = Self::from_errno(errno::ESRCH);
+ /// `ESRMNT`
+ pub const SRMNT: Self = Self::from_errno(errno::ESRMNT);
+ /// `ESTALE`
+ pub const STALE: Self = Self::from_errno(errno::ESTALE);
+ /// `ESTRPIPE`
+ pub const STRPIPE: Self = Self::from_errno(errno::ESTRPIPE);
+ /// `ETIME`
+ pub const TIME: Self = Self::from_errno(errno::ETIME);
+ /// `ETIMEDOUT`
+ pub const TIMEDOUT: Self = Self::from_errno(errno::ETIMEDOUT);
+ /// `E2BIG`
+ #[doc(alias = "2BIG")]
+ pub const TOOBIG: Self = Self::from_errno(errno::E2BIG);
+ /// `ETOOMANYREFS`
+ pub const TOOMANYREFS: Self = Self::from_errno(errno::ETOOMANYREFS);
+ /// `ETXTBSY`
+ pub const TXTBSY: Self = Self::from_errno(errno::ETXTBSY);
+ /// `EUCLEAN`
+ pub const UCLEAN: Self = Self::from_errno(errno::EUCLEAN);
+ /// `EUNATCH`
+ pub const UNATCH: Self = Self::from_errno(errno::EUNATCH);
+ /// `EUSERS`
+ pub const USERS: Self = Self::from_errno(errno::EUSERS);
+ /// `EWOULDBLOCK`
+ pub const WOULDBLOCK: Self = Self::from_errno(errno::EWOULDBLOCK);
+ /// `EXDEV`
+ pub const XDEV: Self = Self::from_errno(errno::EXDEV);
+ /// `EXFULL`
+ pub const XFULL: Self = Self::from_errno(errno::EXFULL);
+}
diff --git a/vendor/rustix/src/imp/linux_raw/io/io_slice.rs b/vendor/rustix/src/imp/linux_raw/io/io_slice.rs
new file mode 100644
index 000000000..fc8e64698
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io/io_slice.rs
@@ -0,0 +1,98 @@
+//! The following is derived from Rust's
+//! library/std/src/sys/unix/io.rs
+//! dca3f1b786efd27be3b325ed1e01e247aa589c3b.
+
+#![allow(unsafe_code)]
+use super::super::c;
+use core::marker::PhantomData;
+use core::slice;
+use linux_raw_sys::general::__kernel_size_t;
+
+/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSlice.html>
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub struct IoSlice<'a> {
+ vec: c::iovec,
+ _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+ /// <https://doc.rust-lang.org/nightly/std/io/struct.IoSlice.html#method.new>
+ #[inline]
+ pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+ IoSlice {
+ vec: c::iovec {
+ iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void,
+ iov_len: buf.len() as _,
+ },
+ _p: PhantomData,
+ }
+ }
+
+ /// <https://doc.rust-lang.org/nightly/std/io/struct.IoSlice.html#method.advance>
+ #[inline]
+ pub fn advance(&mut self, n: usize) {
+ if self.vec.iov_len < n as _ {
+ panic!("advancing IoSlice beyond its length");
+ }
+
+ unsafe {
+ self.vec.iov_len -= n as __kernel_size_t;
+ self.vec.iov_base = self.vec.iov_base.add(n);
+ }
+ }
+
+ /// <https://doc.rust-lang.org/nightly/std/io/struct.IoSlice.html#method.as_slice>
+ #[inline]
+ pub fn as_slice(&self) -> &[u8] {
+ unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) }
+ }
+}
+
+/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html>
+#[repr(transparent)]
+pub struct IoSliceMut<'a> {
+ vec: c::iovec,
+ _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+ /// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html#method.new>
+ #[inline]
+ pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+ IoSliceMut {
+ vec: c::iovec {
+ iov_base: buf.as_mut_ptr() as *mut c::c_void,
+ iov_len: buf.len() as _,
+ },
+ _p: PhantomData,
+ }
+ }
+
+ /// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html#method.advance>
+ #[inline]
+ pub fn advance(&mut self, n: usize) {
+ if self.vec.iov_len < n as _ {
+ panic!("advancing IoSliceMut beyond its length");
+ }
+
+ unsafe {
+ self.vec.iov_len -= n as __kernel_size_t;
+ self.vec.iov_base = self.vec.iov_base.add(n);
+ }
+ }
+
+ /// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html#method.as_slice>
+ #[inline]
+ pub fn as_slice(&self) -> &[u8] {
+ unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) }
+ }
+
+ /// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html#method.as_slice_mut>
+ #[inline]
+ pub fn as_mut_slice(&mut self) -> &mut [u8] {
+ unsafe {
+ slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len as usize)
+ }
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/io/mod.rs b/vendor/rustix/src/imp/linux_raw/io/mod.rs
new file mode 100644
index 000000000..f5c2bf3c0
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io/mod.rs
@@ -0,0 +1,7 @@
+pub mod epoll;
+pub(crate) mod errno;
+#[cfg(not(feature = "std"))]
+pub(crate) mod io_slice;
+pub(crate) mod poll_fd;
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/linux_raw/io/poll_fd.rs b/vendor/rustix/src/imp/linux_raw/io/poll_fd.rs
new file mode 100644
index 000000000..252358331
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io/poll_fd.rs
@@ -0,0 +1,93 @@
+use crate::fd::{AsFd, BorrowedFd};
+use bitflags::bitflags;
+
+bitflags! {
+ /// `POLL*` flags for use with [`poll`].
+ ///
+ /// [`poll`]: crate::io::poll
+ pub struct PollFlags: u16 {
+ /// `POLLIN`
+ const IN = linux_raw_sys::general::POLLIN as u16;
+ /// `POLLPRI`
+ const PRI = linux_raw_sys::general::POLLPRI as u16;
+ /// `POLLOUT`
+ const OUT = linux_raw_sys::general::POLLOUT as u16;
+ /// `POLLRDNORM`
+ const RDNORM = linux_raw_sys::general::POLLRDNORM as u16;
+ /// `POLLWRNORM`
+ const WRNORM = linux_raw_sys::general::POLLWRNORM as u16;
+ /// `POLLRDBAND`
+ const RDBAND = linux_raw_sys::general::POLLRDBAND as u16;
+ /// `POLLWRBAND`
+ const WRBAND = linux_raw_sys::general::POLLWRBAND as u16;
+ /// `POLLERR`
+ const ERR = linux_raw_sys::general::POLLERR as u16;
+ /// `POLLHUP`
+ const HUP = linux_raw_sys::general::POLLHUP as u16;
+ /// `POLLNVAL`
+ const NVAL = linux_raw_sys::general::POLLNVAL as u16;
+ /// `POLLRDHUP`
+ const RDHUP = linux_raw_sys::general::POLLRDHUP as u16;
+ }
+}
+
+/// `struct pollfd`—File descriptor and flags for use with [`poll`].
+///
+/// [`poll`]: crate::io::poll
+#[doc(alias = "pollfd")]
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct PollFd<'fd> {
+ pub(crate) fd: BorrowedFd<'fd>,
+ pub(crate) events: u16,
+ pub(crate) revents: u16,
+}
+
+impl<'fd> PollFd<'fd> {
+ /// Constructs a new `PollFd` holding `fd` and `events`.
+ #[inline]
+ pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> Self {
+ Self::from_borrowed_fd(fd.as_fd(), events)
+ }
+
+ /// Sets the contained file descriptor to `fd`.
+ #[inline]
+ pub fn set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd) {
+ self.fd = fd.as_fd();
+ }
+
+ /// Clears the ready events.
+ #[inline]
+ pub fn clear_revents(&mut self) {
+ self.revents = 0;
+ }
+
+ /// Constructs a new `PollFd` holding `fd` and `events`.
+ ///
+ /// This is the same as `new`, but can be used to avoid borrowing the
+ /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd`
+ /// is a temporary.
+ #[inline]
+ pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self {
+ Self {
+ fd,
+ events: events.bits(),
+ revents: 0,
+ }
+ }
+
+ /// Returns the ready events.
+ #[inline]
+ pub fn revents(&self) -> PollFlags {
+ // Use `unwrap()` here because in theory we know we know all the bits
+ // the OS might set here, but OS's have added extensions in the past.
+ PollFlags::from_bits(self.revents).unwrap()
+ }
+}
+
+impl<'fd> AsFd for PollFd<'fd> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.fd.as_fd()
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/io/syscalls.rs b/vendor/rustix/src/imp/linux_raw/io/syscalls.rs
new file mode 100644
index 000000000..7857859de
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io/syscalls.rs
@@ -0,0 +1,560 @@
+//! linux_raw syscalls supporting `rustix::io`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::c;
+#[cfg(target_pointer_width = "64")]
+use super::super::conv::loff_t_from_u64;
+use super::super::conv::{
+ by_ref, c_int, c_uint, pass_usize, raw_fd, ret, ret_discarded_fd, ret_owned_fd, ret_usize,
+ slice, slice_mut, zero,
+};
+#[cfg(target_pointer_width = "32")]
+use super::super::conv::{hi, lo};
+use crate::fd::{AsFd, BorrowedFd, RawFd};
+use crate::io::{
+ self, epoll, DupFlags, EventfdFlags, IoSlice, IoSliceMut, OwnedFd, PipeFlags, PollFd,
+ ReadWriteFlags,
+};
+#[cfg(feature = "net")]
+use crate::net::{RecvFlags, SendFlags};
+use core::cmp;
+use core::mem::MaybeUninit;
+use linux_raw_sys::general::{
+ epoll_event, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD, UIO_MAXIOV,
+};
+use linux_raw_sys::ioctl::{BLKPBSZGET, BLKSSZGET, FIONBIO, FIONREAD, TIOCEXCL, TIOCNXCL};
+#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
+use {
+ super::super::conv::{opt_ref, size_of},
+ linux_raw_sys::general::{__kernel_timespec, sigset_t},
+};
+
+#[inline]
+pub(crate) fn read(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+
+ unsafe { ret_usize(syscall!(__NR_read, fd, buf_addr_mut, buf_len)) }
+}
+
+#[inline]
+pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], pos: u64) -> io::Result<usize> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+
+ // <https://github.com/torvalds/linux/blob/fcadab740480e0e0e9fa9bd272acd409884d431a/arch/arm64/kernel/sys32.c#L75>
+ #[cfg(all(
+ target_pointer_width = "32",
+ any(target_arch = "arm", target_arch = "mips", target_arch = "power"),
+ ))]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_pread64,
+ fd,
+ buf_addr_mut,
+ buf_len,
+ zero(),
+ hi(pos),
+ lo(pos)
+ ))
+ }
+ #[cfg(all(
+ target_pointer_width = "32",
+ not(any(target_arch = "arm", target_arch = "mips", target_arch = "power")),
+ ))]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_pread64,
+ fd,
+ buf_addr_mut,
+ buf_len,
+ hi(pos),
+ lo(pos)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_pread64,
+ fd,
+ buf_addr_mut,
+ buf_len,
+ loff_t_from_u64(pos)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+ let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]);
+
+ unsafe { ret_usize(syscall!(__NR_readv, fd, bufs_addr, bufs_len)) }
+}
+
+#[inline]
+pub(crate) fn preadv(
+ fd: BorrowedFd<'_>,
+ bufs: &mut [IoSliceMut<'_>],
+ pos: u64,
+) -> io::Result<usize> {
+ let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]);
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_preadv,
+ fd,
+ bufs_addr,
+ bufs_len,
+ hi(pos),
+ lo(pos)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_preadv,
+ fd,
+ bufs_addr,
+ bufs_len,
+ loff_t_from_u64(pos)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn preadv2(
+ fd: BorrowedFd<'_>,
+ bufs: &mut [IoSliceMut<'_>],
+ pos: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]);
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_preadv2,
+ fd,
+ bufs_addr,
+ bufs_len,
+ hi(pos),
+ lo(pos),
+ flags
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_preadv2,
+ fd,
+ bufs_addr,
+ bufs_len,
+ loff_t_from_u64(pos),
+ flags
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn write(fd: BorrowedFd<'_>, buf: &[u8]) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ unsafe { ret_usize(syscall_readonly!(__NR_write, fd, buf_addr, buf_len)) }
+}
+
+#[inline]
+pub(crate) fn pwrite(fd: BorrowedFd<'_>, buf: &[u8], pos: u64) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ // <https://github.com/torvalds/linux/blob/fcadab740480e0e0e9fa9bd272acd409884d431a/arch/arm64/kernel/sys32.c#L81-L83>
+ #[cfg(all(
+ target_pointer_width = "32",
+ any(target_arch = "arm", target_arch = "mips", target_arch = "power"),
+ ))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_pwrite64,
+ fd,
+ buf_addr,
+ buf_len,
+ zero(),
+ hi(pos),
+ lo(pos)
+ ))
+ }
+ #[cfg(all(
+ target_pointer_width = "32",
+ not(any(target_arch = "arm", target_arch = "mips", target_arch = "power")),
+ ))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_pwrite64,
+ fd,
+ buf_addr,
+ buf_len,
+ hi(pos),
+ lo(pos)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_pwrite64,
+ fd,
+ buf_addr,
+ buf_len,
+ loff_t_from_u64(pos)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn writev(fd: BorrowedFd<'_>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+ let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]);
+
+ unsafe { ret_usize(syscall_readonly!(__NR_writev, fd, bufs_addr, bufs_len)) }
+}
+
+#[inline]
+pub(crate) fn pwritev(fd: BorrowedFd<'_>, bufs: &[IoSlice<'_>], pos: u64) -> io::Result<usize> {
+ let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]);
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_pwritev,
+ fd,
+ bufs_addr,
+ bufs_len,
+ hi(pos),
+ lo(pos)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_pwritev,
+ fd,
+ bufs_addr,
+ bufs_len,
+ loff_t_from_u64(pos)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn pwritev2(
+ fd: BorrowedFd<'_>,
+ bufs: &[IoSlice<'_>],
+ pos: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]);
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_pwritev2,
+ fd,
+ bufs_addr,
+ bufs_len,
+ hi(pos),
+ lo(pos),
+ flags
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_pwritev2,
+ fd,
+ bufs_addr,
+ bufs_len,
+ loff_t_from_u64(pos),
+ flags
+ ))
+ }
+}
+
+/// The maximum number of buffers that can be passed into a vectored I/O system
+/// call on the current platform.
+const fn max_iov() -> usize {
+ UIO_MAXIOV as usize
+}
+
+#[inline]
+pub(crate) unsafe fn close(fd: RawFd) {
+ // See the documentation for [`io::close`] for why errors are ignored.
+ syscall_readonly!(__NR_close, raw_fd(fd)).decode_void();
+}
+
+#[inline]
+pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(syscall_readonly!(__NR_eventfd2, c_uint(initval), flags)) }
+}
+
+#[inline]
+pub(crate) fn ioctl_fionread(fd: BorrowedFd<'_>) -> io::Result<u64> {
+ unsafe {
+ let mut result = MaybeUninit::<c::c_int>::uninit();
+ ret(syscall!(__NR_ioctl, fd, c_uint(FIONREAD), &mut result))
+ .map(|()| result.assume_init() as u64)
+ }
+}
+
+#[inline]
+pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ unsafe {
+ let data = c::c_int::from(value);
+ ret(syscall_readonly!(
+ __NR_ioctl,
+ fd,
+ c_uint(FIONBIO),
+ by_ref(&data)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn ioctl_tiocexcl(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TIOCEXCL))) }
+}
+
+#[inline]
+pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TIOCNXCL))) }
+}
+
+#[inline]
+pub(crate) fn ioctl_blksszget(fd: BorrowedFd) -> io::Result<u32> {
+ let mut result = MaybeUninit::<c::c_uint>::uninit();
+ unsafe {
+ ret(syscall!(__NR_ioctl, fd, c_uint(BLKSSZGET), &mut result))
+ .map(|()| result.assume_init() as u32)
+ }
+}
+
+#[inline]
+pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result<u32> {
+ let mut result = MaybeUninit::<c::c_uint>::uninit();
+ unsafe {
+ ret(syscall!(__NR_ioctl, fd, c_uint(BLKPBSZGET), &mut result))
+ .map(|()| result.assume_init() as u32)
+ }
+}
+
+#[cfg(feature = "net")]
+pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
+ let (mut read, mut write) = crate::fs::fd::_is_file_read_write(fd)?;
+ let mut not_socket = false;
+ if read {
+ // Do a `recv` with `PEEK` and `DONTWAIT` for 1 byte. A 0 indicates
+ // the read side is shut down; an `EWOULDBLOCK` indicates the read
+ // side is still open.
+ //
+ // TODO: This code would benefit from having a better way to read into
+ // uninitialized memory.
+ let mut buf = [0];
+ match super::super::net::syscalls::recv(fd, &mut buf, RecvFlags::PEEK | RecvFlags::DONTWAIT)
+ {
+ Ok(0) => read = false,
+ Err(err) => {
+ #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK`
+ match err {
+ io::Errno::AGAIN | io::Errno::WOULDBLOCK => (),
+ io::Errno::NOTSOCK => not_socket = true,
+ _ => return Err(err),
+ }
+ }
+ Ok(_) => (),
+ }
+ }
+ if write && !not_socket {
+ // Do a `send` with `DONTWAIT` for 0 bytes. An `EPIPE` indicates
+ // the write side is shut down.
+ #[allow(unreachable_patterns)] // `EAGAIN` equals `EWOULDBLOCK`
+ match super::super::net::syscalls::send(fd, &[], SendFlags::DONTWAIT) {
+ // TODO or-patterns when we don't need 1.51
+ Err(io::Errno::AGAIN) => (),
+ Err(io::Errno::WOULDBLOCK) => (),
+ Err(io::Errno::NOTSOCK) => (),
+ Err(io::Errno::PIPE) => write = false,
+ Err(err) => return Err(err),
+ Ok(_) => (),
+ }
+ }
+ Ok((read, write))
+}
+
+#[inline]
+pub(crate) fn dup(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(syscall_readonly!(__NR_dup, fd)) }
+}
+
+#[inline]
+pub(crate) fn dup2(fd: BorrowedFd<'_>, new: &mut OwnedFd) -> io::Result<()> {
+ #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
+ {
+ // We don't need to worry about the difference between `dup2` and
+ // `dup3` when the file descriptors are equal because we have an
+ // `&mut OwnedFd` which means `fd` doesn't alias it.
+ dup3(fd, new, DupFlags::empty())
+ }
+
+ #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
+ unsafe {
+ ret_discarded_fd(syscall_readonly!(__NR_dup2, fd, new.as_fd()))
+ }
+}
+
+#[inline]
+pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()> {
+ unsafe { ret_discarded_fd(syscall_readonly!(__NR_dup3, fd, new.as_fd(), flags)) }
+}
+
+#[inline]
+pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> {
+ unsafe {
+ let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(syscall!(__NR_pipe2, &mut result, flags))?;
+ let [p0, p1] = result.assume_init();
+ Ok((p0, p1))
+ }
+}
+
+#[inline]
+pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> {
+ // aarch64 and risc64 omit `__NR_pipe`. On mips, `__NR_pipe` uses a special
+ // calling convention, but using it is not worth complicating our syscall
+ // wrapping infrastructure at this time.
+ #[cfg(any(
+ target_arch = "aarch64",
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ ))]
+ {
+ pipe_with(PipeFlags::empty())
+ }
+ #[cfg(not(any(
+ target_arch = "aarch64",
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ )))]
+ unsafe {
+ let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(syscall!(__NR_pipe, &mut result))?;
+ let [p0, p1] = result.assume_init();
+ Ok((p0, p1))
+ }
+}
+
+#[inline]
+pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
+ let (fds_addr_mut, fds_len) = slice_mut(fds);
+
+ #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
+ unsafe {
+ let timeout = if timeout >= 0 {
+ Some(__kernel_timespec {
+ tv_sec: (timeout as i64) / 1000,
+ tv_nsec: (timeout as i64) % 1000 * 1_000_000,
+ })
+ } else {
+ None
+ };
+ ret_usize(syscall!(
+ __NR_ppoll,
+ fds_addr_mut,
+ fds_len,
+ opt_ref(timeout.as_ref()),
+ zero(),
+ size_of::<sigset_t, _>()
+ ))
+ }
+ #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
+ unsafe {
+ ret_usize(syscall!(__NR_poll, fds_addr_mut, fds_len, c_int(timeout)))
+ }
+}
+
+#[inline]
+pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(syscall_readonly!(__NR_epoll_create1, flags)) }
+}
+
+#[inline]
+pub(crate) unsafe fn epoll_add(
+ epfd: BorrowedFd<'_>,
+ fd: c::c_int,
+ event: &epoll_event,
+) -> io::Result<()> {
+ ret(syscall_readonly!(
+ __NR_epoll_ctl,
+ epfd,
+ c_uint(EPOLL_CTL_ADD),
+ raw_fd(fd),
+ by_ref(event)
+ ))
+}
+
+#[inline]
+pub(crate) unsafe fn epoll_mod(
+ epfd: BorrowedFd<'_>,
+ fd: c::c_int,
+ event: &epoll_event,
+) -> io::Result<()> {
+ ret(syscall_readonly!(
+ __NR_epoll_ctl,
+ epfd,
+ c_uint(EPOLL_CTL_MOD),
+ raw_fd(fd),
+ by_ref(event)
+ ))
+}
+
+#[inline]
+pub(crate) unsafe fn epoll_del(epfd: BorrowedFd<'_>, fd: c::c_int) -> io::Result<()> {
+ ret(syscall_readonly!(
+ __NR_epoll_ctl,
+ epfd,
+ c_uint(EPOLL_CTL_DEL),
+ raw_fd(fd),
+ zero()
+ ))
+}
+
+#[inline]
+pub(crate) fn epoll_wait(
+ epfd: BorrowedFd<'_>,
+ events: *mut epoll_event,
+ num_events: usize,
+ timeout: c::c_int,
+) -> io::Result<usize> {
+ #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_epoll_wait,
+ epfd,
+ events,
+ pass_usize(num_events),
+ c_int(timeout)
+ ))
+ }
+ #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_epoll_pwait,
+ epfd,
+ events,
+ pass_usize(num_events),
+ c_int(timeout),
+ zero()
+ ))
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/io/types.rs b/vendor/rustix/src/imp/linux_raw/io/types.rs
new file mode 100644
index 000000000..282a23aa1
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io/types.rs
@@ -0,0 +1,67 @@
+use super::super::c;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `RWF_*` constants for use with [`preadv2`] and [`pwritev2`].
+ ///
+ /// [`preadv2`]: crate::io::preadv2
+ /// [`pwritev2`]: crate::io::pwritev
+ pub struct ReadWriteFlags: c::c_uint {
+ /// `RWF_DSYNC` (since Linux 4.7)
+ const DSYNC = linux_raw_sys::general::RWF_DSYNC;
+ /// `RWF_HIPRI` (since Linux 4.6)
+ const HIPRI = linux_raw_sys::general::RWF_HIPRI;
+ /// `RWF_SYNC` (since Linux 4.7)
+ const SYNC = linux_raw_sys::general::RWF_SYNC;
+ /// `RWF_NOWAIT` (since Linux 4.14)
+ const NOWAIT = linux_raw_sys::general::RWF_NOWAIT;
+ /// `RWF_APPEND` (since Linux 4.16)
+ const APPEND = linux_raw_sys::general::RWF_APPEND;
+ }
+}
+
+bitflags! {
+ /// `O_*` constants for use with [`dup2`].
+ ///
+ /// [`dup2`]: crate::io::dup2
+ pub struct DupFlags: c::c_uint {
+ /// `O_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::O_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `O_*` constants for use with [`pipe_with`].
+ ///
+ /// [`pipe_with`]: crate::io::pipe_with
+ pub struct PipeFlags: c::c_uint {
+ /// `O_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::O_CLOEXEC;
+ /// `O_DIRECT`
+ const DIRECT = linux_raw_sys::general::O_DIRECT;
+ /// `O_NONBLOCK`
+ const NONBLOCK = linux_raw_sys::general::O_NONBLOCK;
+ }
+}
+
+bitflags! {
+ /// `EFD_*` flags for use with [`eventfd`].
+ ///
+ /// [`eventfd`]: crate::io::eventfd
+ pub struct EventfdFlags: c::c_uint {
+ /// `EFD_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::EFD_CLOEXEC;
+ /// `EFD_NONBLOCK`
+ const NONBLOCK = linux_raw_sys::general::EFD_NONBLOCK;
+ /// `EFD_SEMAPHORE`
+ const SEMAPHORE = linux_raw_sys::general::EFD_SEMAPHORE;
+ }
+}
+
+/// `PIPE_BUF`—The maximum size of a write to a pipe guaranteed to be atomic.
+pub const PIPE_BUF: usize = linux_raw_sys::general::PIPE_BUF as usize;
+
+pub(crate) const AT_FDCWD: c::c_int = linux_raw_sys::general::AT_FDCWD;
+pub(crate) const STDIN_FILENO: c::c_uint = linux_raw_sys::general::STDIN_FILENO;
+pub(crate) const STDOUT_FILENO: c::c_uint = linux_raw_sys::general::STDOUT_FILENO;
+pub(crate) const STDERR_FILENO: c::c_uint = linux_raw_sys::general::STDERR_FILENO;
diff --git a/vendor/rustix/src/imp/linux_raw/io_uring/mod.rs b/vendor/rustix/src/imp/linux_raw/io_uring/mod.rs
new file mode 100644
index 000000000..ef944f04d
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io_uring/mod.rs
@@ -0,0 +1 @@
+pub(crate) mod syscalls;
diff --git a/vendor/rustix/src/imp/linux_raw/io_uring/syscalls.rs b/vendor/rustix/src/imp/linux_raw/io_uring/syscalls.rs
new file mode 100644
index 000000000..812568efc
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/io_uring/syscalls.rs
@@ -0,0 +1,64 @@
+//! linux_raw syscalls supporting `rustix::io_uring`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp::syscalls` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::conv::{by_mut, c_uint, pass_usize, ret, ret_c_uint, ret_owned_fd};
+use crate::fd::BorrowedFd;
+use crate::io;
+use crate::io::OwnedFd;
+use crate::io_uring::{io_uring_params, IoringEnterFlags, IoringRegisterOp};
+use core::ffi::c_void;
+
+#[inline]
+pub(crate) fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd> {
+ unsafe {
+ ret_owned_fd(syscall!(
+ __NR_io_uring_setup,
+ c_uint(entries),
+ by_mut(params)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) unsafe fn io_uring_register(
+ fd: BorrowedFd<'_>,
+ opcode: IoringRegisterOp,
+ arg: *const c_void,
+ nr_args: u32,
+) -> io::Result<()> {
+ ret(syscall_readonly!(
+ __NR_io_uring_register,
+ fd,
+ c_uint(opcode as u32),
+ arg,
+ c_uint(nr_args)
+ ))
+}
+
+#[inline]
+pub(crate) unsafe fn io_uring_enter(
+ fd: BorrowedFd<'_>,
+ to_submit: u32,
+ min_complete: u32,
+ flags: IoringEnterFlags,
+ arg: *const c_void,
+ size: usize,
+) -> io::Result<u32> {
+ // This is not `_readonly` because `io_uring_enter` waits for I/O to
+ // complete, and I/O could involve writing to memory buffers, which
+ // could be a side effect depended on by the caller.
+ ret_c_uint(syscall!(
+ __NR_io_uring_enter,
+ fd,
+ c_uint(to_submit),
+ c_uint(min_complete),
+ flags,
+ arg,
+ pass_usize(size)
+ ))
+}
diff --git a/vendor/rustix/src/imp/linux_raw/mm/mod.rs b/vendor/rustix/src/imp/linux_raw/mm/mod.rs
new file mode 100644
index 000000000..1e0181a99
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/mm/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/linux_raw/mm/syscalls.rs b/vendor/rustix/src/imp/linux_raw/mm/syscalls.rs
new file mode 100644
index 000000000..8b230be3d
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/mm/syscalls.rs
@@ -0,0 +1,214 @@
+//! linux_raw syscalls supporting `rustix::io`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::c;
+#[cfg(target_pointer_width = "64")]
+use super::super::conv::loff_t_from_u64;
+use super::super::conv::{c_uint, no_fd, pass_usize, ret, ret_owned_fd, ret_void_star};
+use super::types::{
+ Advice, MapFlags, MlockFlags, MprotectFlags, MremapFlags, MsyncFlags, ProtFlags,
+ UserfaultfdFlags,
+};
+use crate::fd::BorrowedFd;
+use crate::io::{self, OwnedFd};
+#[cfg(target_pointer_width = "32")]
+use core::convert::TryInto;
+use linux_raw_sys::general::MAP_ANONYMOUS;
+
+#[inline]
+pub(crate) fn madvise(addr: *mut c::c_void, len: usize, advice: Advice) -> io::Result<()> {
+ unsafe {
+ ret(syscall!(
+ __NR_madvise,
+ addr,
+ pass_usize(len),
+ c_uint(advice as c::c_uint)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) unsafe fn msync(addr: *mut c::c_void, len: usize, flags: MsyncFlags) -> io::Result<()> {
+ ret(syscall!(__NR_msync, addr, pass_usize(len), flags))
+}
+
+/// # Safety
+///
+/// `mmap` is primarily unsafe due to the `addr` parameter, as anything working
+/// with memory pointed to by raw pointers is unsafe.
+#[inline]
+pub(crate) unsafe fn mmap(
+ addr: *mut c::c_void,
+ length: usize,
+ prot: ProtFlags,
+ flags: MapFlags,
+ fd: BorrowedFd<'_>,
+ offset: u64,
+) -> io::Result<*mut c::c_void> {
+ #[cfg(target_pointer_width = "32")]
+ {
+ ret_void_star(syscall!(
+ __NR_mmap2,
+ addr,
+ pass_usize(length),
+ prot,
+ flags,
+ fd,
+ (offset / 4096)
+ .try_into()
+ .map(|scaled_offset| pass_usize(scaled_offset))
+ .map_err(|_| io::Errno::INVAL)?
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ {
+ ret_void_star(syscall!(
+ __NR_mmap,
+ addr,
+ pass_usize(length),
+ prot,
+ flags,
+ fd,
+ loff_t_from_u64(offset)
+ ))
+ }
+}
+
+/// # Safety
+///
+/// `mmap` is primarily unsafe due to the `addr` parameter, as anything working
+/// with memory pointed to by raw pointers is unsafe.
+#[inline]
+pub(crate) unsafe fn mmap_anonymous(
+ addr: *mut c::c_void,
+ length: usize,
+ prot: ProtFlags,
+ flags: MapFlags,
+) -> io::Result<*mut c::c_void> {
+ #[cfg(target_pointer_width = "32")]
+ {
+ ret_void_star(syscall!(
+ __NR_mmap2,
+ addr,
+ pass_usize(length),
+ prot,
+ c_uint(flags.bits() | MAP_ANONYMOUS),
+ no_fd(),
+ pass_usize(0)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ {
+ ret_void_star(syscall!(
+ __NR_mmap,
+ addr,
+ pass_usize(length),
+ prot,
+ c_uint(flags.bits() | MAP_ANONYMOUS),
+ no_fd(),
+ loff_t_from_u64(0)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) unsafe fn mprotect(
+ ptr: *mut c::c_void,
+ len: usize,
+ flags: MprotectFlags,
+) -> io::Result<()> {
+ ret(syscall!(__NR_mprotect, ptr, pass_usize(len), flags))
+}
+
+/// # Safety
+///
+/// `munmap` is primarily unsafe due to the `addr` parameter, as anything
+/// working with memory pointed to by raw pointers is unsafe.
+#[inline]
+pub(crate) unsafe fn munmap(addr: *mut c::c_void, length: usize) -> io::Result<()> {
+ ret(syscall!(__NR_munmap, addr, pass_usize(length)))
+}
+
+/// # Safety
+///
+/// `mremap` is primarily unsafe due to the `old_address` parameter, as
+/// anything working with memory pointed to by raw pointers is unsafe.
+#[inline]
+pub(crate) unsafe fn mremap(
+ old_address: *mut c::c_void,
+ old_size: usize,
+ new_size: usize,
+ flags: MremapFlags,
+) -> io::Result<*mut c::c_void> {
+ ret_void_star(syscall!(
+ __NR_mremap,
+ old_address,
+ pass_usize(old_size),
+ pass_usize(new_size),
+ flags
+ ))
+}
+
+/// # Safety
+///
+/// `mremap_fixed` is primarily unsafe due to the `old_address` and
+/// `new_address` parameters, as anything working with memory pointed to by raw
+/// pointers is unsafe.
+#[inline]
+pub(crate) unsafe fn mremap_fixed(
+ old_address: *mut c::c_void,
+ old_size: usize,
+ new_size: usize,
+ flags: MremapFlags,
+ new_address: *mut c::c_void,
+) -> io::Result<*mut c::c_void> {
+ ret_void_star(syscall!(
+ __NR_mremap,
+ old_address,
+ pass_usize(old_size),
+ pass_usize(new_size),
+ flags,
+ new_address
+ ))
+}
+
+/// # Safety
+///
+/// `mlock` operates on raw pointers and may round out to the nearest page
+/// boundaries.
+#[inline]
+pub(crate) unsafe fn mlock(addr: *mut c::c_void, length: usize) -> io::Result<()> {
+ ret(syscall!(__NR_mlock, addr, pass_usize(length)))
+}
+
+/// # Safety
+///
+/// `mlock_with` operates on raw pointers and may round out to the nearest page
+/// boundaries.
+#[inline]
+pub(crate) unsafe fn mlock_with(
+ addr: *mut c::c_void,
+ length: usize,
+ flags: MlockFlags,
+) -> io::Result<()> {
+ ret(syscall!(__NR_mlock2, addr, pass_usize(length), flags))
+}
+
+/// # Safety
+///
+/// `munlock` operates on raw pointers and may round out to the nearest page
+/// boundaries.
+#[inline]
+pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result<()> {
+ ret(syscall!(__NR_munlock, addr, pass_usize(length)))
+}
+
+#[inline]
+pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> {
+ ret_owned_fd(syscall_readonly!(__NR_userfaultfd, flags))
+}
diff --git a/vendor/rustix/src/imp/linux_raw/mm/types.rs b/vendor/rustix/src/imp/linux_raw/mm/types.rs
new file mode 100644
index 000000000..a58dd76be
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/mm/types.rs
@@ -0,0 +1,208 @@
+use super::super::c;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `PROT_*` flags for use with [`mmap`].
+ ///
+ /// For `PROT_NONE`, use `ProtFlags::empty()`.
+ ///
+ /// [`mmap`]: crate::io::mmap
+ pub struct ProtFlags: u32 {
+ /// `PROT_READ`
+ const READ = linux_raw_sys::general::PROT_READ;
+ /// `PROT_WRITE`
+ const WRITE = linux_raw_sys::general::PROT_WRITE;
+ /// `PROT_EXEC`
+ const EXEC = linux_raw_sys::general::PROT_EXEC;
+ }
+}
+
+bitflags! {
+ /// `PROT_*` flags for use with [`mprotect`].
+ ///
+ /// For `PROT_NONE`, use `MprotectFlags::empty()`.
+ ///
+ /// [`mprotect`]: crate::io::mprotect
+ pub struct MprotectFlags: u32 {
+ /// `PROT_READ`
+ const READ = linux_raw_sys::general::PROT_READ;
+ /// `PROT_WRITE`
+ const WRITE = linux_raw_sys::general::PROT_WRITE;
+ /// `PROT_EXEC`
+ const EXEC = linux_raw_sys::general::PROT_EXEC;
+ /// `PROT_GROWSUP`
+ const GROWSUP = linux_raw_sys::general::PROT_GROWSUP;
+ /// `PROT_GROWSDOWN`
+ const GROWSDOWN = linux_raw_sys::general::PROT_GROWSDOWN;
+ }
+}
+
+bitflags! {
+ /// `MAP_*` flags for use with [`mmap`].
+ ///
+ /// For `MAP_ANONYMOUS` (aka `MAP_ANON`), see [`mmap_anonymous`].
+ ///
+ /// [`mmap`]: crate::io::mmap
+ /// [`mmap_anonymous`]: crates::io::mmap_anonymous
+ pub struct MapFlags: u32 {
+ /// `MAP_SHARED`
+ const SHARED = linux_raw_sys::general::MAP_SHARED;
+ /// `MAP_SHARED_VALIDATE` (since Linux 4.15)
+ const SHARED_VALIDATE = linux_raw_sys::general::MAP_SHARED_VALIDATE;
+ /// `MAP_PRIVATE`
+ const PRIVATE = linux_raw_sys::general::MAP_PRIVATE;
+ /// `MAP_DENYWRITE`
+ const DENYWRITE = linux_raw_sys::general::MAP_DENYWRITE;
+ /// `MAP_FIXED`
+ const FIXED = linux_raw_sys::general::MAP_FIXED;
+ /// `MAP_FIXED_NOREPLACE` (since Linux 4.17)
+ const FIXED_NOREPLACE = linux_raw_sys::general::MAP_FIXED_NOREPLACE;
+ /// `MAP_GROWSDOWN`
+ const GROWSDOWN = linux_raw_sys::general::MAP_GROWSDOWN;
+ /// `MAP_HUGETLB`
+ const HUGETLB = linux_raw_sys::general::MAP_HUGETLB;
+ /// `MAP_HUGE_2MB` (since Linux 3.8)
+ const HUGE_2MB = linux_raw_sys::general::MAP_HUGE_2MB;
+ /// `MAP_HUGE_1GB` (since Linux 3.8)
+ const HUGE_1GB = linux_raw_sys::general::MAP_HUGE_1GB;
+ /// `MAP_LOCKED`
+ const LOCKED = linux_raw_sys::general::MAP_LOCKED;
+ /// `MAP_NORESERVE`
+ const NORESERVE = linux_raw_sys::general::MAP_NORESERVE;
+ /// `MAP_POPULATE`
+ const POPULATE = linux_raw_sys::general::MAP_POPULATE;
+ /// `MAP_STACK`
+ const STACK = linux_raw_sys::general::MAP_STACK;
+ /// `MAP_SYNC` (since Linux 4.15)
+ #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+ const SYNC = linux_raw_sys::general::MAP_SYNC;
+ /// `MAP_UNINITIALIZED`
+ #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+ const UNINITIALIZED = linux_raw_sys::general::MAP_UNINITIALIZED;
+ }
+}
+
+bitflags! {
+ /// `MREMAP_*` flags for use with [`mremap`].
+ ///
+ /// For `MREMAP_FIXED`, see [`mremap_fixed`].
+ ///
+ /// [`mremap`]: crate::io::mremap
+ /// [`mremap_fixed`]: crate::io::mremap_fixed
+ pub struct MremapFlags: u32 {
+ /// `MREMAP_MAYMOVE`
+ const MAYMOVE = linux_raw_sys::general::MREMAP_MAYMOVE;
+ /// `MREMAP_DONTUNMAP` (since Linux 5.7)
+ const DONTUNMAP = linux_raw_sys::general::MREMAP_DONTUNMAP;
+ }
+}
+
+bitflags! {
+ /// `MLOCK_*` flags for use with [`mlock_with`].
+ ///
+ /// [`mlock_with`]: crate::io::mlock_with
+ pub struct MlockFlags: u32 {
+ /// `MLOCK_ONFAULT`
+ const ONFAULT = linux_raw_sys::general::MLOCK_ONFAULT;
+ }
+}
+
+bitflags! {
+ /// `MS_*` flags for use with [`msync`].
+ ///
+ /// [`msync`]: crate::io::msync
+ pub struct MsyncFlags: u32 {
+ /// `MS_SYNC`—Requests an update and waits for it to complete.
+ const SYNC = linux_raw_sys::general::MS_SYNC;
+ /// `MS_ASYNC`—Specifies that an update be scheduled, but the call
+ /// returns immediately.
+ const ASYNC = linux_raw_sys::general::MS_ASYNC;
+ /// `MS_INVALIDATE`—Asks to invalidate other mappings of the same
+ /// file (so that they can be updated with the fresh values just
+ /// written).
+ const INVALIDATE = linux_raw_sys::general::MS_INVALIDATE;
+ }
+}
+
+bitflags! {
+ /// `O_*` flags for use with [`userfaultfd`].
+ ///
+ /// [`userfaultfd`]: crate::io::userfaultfd
+ pub struct UserfaultfdFlags: c::c_uint {
+ /// `O_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::O_CLOEXEC;
+ /// `O_NONBLOCK`
+ const NONBLOCK = linux_raw_sys::general::O_NONBLOCK;
+ }
+}
+
+/// `POSIX_MADV_*` constants for use with [`madvise`].
+///
+/// [`madvise`]: crate::mm::madvise
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum Advice {
+ /// `POSIX_MADV_NORMAL`
+ Normal = linux_raw_sys::general::MADV_NORMAL,
+
+ /// `POSIX_MADV_SEQUENTIAL`
+ Sequential = linux_raw_sys::general::MADV_SEQUENTIAL,
+
+ /// `POSIX_MADV_RANDOM`
+ Random = linux_raw_sys::general::MADV_RANDOM,
+
+ /// `POSIX_MADV_WILLNEED`
+ WillNeed = linux_raw_sys::general::MADV_WILLNEED,
+
+ /// `MADV_DONTNEED`
+ LinuxDontNeed = linux_raw_sys::general::MADV_DONTNEED,
+
+ /// `MADV_FREE` (since Linux 4.5)
+ LinuxFree = linux_raw_sys::general::MADV_FREE,
+ /// `MADV_REMOVE`
+ LinuxRemove = linux_raw_sys::general::MADV_REMOVE,
+ /// `MADV_DONTFORK`
+ LinuxDontFork = linux_raw_sys::general::MADV_DONTFORK,
+ /// `MADV_DOFORK`
+ LinuxDoFork = linux_raw_sys::general::MADV_DOFORK,
+ /// `MADV_HWPOISON`
+ LinuxHwPoison = linux_raw_sys::general::MADV_HWPOISON,
+ /// `MADV_SOFT_OFFLINE`
+ #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+ LinuxSoftOffline = linux_raw_sys::general::MADV_SOFT_OFFLINE,
+ /// `MADV_MERGEABLE`
+ LinuxMergeable = linux_raw_sys::general::MADV_MERGEABLE,
+ /// `MADV_UNMERGEABLE`
+ LinuxUnmergeable = linux_raw_sys::general::MADV_UNMERGEABLE,
+ /// `MADV_HUGEPAGE` (since Linux 2.6.38)
+ LinuxHugepage = linux_raw_sys::general::MADV_HUGEPAGE,
+ /// `MADV_NOHUGEPAGE` (since Linux 2.6.38)
+ LinuxNoHugepage = linux_raw_sys::general::MADV_NOHUGEPAGE,
+ /// `MADV_DONTDUMP` (since Linux 3.4)
+ LinuxDontDump = linux_raw_sys::general::MADV_DONTDUMP,
+ /// `MADV_DODUMP` (since Linux 3.4)
+ LinuxDoDump = linux_raw_sys::general::MADV_DODUMP,
+ /// `MADV_WIPEONFORK` (since Linux 4.14)
+ LinuxWipeOnFork = linux_raw_sys::general::MADV_WIPEONFORK,
+ /// `MADV_KEEPONFORK` (since Linux 4.14)
+ LinuxKeepOnFork = linux_raw_sys::general::MADV_KEEPONFORK,
+ /// `MADV_COLD` (since Linux 5.4)
+ LinuxCold = linux_raw_sys::general::MADV_COLD,
+ /// `MADV_PAGEOUT` (since Linux 5.4)
+ LinuxPageOut = linux_raw_sys::general::MADV_PAGEOUT,
+ /// `MADV_POPULATE_READ` (since Linux 5.14)
+ LinuxPopulateRead = linux_raw_sys::general::MADV_POPULATE_READ,
+ /// `MADV_POPULATE_WRITE` (since Linux 5.14)
+ LinuxPopulateWrite = linux_raw_sys::general::MADV_POPULATE_WRITE,
+}
+
+impl Advice {
+ /// `POSIX_MADV_DONTNEED`
+ ///
+ /// On Linux, this is mapped to `POSIX_MADV_NORMAL` because
+ /// Linux's `MADV_DONTNEED` differs from `POSIX_MADV_DONTNEED`. See
+ /// `LinuxDontNeed` for the Linux behavior.
+ #[allow(non_upper_case_globals)]
+ pub const DontNeed: Self = Self::Normal;
+}
diff --git a/vendor/rustix/src/imp/linux_raw/mod.rs b/vendor/rustix/src/imp/linux_raw/mod.rs
new file mode 100644
index 000000000..ed46eaad1
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/mod.rs
@@ -0,0 +1,68 @@
+//! The linux_raw backend.
+//!
+//! This makes Linux syscalls directly, without going through libc.
+//!
+//! # Safety
+//!
+//! These files performs raw system calls, and sometimes passes them
+//! uninitialized memory buffers. The signatures in this file are currently
+//! manually maintained and must correspond with the signatures of the actual
+//! Linux syscalls.
+//!
+//! Some of this could be auto-generated from the Linux header file
+//! <linux/syscalls.h>, but we often need more information than it provides,
+//! such as which pointers are array slices, out parameters, or in-out
+//! parameters, which integers are owned or borrowed file descriptors, etc.
+
+#[macro_use]
+mod arch;
+mod conv;
+mod elf;
+mod reg;
+#[cfg(any(feature = "time", target_arch = "x86"))]
+mod vdso;
+#[cfg(any(feature = "time", target_arch = "x86"))]
+mod vdso_wrappers;
+
+#[cfg(any(
+ feature = "param",
+ feature = "runtime",
+ feature = "time",
+ target_arch = "x86",
+))]
+pub(crate) mod param;
+// #[cfg(feature = "fs")] // TODO: Enable once `OwnedFd` moves out of the tree.
+pub(crate) mod fs;
+pub(crate) mod io;
+#[cfg(feature = "io_uring")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "io_uring")))]
+pub(crate) mod io_uring;
+#[cfg(any(feature = "mm", feature = "time", target_arch = "x86"))] // vdso.rs uses `madvise`
+pub(crate) mod mm;
+#[cfg(feature = "net")]
+pub(crate) mod net;
+pub(crate) mod process;
+#[cfg(feature = "rand")]
+pub(crate) mod rand;
+#[cfg(feature = "runtime")]
+pub(crate) mod runtime;
+#[cfg(feature = "termios")]
+pub(crate) mod termios;
+#[cfg(feature = "thread")]
+pub(crate) mod thread;
+pub(crate) mod time;
+
+#[cfg(feature = "std")]
+pub(crate) mod fd {
+ pub use io_lifetimes::*;
+ #[allow(unused_imports)]
+ pub(crate) use std::os::unix::io::RawFd as LibcFd;
+ pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+}
+
+#[cfg(not(feature = "std"))]
+pub(crate) use crate::io::fd;
+
+// The linux_raw backend doesn't use actual libc, so we define selected
+// libc-like definitions in a module called `c`.
+pub(crate) mod c;
diff --git a/vendor/rustix/src/imp/linux_raw/net/addr.rs b/vendor/rustix/src/imp/linux_raw/net/addr.rs
new file mode 100644
index 000000000..d5683f34e
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/net/addr.rs
@@ -0,0 +1,172 @@
+//! IPv4, IPv6, and Socket addresses.
+//!
+//! # Safety
+//!
+//! Linux's IPv6 type contains a union.
+#![allow(unsafe_code)]
+
+use super::super::c;
+use crate::ffi::CStr;
+use crate::{io, path};
+use core::convert::TryInto;
+use core::{fmt, slice};
+
+/// `struct sockaddr_un`
+#[derive(Clone)]
+#[doc(alias = "sockaddr_un")]
+pub struct SocketAddrUnix {
+ pub(crate) unix: c::sockaddr_un,
+ len: c::socklen_t,
+}
+
+impl SocketAddrUnix {
+ /// Construct a new Unix-domain address from a filesystem path.
+ #[inline]
+ pub fn new<P: path::Arg>(path: P) -> io::Result<Self> {
+ path.into_with_c_str(Self::_new)
+ }
+
+ #[inline]
+ fn _new(path: &CStr) -> io::Result<Self> {
+ let mut unix = Self::init();
+ let bytes = path.to_bytes_with_nul();
+ if bytes.len() > unix.sun_path.len() {
+ return Err(io::Errno::NAMETOOLONG);
+ }
+ for (i, b) in bytes.iter().enumerate() {
+ unix.sun_path[i] = *b as c::c_char;
+ }
+ let len = offsetof_sun_path() + bytes.len();
+ let len = len.try_into().unwrap();
+ Ok(Self { unix, len })
+ }
+
+ /// Construct a new abstract Unix-domain address from a byte slice.
+ #[inline]
+ pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
+ let mut unix = Self::init();
+ if 1 + name.len() > unix.sun_path.len() {
+ return Err(io::Errno::NAMETOOLONG);
+ }
+ unix.sun_path[0] = b'\0' as c::c_char;
+ for (i, b) in name.iter().enumerate() {
+ unix.sun_path[1 + i] = *b as c::c_char;
+ }
+ let len = offsetof_sun_path() + 1 + name.len();
+ let len = len.try_into().unwrap();
+ Ok(Self { unix, len })
+ }
+
+ fn init() -> c::sockaddr_un {
+ c::sockaddr_un {
+ sun_family: c::AF_UNIX as _,
+ sun_path: [0; 108],
+ }
+ }
+
+ /// For a filesystem path address, return the path.
+ #[inline]
+ pub fn path(&self) -> Option<&CStr> {
+ let len = self.len();
+ if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char {
+ let end = len as usize - offsetof_sun_path();
+ let bytes = &self.unix.sun_path[..end];
+ // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And
+ // `from_bytes_with_nul_unchecked` since the string is NUL-terminated.
+ unsafe {
+ Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
+ bytes.as_ptr().cast(),
+ bytes.len(),
+ )))
+ }
+ } else {
+ None
+ }
+ }
+
+ /// For an abstract address, return the identifier.
+ #[inline]
+ pub fn abstract_name(&self) -> Option<&[u8]> {
+ let len = self.len();
+ if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char {
+ let end = len as usize - offsetof_sun_path();
+ let bytes = &self.unix.sun_path[1..end];
+ // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
+ unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ pub(crate) fn addr_len(&self) -> c::socklen_t {
+ self.len
+ }
+
+ #[inline]
+ pub(crate) fn len(&self) -> usize {
+ self.addr_len() as usize
+ }
+}
+
+impl PartialEq for SocketAddrUnix {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len])
+ }
+}
+
+impl Eq for SocketAddrUnix {}
+
+impl PartialOrd for SocketAddrUnix {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len])
+ }
+}
+
+impl Ord for SocketAddrUnix {
+ #[inline]
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len])
+ }
+}
+
+impl core::hash::Hash for SocketAddrUnix {
+ #[inline]
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ let self_len = self.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].hash(state)
+ }
+}
+
+impl fmt::Debug for SocketAddrUnix {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(path) = self.path() {
+ path.fmt(fmt)
+ } else if let Some(name) = self.abstract_name() {
+ name.fmt(fmt)
+ } else {
+ "(unnamed)".fmt(fmt)
+ }
+ }
+}
+
+/// `struct sockaddr_storage` as a raw struct.
+pub type SocketAddrStorage = c::sockaddr;
+
+/// Return the offset of the `sun_path` field of `sockaddr_un`.
+#[inline]
+pub(crate) fn offsetof_sun_path() -> usize {
+ let z = c::sockaddr_un {
+ sun_family: 0_u16,
+ sun_path: [0; 108],
+ };
+ (crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/net/ext.rs b/vendor/rustix/src/imp/linux_raw/net/ext.rs
new file mode 100644
index 000000000..8556c9d90
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/net/ext.rs
@@ -0,0 +1,64 @@
+#![allow(unsafe_code)]
+
+use super::super::c;
+
+#[inline]
+pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 {
+ addr.s_addr
+}
+
+#[inline]
+pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr {
+ c::in_addr { s_addr }
+}
+
+#[cfg(not(feature = "std"))]
+#[inline]
+pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
+ // Safety: `in6_addr` is `repr(C)` and contains plain integer data.
+ unsafe { addr.in6_u.u6_addr8 }
+}
+
+// TODO: With Rust 1.55, we can use the above `in6_addr_s6_addr` definition
+// that uses a const-fn union access instead of doing a transmute.
+#[cfg(not(not(feature = "std")))]
+#[inline]
+pub(crate) fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
+ // Safety: `in6_addr` is `repr(C)` and contains plain integer data.
+ unsafe { core::mem::transmute(addr) }
+}
+
+#[inline]
+pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
+ c::in6_addr {
+ in6_u: linux_raw_sys::general::in6_addr__bindgen_ty_1 { u6_addr8: s6_addr },
+ }
+}
+
+#[inline]
+pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
+ addr.sin6_scope_id
+}
+
+#[cfg(not(feature = "std"))]
+#[inline]
+pub(crate) fn sockaddr_in6_sin6_scope_id_mut(addr: &mut c::sockaddr_in6) -> &mut u32 {
+ &mut addr.sin6_scope_id
+}
+
+#[inline]
+pub(crate) const fn sockaddr_in6_new(
+ sin6_family: c::sa_family_t,
+ sin6_port: u16,
+ sin6_flowinfo: u32,
+ sin6_addr: c::in6_addr,
+ sin6_scope_id: u32,
+) -> c::sockaddr_in6 {
+ c::sockaddr_in6 {
+ sin6_family,
+ sin6_port,
+ sin6_flowinfo,
+ sin6_addr,
+ sin6_scope_id,
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/net/mod.rs b/vendor/rustix/src/imp/linux_raw/net/mod.rs
new file mode 100644
index 000000000..5e67dfd21
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/net/mod.rs
@@ -0,0 +1,8 @@
+pub(crate) mod addr;
+#[cfg(not(feature = "std"))]
+pub(crate) mod ext;
+pub(crate) mod read_sockaddr;
+pub(crate) mod send_recv;
+pub(crate) mod syscalls;
+pub(crate) mod types;
+pub(crate) mod write_sockaddr;
diff --git a/vendor/rustix/src/imp/linux_raw/net/read_sockaddr.rs b/vendor/rustix/src/imp/linux_raw/net/read_sockaddr.rs
new file mode 100644
index 000000000..b9bc09b96
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/net/read_sockaddr.rs
@@ -0,0 +1,175 @@
+//! The BSD sockets API requires us to read the `ss_family` field before
+//! we can interpret the rest of a `sockaddr` produced by the kernel.
+#![allow(unsafe_code)]
+
+use super::super::c;
+use crate::io;
+use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
+use alloc::vec::Vec;
+use core::mem::size_of;
+
+// This must match the header of `sockaddr`.
+#[repr(C)]
+struct sockaddr_header {
+ ss_family: u16,
+}
+
+/// Read the `ss_family` field from a socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
+#[inline]
+unsafe fn read_ss_family(storage: *const c::sockaddr) -> u16 {
+ // Assert that we know the layout of `sockaddr`.
+ let _ = c::sockaddr {
+ __storage: c::sockaddr_storage {
+ __bindgen_anon_1: linux_raw_sys::general::__kernel_sockaddr_storage__bindgen_ty_1 {
+ __bindgen_anon_1:
+ linux_raw_sys::general::__kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 {
+ ss_family: 0_u16,
+ __data: [0; 126_usize],
+ },
+ },
+ },
+ };
+
+ (*storage.cast::<sockaddr_header>()).ss_family
+}
+
+/// Set the `ss_family` field of a socket address to `AF_UNSPEC`, so that we
+/// can test for `AF_UNSPEC` to test whether it was stored to.
+#[inline]
+pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr) {
+ (*storage.cast::<sockaddr_header>()).ss_family = c::AF_UNSPEC as _;
+}
+
+/// Read a socket address encoded in a platform-specific format.
+///
+/// # Safety
+///
+/// `storage` must point to valid socket address storage.
+pub(crate) unsafe fn read_sockaddr(
+ storage: *const c::sockaddr,
+ len: usize,
+) -> io::Result<SocketAddrAny> {
+ let offsetof_sun_path = super::addr::offsetof_sun_path();
+
+ if len < size_of::<c::sa_family_t>() {
+ return Err(io::Errno::INVAL);
+ }
+ match read_ss_family(storage).into() {
+ c::AF_INET => {
+ if len < size_of::<c::sockaddr_in>() {
+ return Err(io::Errno::INVAL);
+ }
+ let decode = *storage.cast::<c::sockaddr_in>();
+ Ok(SocketAddrAny::V4(SocketAddrV4::new(
+ Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)),
+ u16::from_be(decode.sin_port),
+ )))
+ }
+ c::AF_INET6 => {
+ if len < size_of::<c::sockaddr_in6>() {
+ return Err(io::Errno::INVAL);
+ }
+ let decode = *storage.cast::<c::sockaddr_in6>();
+ Ok(SocketAddrAny::V6(SocketAddrV6::new(
+ Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8),
+ u16::from_be(decode.sin6_port),
+ u32::from_be(decode.sin6_flowinfo),
+ decode.sin6_scope_id,
+ )))
+ }
+ c::AF_UNIX => {
+ if len < offsetof_sun_path {
+ return Err(io::Errno::INVAL);
+ }
+ if len == offsetof_sun_path {
+ Ok(SocketAddrAny::Unix(SocketAddrUnix::new(&[][..])?))
+ } else {
+ let decode = *storage.cast::<c::sockaddr_un>();
+ assert_eq!(
+ decode.sun_path[len - 1 - offsetof_sun_path],
+ b'\0' as c::c_char
+ );
+ Ok(SocketAddrAny::Unix(SocketAddrUnix::new(
+ decode.sun_path[..len - 1 - offsetof_sun_path]
+ .iter()
+ .map(|c| *c as u8)
+ .collect::<Vec<u8>>(),
+ )?))
+ }
+ }
+ _ => Err(io::Errno::NOTSUP),
+ }
+}
+
+/// Read a socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
+pub(crate) unsafe fn maybe_read_sockaddr_os(
+ storage: *const c::sockaddr,
+ len: usize,
+) -> Option<SocketAddrAny> {
+ if len == 0 {
+ None
+ } else {
+ Some(read_sockaddr_os(storage, len))
+ }
+}
+
+/// Read a socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
+pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) -> SocketAddrAny {
+ let offsetof_sun_path = super::addr::offsetof_sun_path();
+
+ assert!(len >= size_of::<c::sa_family_t>());
+ match read_ss_family(storage).into() {
+ c::AF_INET => {
+ assert!(len >= size_of::<c::sockaddr_in>());
+ let decode = *storage.cast::<c::sockaddr_in>();
+ SocketAddrAny::V4(SocketAddrV4::new(
+ Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)),
+ u16::from_be(decode.sin_port),
+ ))
+ }
+ c::AF_INET6 => {
+ assert!(len >= size_of::<c::sockaddr_in6>());
+ let decode = *storage.cast::<c::sockaddr_in6>();
+ SocketAddrAny::V6(SocketAddrV6::new(
+ Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8),
+ u16::from_be(decode.sin6_port),
+ u32::from_be(decode.sin6_flowinfo),
+ decode.sin6_scope_id,
+ ))
+ }
+ c::AF_UNIX => {
+ assert!(len >= offsetof_sun_path);
+ if len == offsetof_sun_path {
+ SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap())
+ } else {
+ let decode = *storage.cast::<c::sockaddr_un>();
+ assert_eq!(
+ decode.sun_path[len - 1 - offsetof_sun_path],
+ b'\0' as c::c_char
+ );
+ SocketAddrAny::Unix(
+ SocketAddrUnix::new(
+ decode.sun_path[..len - 1 - offsetof_sun_path]
+ .iter()
+ .map(|c| *c as u8)
+ .collect::<Vec<u8>>(),
+ )
+ .unwrap(),
+ )
+ }
+ }
+ other => unimplemented!("{:?}", other),
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/net/send_recv.rs b/vendor/rustix/src/imp/linux_raw/net/send_recv.rs
new file mode 100644
index 000000000..888e81e2b
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/net/send_recv.rs
@@ -0,0 +1,42 @@
+use super::super::c;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `MSG_*`
+ pub struct SendFlags: u32 {
+ /// `MSG_CONFIRM`
+ const CONFIRM = c::MSG_CONFIRM;
+ /// `MSG_DONTROUTE`
+ const DONTROUTE = c::MSG_DONTROUTE;
+ /// `MSG_DONTWAIT`
+ const DONTWAIT = c::MSG_DONTWAIT;
+ /// `MSG_EOT`
+ const EOT = c::MSG_EOR;
+ /// `MSG_MORE`
+ const MORE = c::MSG_MORE;
+ /// `MSG_NOSIGNAL`
+ const NOSIGNAL = c::MSG_NOSIGNAL;
+ /// `MSG_OOB`
+ const OOB = c::MSG_OOB;
+ }
+}
+
+bitflags! {
+ /// `MSG_*`
+ pub struct RecvFlags: u32 {
+ /// `MSG_CMSG_CLOEXEC`
+ const CMSG_CLOEXEC = c::MSG_CMSG_CLOEXEC;
+ /// `MSG_DONTWAIT`
+ const DONTWAIT = c::MSG_DONTWAIT;
+ /// `MSG_ERRQUEUE`
+ const ERRQUEUE = c::MSG_ERRQUEUE;
+ /// `MSG_OOB`
+ const OOB = c::MSG_OOB;
+ /// `MSG_PEEK`
+ const PEEK = c::MSG_PEEK;
+ /// `MSG_TRUNC`
+ const TRUNC = c::MSG_TRUNC;
+ /// `MSG_WAITALL`
+ const WAITALL = c::MSG_WAITALL;
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/net/syscalls.rs b/vendor/rustix/src/imp/linux_raw/net/syscalls.rs
new file mode 100644
index 000000000..18a0f130d
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/net/syscalls.rs
@@ -0,0 +1,1234 @@
+//! linux_raw syscalls supporting `rustix::net`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::c;
+use super::super::conv::{
+ by_mut, by_ref, c_int, c_uint, ret, ret_owned_fd, ret_usize, size_of, slice, slice_mut,
+ socklen_t, zero,
+};
+use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os};
+use super::send_recv::{RecvFlags, SendFlags};
+use super::types::{AcceptFlags, AddressFamily, Protocol, Shutdown, SocketFlags, SocketType};
+use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
+use crate::fd::BorrowedFd;
+use crate::io::{self, OwnedFd};
+use crate::net::{SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
+use c::{sockaddr, sockaddr_in, sockaddr_in6, socklen_t};
+use core::convert::TryInto;
+use core::mem::MaybeUninit;
+#[cfg(target_arch = "x86")]
+use {
+ super::super::conv::{slice_just_addr, x86_sys},
+ super::super::reg::{ArgReg, SocketArg},
+ linux_raw_sys::general::{
+ SYS_ACCEPT, SYS_ACCEPT4, SYS_BIND, SYS_CONNECT, SYS_GETPEERNAME, SYS_GETSOCKNAME,
+ SYS_GETSOCKOPT, SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_SEND, SYS_SENDTO, SYS_SETSOCKOPT,
+ SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR,
+ },
+};
+
+#[inline]
+pub(crate) fn socket(
+ family: AddressFamily,
+ type_: SocketType,
+ protocol: Protocol,
+) -> io::Result<OwnedFd> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(__NR_socket, family, type_, protocol))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SOCKET),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ family.into(),
+ type_.into(),
+ protocol.into(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn socket_with(
+ family: AddressFamily,
+ type_: SocketType,
+ flags: SocketFlags,
+ protocol: Protocol,
+) -> io::Result<OwnedFd> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_socket,
+ family,
+ (type_, flags),
+ protocol
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SOCKET),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ family.into(),
+ (type_, flags).into(),
+ protocol.into(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn socketpair(
+ family: AddressFamily,
+ type_: SocketType,
+ flags: SocketFlags,
+ protocol: Protocol,
+) -> io::Result<(OwnedFd, OwnedFd)> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(syscall!(
+ __NR_socketpair,
+ family,
+ (type_, flags),
+ protocol,
+ &mut result
+ ))
+ .map(|()| {
+ let [fd0, fd1] = result.assume_init();
+ (fd0, fd1)
+ })
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_SOCKETPAIR),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ family.into(),
+ (type_, flags).into(),
+ protocol.into(),
+ (&mut result).into(),
+ ])
+ ))
+ .map(|()| {
+ let [fd0, fd1] = result.assume_init();
+ (fd0, fd1)
+ })
+ }
+}
+
+#[inline]
+pub(crate) fn accept(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let fd = ret_owned_fd(syscall_readonly!(__NR_accept, fd, zero(), zero()))?;
+ Ok(fd)
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let fd = ret_owned_fd(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_ACCEPT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), zero(), zero()])
+ ))?;
+ Ok(fd)
+ }
+}
+
+#[inline]
+pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: AcceptFlags) -> io::Result<OwnedFd> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let fd = ret_owned_fd(syscall_readonly!(__NR_accept4, fd, zero(), zero(), flags))?;
+ Ok(fd)
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let fd = ret_owned_fd(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_ACCEPT4),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), zero(), zero(), flags.into()])
+ ))?;
+ Ok(fd)
+ }
+}
+
+#[inline]
+pub(crate) fn acceptfrom(fd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ let fd = ret_owned_fd(syscall!(
+ __NR_accept,
+ fd,
+ &mut storage,
+ by_mut(&mut addrlen)
+ ))?;
+ Ok((
+ fd,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ let fd = ret_owned_fd(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_ACCEPT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ ])
+ ))?;
+ Ok((
+ fd,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn acceptfrom_with(
+ fd: BorrowedFd<'_>,
+ flags: AcceptFlags,
+) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ let fd = ret_owned_fd(syscall!(
+ __NR_accept4,
+ fd,
+ &mut storage,
+ by_mut(&mut addrlen),
+ flags
+ ))?;
+ Ok((
+ fd,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ let fd = ret_owned_fd(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_ACCEPT4),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ flags.into(),
+ ])
+ ))?;
+ Ok((
+ fd,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_shutdown,
+ fd,
+ c_uint(how as c::c_uint)
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SHUTDOWN),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), c_uint(how as c::c_uint)])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ #[cfg(not(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ target_arch = "x86",
+ target_arch = "x86_64",
+ )))]
+ unsafe {
+ ret_usize(syscall_readonly!(__NR_send, fd, buf_addr, buf_len, flags))
+ }
+ #[cfg(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ target_arch = "x86_64",
+ ))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_sendto,
+ fd,
+ buf_addr,
+ buf_len,
+ flags,
+ zero(),
+ zero()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SEND),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), buf_addr, buf_len, flags.into()])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn sendto_v4(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrV4,
+) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_sendto,
+ fd,
+ buf_addr,
+ buf_len,
+ flags,
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SENDTO),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr,
+ buf_len,
+ flags.into(),
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn sendto_v6(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrV6,
+) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_sendto,
+ fd,
+ buf_addr,
+ buf_len,
+ flags,
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SENDTO),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr,
+ buf_len,
+ flags.into(),
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn sendto_unix(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrUnix,
+) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_sendto,
+ fd,
+ buf_addr,
+ buf_len,
+ flags,
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len())
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SENDTO),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr,
+ buf_len,
+ flags.into(),
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len()),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+
+ #[cfg(not(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ target_arch = "x86",
+ target_arch = "x86_64",
+ )))]
+ unsafe {
+ ret_usize(syscall!(__NR_recv, fd, buf_addr_mut, buf_len, flags))
+ }
+ #[cfg(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ target_arch = "x86_64",
+ ))]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_recvfrom,
+ fd,
+ buf_addr_mut,
+ buf_len,
+ flags,
+ zero(),
+ zero()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_RECV),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr_mut,
+ buf_len,
+ flags.into(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn recvfrom(
+ fd: BorrowedFd<'_>,
+ buf: &mut [u8],
+ flags: RecvFlags,
+) -> io::Result<(usize, Option<SocketAddrAny>)> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+
+ unsafe {
+ // `recvfrom` does not write to the storage if the socket is
+ // connection-oriented sockets, so we initialize the family field to
+ // `AF_UNSPEC` so that we can detect this case.
+ initialize_family_to_unspec(storage.as_mut_ptr());
+
+ #[cfg(not(target_arch = "x86"))]
+ let nread = ret_usize(syscall!(
+ __NR_recvfrom,
+ fd,
+ buf_addr_mut,
+ buf_len,
+ flags,
+ &mut storage,
+ by_mut(&mut addrlen)
+ ))?;
+ #[cfg(target_arch = "x86")]
+ let nread = ret_usize(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_RECVFROM),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr_mut,
+ buf_len,
+ flags.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ ])
+ ))?;
+
+ Ok((
+ nread,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn getpeername(fd: BorrowedFd<'_>) -> io::Result<Option<SocketAddrAny>> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ ret(syscall!(
+ __NR_getpeername,
+ fd,
+ &mut storage,
+ by_mut(&mut addrlen)
+ ))?;
+ Ok(maybe_read_sockaddr_os(
+ &storage.assume_init(),
+ addrlen.try_into().unwrap(),
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ ret(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_GETPEERNAME),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ ])
+ ))?;
+ Ok(maybe_read_sockaddr_os(
+ &storage.assume_init(),
+ addrlen.try_into().unwrap(),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn getsockname(fd: BorrowedFd<'_>) -> io::Result<SocketAddrAny> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ ret(syscall!(
+ __NR_getsockname,
+ fd,
+ &mut storage,
+ by_mut(&mut addrlen)
+ ))?;
+ Ok(read_sockaddr_os(
+ &storage.assume_init(),
+ addrlen.try_into().unwrap(),
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ ret(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_GETSOCKNAME),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ ])
+ ))?;
+ Ok(read_sockaddr_os(
+ &storage.assume_init(),
+ addrlen.try_into().unwrap(),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn bind_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_bind,
+ fd,
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_BIND),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn bind_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_bind,
+ fd,
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_BIND),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn bind_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_bind,
+ fd,
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len())
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_BIND),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len()),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn connect_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_connect,
+ fd,
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_CONNECT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn connect_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_connect,
+ fd,
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_CONNECT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn connect_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_connect,
+ fd,
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len())
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_CONNECT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len()),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(__NR_listen, fd, c_int(backlog)))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_LISTEN),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), c_int(backlog)])
+ ))
+ }
+}
+
+pub(crate) mod sockopt {
+ use super::{c, BorrowedFd};
+ use crate::io;
+ use crate::net::sockopt::Timeout;
+ use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
+ use c::{SO_RCVTIMEO_NEW, SO_RCVTIMEO_OLD, SO_SNDTIMEO_NEW, SO_SNDTIMEO_OLD};
+ use core::convert::TryInto;
+ use core::time::Duration;
+ use linux_raw_sys::general::{__kernel_timespec, timeval};
+
+ // TODO: With Rust 1.53 we can use `Duration::ZERO` instead.
+ const DURATION_ZERO: Duration = Duration::from_secs(0);
+
+ #[inline]
+ fn getsockopt<T: Copy>(fd: BorrowedFd<'_>, level: u32, optname: u32) -> io::Result<T> {
+ use super::*;
+
+ let mut optlen = core::mem::size_of::<T>();
+ debug_assert!(
+ optlen as usize >= core::mem::size_of::<c::c_int>(),
+ "Socket APIs don't ever use `bool` directly"
+ );
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut value = MaybeUninit::<T>::uninit();
+ ret(syscall!(
+ __NR_getsockopt,
+ fd,
+ c_uint(level),
+ c_uint(optname),
+ &mut value,
+ by_mut(&mut optlen)
+ ))?;
+
+ assert_eq!(
+ optlen as usize,
+ core::mem::size_of::<T>(),
+ "unexpected getsockopt size"
+ );
+ Ok(value.assume_init())
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut value = MaybeUninit::<T>::uninit();
+ ret(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_GETSOCKOPT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ c_uint(level),
+ c_uint(optname),
+ (&mut value).into(),
+ by_mut(&mut optlen),
+ ])
+ ))?;
+ assert_eq!(
+ optlen as usize,
+ core::mem::size_of::<T>(),
+ "unexpected getsockopt size"
+ );
+ Ok(value.assume_init())
+ }
+ }
+
+ #[inline]
+ fn setsockopt<T: Copy>(
+ fd: BorrowedFd<'_>,
+ level: u32,
+ optname: u32,
+ value: T,
+ ) -> io::Result<()> {
+ use super::*;
+
+ let optlen = core::mem::size_of::<T>().try_into().unwrap();
+ debug_assert!(
+ optlen as usize >= core::mem::size_of::<c::c_int>(),
+ "Socket APIs don't ever use `bool` directly"
+ );
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_setsockopt,
+ fd,
+ c_uint(level),
+ c_uint(optname),
+ by_ref(&value),
+ socklen_t(optlen)
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SETSOCKOPT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ c_uint(level),
+ c_uint(optname),
+ by_ref(&value),
+ socklen_t(optlen),
+ ])
+ ))
+ }
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_type(fd: BorrowedFd<'_>) -> io::Result<SocketType> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_TYPE)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_reuseaddr(fd: BorrowedFd<'_>, reuseaddr: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::SOL_SOCKET as _,
+ c::SO_REUSEADDR,
+ from_bool(reuseaddr),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_broadcast(fd: BorrowedFd<'_>, broadcast: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::SOL_SOCKET as _,
+ c::SO_BROADCAST,
+ from_bool(broadcast),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_broadcast(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_BROADCAST).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_linger(
+ fd: BorrowedFd<'_>,
+ linger: Option<Duration>,
+ ) -> io::Result<()> {
+ // Convert `linger` to seconds, rounding up.
+ let l_linger = if let Some(linger) = linger {
+ let mut l_linger = linger.as_secs();
+ if linger.subsec_nanos() != 0 {
+ l_linger = l_linger.checked_add(1).ok_or(io::Errno::INVAL)?;
+ }
+ l_linger.try_into().map_err(|_e| io::Errno::INVAL)?
+ } else {
+ 0
+ };
+ let linger = c::linger {
+ l_onoff: c::c_int::from(linger.is_some()),
+ l_linger,
+ };
+ setsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER, linger)
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result<Option<Duration>> {
+ let linger: c::linger = getsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER)?;
+ // TODO: With Rust 1.50, this could use `.then`.
+ Ok(if linger.l_onoff != 0 {
+ Some(Duration::from_secs(linger.l_linger as u64))
+ } else {
+ None
+ })
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_passcred(fd: BorrowedFd<'_>, passcred: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED, from_bool(passcred))
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_passcred(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_timeout(
+ fd: BorrowedFd<'_>,
+ id: Timeout,
+ timeout: Option<Duration>,
+ ) -> io::Result<()> {
+ let time = duration_to_linux(timeout)?;
+ let optname = match id {
+ Timeout::Recv => SO_RCVTIMEO_NEW,
+ Timeout::Send => SO_SNDTIMEO_NEW,
+ };
+ match setsockopt(fd, c::SOL_SOCKET, optname, time) {
+ Err(io::Errno::NOPROTOOPT) if SO_RCVTIMEO_NEW != SO_RCVTIMEO_OLD => {
+ set_socket_timeout_old(fd, id, timeout)
+ }
+ otherwise => otherwise,
+ }
+ }
+
+ /// Same as `set_socket_timeout` but uses `timeval` instead of
+ /// `__kernel_timespec` and `_OLD` constants instead of `_NEW`.
+ fn set_socket_timeout_old(
+ fd: BorrowedFd<'_>,
+ id: Timeout,
+ timeout: Option<Duration>,
+ ) -> io::Result<()> {
+ let time = duration_to_linux_old(timeout)?;
+ let optname = match id {
+ Timeout::Recv => SO_RCVTIMEO_OLD,
+ Timeout::Send => SO_SNDTIMEO_OLD,
+ };
+ setsockopt(fd, c::SOL_SOCKET, optname, time)
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_timeout(
+ fd: BorrowedFd<'_>,
+ id: Timeout,
+ ) -> io::Result<Option<Duration>> {
+ let optname = match id {
+ Timeout::Recv => SO_RCVTIMEO_NEW,
+ Timeout::Send => SO_SNDTIMEO_NEW,
+ };
+ let time: __kernel_timespec = match getsockopt(fd, c::SOL_SOCKET, optname) {
+ Err(io::Errno::NOPROTOOPT) if SO_RCVTIMEO_NEW != SO_RCVTIMEO_OLD => {
+ return get_socket_timeout_old(fd, id)
+ }
+ otherwise => otherwise?,
+ };
+ Ok(duration_from_linux(time))
+ }
+
+ /// Same as `get_socket_timeout` but uses `timeval` instead of
+ /// `__kernel_timespec` and `_OLD` constants instead of `_NEW`.
+ fn get_socket_timeout_old(fd: BorrowedFd<'_>, id: Timeout) -> io::Result<Option<Duration>> {
+ let optname = match id {
+ Timeout::Recv => SO_RCVTIMEO_OLD,
+ Timeout::Send => SO_SNDTIMEO_OLD,
+ };
+ let time: timeval = getsockopt(fd, c::SOL_SOCKET, optname)?;
+ Ok(duration_from_linux_old(time))
+ }
+
+ /// Convert a C `timespec` to a Rust `Option<Duration>`.
+ #[inline]
+ fn duration_from_linux(time: __kernel_timespec) -> Option<Duration> {
+ if time.tv_sec == 0 && time.tv_nsec == 0 {
+ None
+ } else {
+ Some(
+ Duration::from_secs(time.tv_sec as u64) + Duration::from_nanos(time.tv_nsec as u64),
+ )
+ }
+ }
+
+ /// Like `duration_from_linux` but uses Linux's old 32-bit `timeval`.
+ fn duration_from_linux_old(time: timeval) -> Option<Duration> {
+ if time.tv_sec == 0 && time.tv_usec == 0 {
+ None
+ } else {
+ Some(
+ Duration::from_secs(time.tv_sec as u64)
+ + Duration::from_micros(time.tv_usec as u64),
+ )
+ }
+ }
+
+ /// Convert a Rust `Option<Duration>` to a C `timespec`.
+ #[inline]
+ fn duration_to_linux(timeout: Option<Duration>) -> io::Result<__kernel_timespec> {
+ Ok(match timeout {
+ Some(timeout) => {
+ if timeout == DURATION_ZERO {
+ return Err(io::Errno::INVAL);
+ }
+ let mut timeout = __kernel_timespec {
+ tv_sec: timeout.as_secs().try_into().unwrap_or(i64::MAX),
+ tv_nsec: timeout.subsec_nanos().into(),
+ };
+ if timeout.tv_sec == 0 && timeout.tv_nsec == 0 {
+ timeout.tv_nsec = 1;
+ }
+ timeout
+ }
+ None => __kernel_timespec {
+ tv_sec: 0,
+ tv_nsec: 0,
+ },
+ })
+ }
+
+ /// Like `duration_to_linux` but uses Linux's old 32-bit `timeval`.
+ fn duration_to_linux_old(timeout: Option<Duration>) -> io::Result<timeval> {
+ Ok(match timeout {
+ Some(timeout) => {
+ if timeout == DURATION_ZERO {
+ return Err(io::Errno::INVAL);
+ }
+
+ // `subsec_micros` rounds down, so we use `subsec_nanos` and
+ // manually round up.
+ let mut timeout = timeval {
+ tv_sec: timeout.as_secs().try_into().unwrap_or(c::c_long::MAX),
+ tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _,
+ };
+ if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+ timeout.tv_usec = 1;
+ }
+ timeout
+ }
+ None => timeval {
+ tv_sec: 0,
+ tv_usec: 0,
+ },
+ })
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_ttl(fd: BorrowedFd<'_>, ttl: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL, ttl)
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_v6only(fd: BorrowedFd<'_>, only_v6: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY, from_bool(only_v6))
+ }
+
+ #[inline]
+ pub(crate) fn get_ipv6_v6only(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_multicast_loop(
+ fd: BorrowedFd<'_>,
+ multicast_loop: bool,
+ ) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IP as _,
+ c::IP_MULTICAST_LOOP,
+ from_bool(multicast_loop),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_LOOP).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_multicast_ttl(fd: BorrowedFd<'_>, multicast_ttl: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL, multicast_ttl)
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_multicast_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_multicast_loop(
+ fd: BorrowedFd<'_>,
+ multicast_loop: bool,
+ ) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IPV6 as _,
+ c::IPV6_MULTICAST_LOOP,
+ from_bool(multicast_loop),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_ipv6_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_MULTICAST_LOOP).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_add_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ ) -> io::Result<()> {
+ let mreq = to_imr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_ADD_MEMBERSHIP, mreq)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_add_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv6Addr,
+ interface: u32,
+ ) -> io::Result<()> {
+ let mreq = to_ipv6mr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_ADD_MEMBERSHIP, mreq)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_drop_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ ) -> io::Result<()> {
+ let mreq = to_imr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_DROP_MEMBERSHIP, mreq)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_drop_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv6Addr,
+ interface: u32,
+ ) -> io::Result<()> {
+ let mreq = to_ipv6mr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_DROP_MEMBERSHIP, mreq)
+ }
+
+ #[inline]
+ pub(crate) fn set_tcp_nodelay(fd: BorrowedFd<'_>, nodelay: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY, from_bool(nodelay))
+ }
+
+ #[inline]
+ pub(crate) fn get_tcp_nodelay(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY).map(to_bool)
+ }
+
+ #[inline]
+ fn to_imr(multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> c::ip_mreq {
+ c::ip_mreq {
+ imr_multiaddr: to_imr_addr(multiaddr),
+ imr_interface: to_imr_addr(interface),
+ }
+ }
+
+ #[inline]
+ fn to_imr_addr(addr: &Ipv4Addr) -> c::in_addr {
+ c::in_addr {
+ s_addr: u32::from_ne_bytes(addr.octets()),
+ }
+ }
+
+ #[inline]
+ fn to_ipv6mr(multiaddr: &Ipv6Addr, interface: u32) -> c::ipv6_mreq {
+ c::ipv6_mreq {
+ ipv6mr_multiaddr: to_ipv6mr_multiaddr(multiaddr),
+ ipv6mr_ifindex: to_ipv6mr_interface(interface),
+ }
+ }
+
+ #[inline]
+ fn to_ipv6mr_multiaddr(multiaddr: &Ipv6Addr) -> c::in6_addr {
+ c::in6_addr {
+ in6_u: linux_raw_sys::general::in6_addr__bindgen_ty_1 {
+ u6_addr8: multiaddr.octets(),
+ },
+ }
+ }
+
+ #[inline]
+ fn to_ipv6mr_interface(interface: u32) -> c::c_int {
+ interface as c::c_int
+ }
+
+ #[inline]
+ fn from_bool(value: bool) -> c::c_uint {
+ c::c_uint::from(value)
+ }
+
+ #[inline]
+ fn to_bool(value: c::c_uint) -> bool {
+ value != 0
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/net/types.rs b/vendor/rustix/src/imp/linux_raw/net/types.rs
new file mode 100644
index 000000000..b8f786b3f
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/net/types.rs
@@ -0,0 +1,282 @@
+use super::super::c;
+use bitflags::bitflags;
+
+/// A type for holding raw integer socket types.
+#[doc(hidden)]
+pub type RawSocketType = u32;
+
+/// `SOCK_*` constants for use with [`socket`].
+///
+/// [`socket`]: crate::net::socket
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct SocketType(pub(crate) RawSocketType);
+
+#[rustfmt::skip]
+impl SocketType {
+ /// `SOCK_STREAM`
+ pub const STREAM: Self = Self(c::SOCK_STREAM);
+
+ /// `SOCK_DGRAM`
+ pub const DGRAM: Self = Self(c::SOCK_DGRAM);
+
+ /// `SOCK_SEQPACKET`
+ pub const SEQPACKET: Self = Self(c::SOCK_SEQPACKET);
+
+ /// `SOCK_RAW`
+ pub const RAW: Self = Self(c::SOCK_RAW);
+
+ /// `SOCK_RDM`
+ pub const RDM: Self = Self(c::SOCK_RDM);
+
+ /// Constructs a `SocketType` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawSocketType) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `SocketType`.
+ #[inline]
+ pub const fn as_raw(self) -> RawSocketType {
+ self.0
+ }
+}
+
+/// A type for holding raw integer address families.
+#[doc(hidden)]
+pub type RawAddressFamily = c::sa_family_t;
+
+/// `AF_*` constants.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct AddressFamily(pub(crate) RawAddressFamily);
+
+#[rustfmt::skip]
+impl AddressFamily {
+ /// `AF_UNSPEC`
+ pub const UNSPEC: Self = Self(c::AF_UNSPEC as _);
+ /// `AF_INET`
+ pub const INET: Self = Self(c::AF_INET as _);
+ /// `AF_INET6`
+ pub const INET6: Self = Self(c::AF_INET6 as _);
+ /// `AF_NETLINK`
+ pub const NETLINK: Self = Self(c::AF_NETLINK as _);
+ /// `AF_UNIX`, aka `AF_LOCAL`
+ #[doc(alias = "LOCAL")]
+ pub const UNIX: Self = Self(c::AF_UNIX as _);
+ /// `AF_AX25`
+ pub const AX25: Self = Self(c::AF_AX25 as _);
+ /// `AF_IPX`
+ pub const IPX: Self = Self(c::AF_IPX as _);
+ /// `AF_APPLETALK`
+ pub const APPLETALK: Self = Self(c::AF_APPLETALK as _);
+ /// `AF_NETROM`
+ pub const NETROM: Self = Self(c::AF_NETROM as _);
+ /// `AF_BRIDGE`
+ pub const BRIDGE: Self = Self(c::AF_BRIDGE as _);
+ /// `AF_ATMPVC`
+ pub const ATMPVC: Self = Self(c::AF_ATMPVC as _);
+ /// `AF_X25`
+ pub const X25: Self = Self(c::AF_X25 as _);
+ /// `AF_ROSE`
+ pub const ROSE: Self = Self(c::AF_ROSE as _);
+ /// `AF_DECnet`
+ #[allow(non_upper_case_globals)]
+ pub const DECnet: Self = Self(c::AF_DECnet as _);
+ /// `AF_NETBEUI`
+ pub const NETBEUI: Self = Self(c::AF_NETBEUI as _);
+ /// `AF_SECURITY`
+ pub const SECURITY: Self = Self(c::AF_SECURITY as _);
+ /// `AF_KEY`
+ pub const KEY: Self = Self(c::AF_KEY as _);
+ /// `AF_PACKET`
+ pub const PACKET: Self = Self(c::AF_PACKET as _);
+ /// `AF_ASH`
+ pub const ASH: Self = Self(c::AF_ASH as _);
+ /// `AF_ECONET`
+ pub const ECONET: Self = Self(c::AF_ECONET as _);
+ /// `AF_ATMSVC`
+ pub const ATMSVC: Self = Self(c::AF_ATMSVC as _);
+ /// `AF_RDS`
+ pub const RDS: Self = Self(c::AF_RDS as _);
+ /// `AF_SNA`
+ pub const SNA: Self = Self(c::AF_SNA as _);
+ /// `AF_IRDA`
+ pub const IRDA: Self = Self(c::AF_IRDA as _);
+ /// `AF_PPPOX`
+ pub const PPPOX: Self = Self(c::AF_PPPOX as _);
+ /// `AF_WANPIPE`
+ pub const WANPIPE: Self = Self(c::AF_WANPIPE as _);
+ /// `AF_LLC`
+ pub const LLC: Self = Self(c::AF_LLC as _);
+ /// `AF_CAN`
+ pub const CAN: Self = Self(c::AF_CAN as _);
+ /// `AF_TIPC`
+ pub const TIPC: Self = Self(c::AF_TIPC as _);
+ /// `AF_BLUETOOTH`
+ pub const BLUETOOTH: Self = Self(c::AF_BLUETOOTH as _);
+ /// `AF_IUCV`
+ pub const IUCV: Self = Self(c::AF_IUCV as _);
+ /// `AF_RXRPC`
+ pub const RXRPC: Self = Self(c::AF_RXRPC as _);
+ /// `AF_ISDN`
+ pub const ISDN: Self = Self(c::AF_ISDN as _);
+ /// `AF_PHONET`
+ pub const PHONET: Self = Self(c::AF_PHONET as _);
+ /// `AF_IEEE802154`
+ pub const IEEE802154: Self = Self(c::AF_IEEE802154 as _);
+
+ /// Constructs a `AddressFamily` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawAddressFamily) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `AddressFamily`.
+ #[inline]
+ pub const fn as_raw(self) -> RawAddressFamily {
+ self.0
+ }
+}
+
+/// A type for holding raw integer protocols.
+#[doc(hidden)]
+pub type RawProtocol = u32;
+
+/// `IPPROTO_*`
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct Protocol(pub(crate) RawProtocol);
+
+#[rustfmt::skip]
+impl Protocol {
+ /// `IPPROTO_IP`
+ pub const IP: Self = Self(c::IPPROTO_IP as _);
+ /// `IPPROTO_ICMP`
+ pub const ICMP: Self = Self(c::IPPROTO_ICMP as _);
+ /// `IPPROTO_IGMP`
+ pub const IGMP: Self = Self(c::IPPROTO_IGMP as _);
+ /// `IPPROTO_IPIP`
+ pub const IPIP: Self = Self(c::IPPROTO_IPIP as _);
+ /// `IPPROTO_TCP`
+ pub const TCP: Self = Self(c::IPPROTO_TCP as _);
+ /// `IPPROTO_EGP`
+ pub const EGP: Self = Self(c::IPPROTO_EGP as _);
+ /// `IPPROTO_PUP`
+ pub const PUP: Self = Self(c::IPPROTO_PUP as _);
+ /// `IPPROTO_UDP`
+ pub const UDP: Self = Self(c::IPPROTO_UDP as _);
+ /// `IPPROTO_IDP`
+ pub const IDP: Self = Self(c::IPPROTO_IDP as _);
+ /// `IPPROTO_TP`
+ pub const TP: Self = Self(c::IPPROTO_TP as _);
+ /// `IPPROTO_DCCP`
+ pub const DCCP: Self = Self(c::IPPROTO_DCCP as _);
+ /// `IPPROTO_IPV6`
+ pub const IPV6: Self = Self(c::IPPROTO_IPV6 as _);
+ /// `IPPROTO_RSVP`
+ pub const RSVP: Self = Self(c::IPPROTO_RSVP as _);
+ /// `IPPROTO_GRE`
+ pub const GRE: Self = Self(c::IPPROTO_GRE as _);
+ /// `IPPROTO_ESP`
+ pub const ESP: Self = Self(c::IPPROTO_ESP as _);
+ /// `IPPROTO_AH`
+ pub const AH: Self = Self(c::IPPROTO_AH as _);
+ /// `IPPROTO_MTP`
+ pub const MTP: Self = Self(c::IPPROTO_MTP as _);
+ /// `IPPROTO_BEETPH`
+ pub const BEETPH: Self = Self(c::IPPROTO_BEETPH as _);
+ /// `IPPROTO_ENCAP`
+ pub const ENCAP: Self = Self(c::IPPROTO_ENCAP as _);
+ /// `IPPROTO_PIM`
+ pub const PIM: Self = Self(c::IPPROTO_PIM as _);
+ /// `IPPROTO_COMP`
+ pub const COMP: Self = Self(c::IPPROTO_COMP as _);
+ /// `IPPROTO_SCTP`
+ pub const SCTP: Self = Self(c::IPPROTO_SCTP as _);
+ /// `IPPROTO_UDPLITE`
+ pub const UDPLITE: Self = Self(c::IPPROTO_UDPLITE as _);
+ /// `IPPROTO_MPLS`
+ pub const MPLS: Self = Self(c::IPPROTO_MPLS as _);
+ /// `IPPROTO_ETHERNET`
+ pub const ETHERNET: Self = Self(c::IPPROTO_ETHERNET as _);
+ /// `IPPROTO_RAW`
+ pub const RAW: Self = Self(c::IPPROTO_RAW as _);
+ /// `IPPROTO_MPTCP`
+ pub const MPTCP: Self = Self(c::IPPROTO_MPTCP as _);
+ /// `IPPROTO_FRAGMENT`
+ pub const FRAGMENT: Self = Self(c::IPPROTO_FRAGMENT as _);
+ /// `IPPROTO_ICMPV6`
+ pub const ICMPV6: Self = Self(c::IPPROTO_ICMPV6 as _);
+ /// `IPPROTO_MH`
+ pub const MH: Self = Self(c::IPPROTO_MH as _);
+ /// `IPPROTO_ROUTING`
+ pub const ROUTING: Self = Self(c::IPPROTO_ROUTING as _);
+
+ /// Constructs a `Protocol` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawProtocol) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `Protocol`.
+ #[inline]
+ pub const fn as_raw(self) -> RawProtocol {
+ self.0
+ }
+}
+
+/// `SHUT_*` constants for use with [`shutdown`].
+///
+/// [`shutdown`]: crate::net::shutdown
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u32)]
+pub enum Shutdown {
+ /// `SHUT_WR`—Disable further read operations.
+ Read = c::SHUT_RD,
+ /// `SHUT_WR`—Disable further write operations.
+ Write = c::SHUT_WR,
+ /// `SHUT_RDWR`—Disable further read and write operations.
+ ReadWrite = c::SHUT_RDWR,
+}
+
+bitflags! {
+ /// `SOCK_*` constants for use with [`accept_with`] and [`acceptfrom_with`].
+ ///
+ /// [`accept_with`]: crate::net::accept_with
+ /// [`acceptfrom_with`]: crate::net::acceptfrom_with
+ pub struct AcceptFlags: c::c_uint {
+ /// `SOCK_NONBLOCK`
+ const NONBLOCK = c::O_NONBLOCK;
+ /// `SOCK_CLOEXEC`
+ const CLOEXEC = c::O_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `SOCK_*` constants for use with [`socket`].
+ ///
+ /// [`socket`]: crate::net::socket
+ pub struct SocketFlags: c::c_uint {
+ /// `SOCK_NONBLOCK`
+ const NONBLOCK = c::O_NONBLOCK;
+
+ /// `SOCK_CLOEXEC`
+ const CLOEXEC = c::O_CLOEXEC;
+ }
+}
+
+/// Timeout identifier for use with [`set_socket_timeout`] and
+/// [`get_socket_timeout`].
+///
+/// [`set_socket_timeout`]: crate::net::sockopt::set_socket_timeout.
+/// [`get_socket_timeout`]: crate::net::sockopt::get_socket_timeout.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u32)]
+pub enum Timeout {
+ /// `SO_RCVTIMEO`—Timeout for receiving.
+ Recv = c::SO_RCVTIMEO_NEW,
+
+ /// `SO_SNDTIMEO`—Timeout for sending.
+ Send = c::SO_SNDTIMEO_NEW,
+}
diff --git a/vendor/rustix/src/imp/linux_raw/net/write_sockaddr.rs b/vendor/rustix/src/imp/linux_raw/net/write_sockaddr.rs
new file mode 100644
index 000000000..17abd96a0
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/net/write_sockaddr.rs
@@ -0,0 +1,60 @@
+//! The BSD sockets API requires us to read the `ss_family` field before
+//! we can interpret the rest of a `sockaddr` produced by the kernel.
+#![allow(unsafe_code)]
+
+use super::super::c;
+use crate::net::{SocketAddrAny, SocketAddrStorage, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
+use core::mem::size_of;
+
+pub(crate) unsafe fn write_sockaddr(
+ addr: &SocketAddrAny,
+ storage: *mut SocketAddrStorage,
+) -> usize {
+ match addr {
+ SocketAddrAny::V4(v4) => write_sockaddr_v4(v4, storage),
+ SocketAddrAny::V6(v6) => write_sockaddr_v6(v6, storage),
+ SocketAddrAny::Unix(unix) => write_sockaddr_unix(unix, storage),
+ }
+}
+
+pub(crate) unsafe fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in {
+ c::sockaddr_in {
+ sin_family: c::AF_INET as _,
+ sin_port: u16::to_be(v4.port()),
+ sin_addr: c::in_addr {
+ s_addr: u32::from_ne_bytes(v4.ip().octets()),
+ },
+ __pad: [0_u8; 8],
+ }
+}
+
+unsafe fn write_sockaddr_v4(v4: &SocketAddrV4, storage: *mut SocketAddrStorage) -> usize {
+ let encoded = encode_sockaddr_v4(v4);
+ core::ptr::write(storage.cast(), encoded);
+ size_of::<c::sockaddr_in>()
+}
+
+pub(crate) unsafe fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 {
+ c::sockaddr_in6 {
+ sin6_family: c::AF_INET6 as _,
+ sin6_port: u16::to_be(v6.port()),
+ sin6_flowinfo: u32::to_be(v6.flowinfo()),
+ sin6_addr: c::in6_addr {
+ in6_u: linux_raw_sys::general::in6_addr__bindgen_ty_1 {
+ u6_addr8: v6.ip().octets(),
+ },
+ },
+ sin6_scope_id: v6.scope_id(),
+ }
+}
+
+unsafe fn write_sockaddr_v6(v6: &SocketAddrV6, storage: *mut SocketAddrStorage) -> usize {
+ let encoded = encode_sockaddr_v6(v6);
+ core::ptr::write(storage.cast(), encoded);
+ size_of::<c::sockaddr_in6>()
+}
+
+unsafe fn write_sockaddr_unix(unix: &SocketAddrUnix, storage: *mut SocketAddrStorage) -> usize {
+ core::ptr::write(storage.cast(), unix.unix);
+ unix.len()
+}
diff --git a/vendor/rustix/src/imp/linux_raw/param/auxv.rs b/vendor/rustix/src/imp/linux_raw/param/auxv.rs
new file mode 100644
index 000000000..beed8613c
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/param/auxv.rs
@@ -0,0 +1,203 @@
+//! Linux auxv support.
+//!
+//! # Safety
+//!
+//! This uses raw pointers to locate and read the kernel-provided auxv array.
+#![allow(unsafe_code)]
+
+use super::super::c;
+use super::super::elf::{Elf_Ehdr, Elf_Phdr};
+#[cfg(feature = "param")]
+use crate::ffi::CStr;
+use core::mem::size_of;
+use core::ptr::null;
+#[cfg(feature = "runtime")]
+use core::slice;
+use linux_raw_sys::general::{
+ AT_CLKTCK, AT_EXECFN, AT_HWCAP, AT_HWCAP2, AT_NULL, AT_PAGESZ, AT_PHDR, AT_PHENT, AT_PHNUM,
+ AT_SYSINFO_EHDR,
+};
+
+#[cfg(feature = "param")]
+#[inline]
+pub(crate) fn page_size() -> usize {
+ auxv().page_size
+}
+
+#[cfg(feature = "param")]
+#[inline]
+pub(crate) fn clock_ticks_per_second() -> u64 {
+ auxv().clock_ticks_per_second as u64
+}
+
+#[cfg(feature = "param")]
+#[inline]
+pub(crate) fn linux_hwcap() -> (usize, usize) {
+ let auxv = auxv();
+ (auxv.hwcap, auxv.hwcap2)
+}
+
+#[cfg(feature = "param")]
+#[inline]
+pub(crate) fn linux_execfn() -> &'static CStr {
+ let execfn = auxv().execfn;
+
+ // Safety: We assume the `AT_EXECFN` value provided by the kernel is a
+ // valid pointer to a valid NUL-terminated array of bytes.
+ unsafe { CStr::from_ptr(execfn.cast()) }
+}
+
+#[cfg(feature = "runtime")]
+#[inline]
+pub(crate) fn exe_phdrs() -> (*const c::c_void, usize) {
+ let auxv = auxv();
+ (auxv.phdr.cast(), auxv.phnum)
+}
+
+#[cfg(feature = "runtime")]
+#[inline]
+pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] {
+ let auxv = auxv();
+
+ // Safety: We assume the `AT_PHDR` and `AT_PHNUM` values provided by the
+ // kernel form a valid slice.
+ unsafe { slice::from_raw_parts(auxv.phdr, auxv.phnum) }
+}
+
+#[inline]
+pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr {
+ auxv().sysinfo_ehdr
+}
+
+#[inline]
+fn auxv() -> &'static Auxv {
+ // Safety: `AUXV` is initialized from the `.init_array`, and we never
+ // mutate it thereafter, so it's effectively initialized read-only in all
+ // other code.
+ unsafe {
+ // Assert that the initialization has happened. On glibc and musl, this
+ // is handled automatically by `.init_array` functions. Otherwise,
+ // `rustix::process::init` must be called explicitly.
+ debug_assert_ne!(AUXV.page_size, 0);
+
+ &AUXV
+ }
+}
+
+/// A struct for holding fields obtained from the kernel-provided auxv array.
+struct Auxv {
+ page_size: usize,
+ clock_ticks_per_second: usize,
+ hwcap: usize,
+ hwcap2: usize,
+ sysinfo_ehdr: *const Elf_Ehdr,
+ phdr: *const Elf_Phdr,
+ phnum: usize,
+ execfn: *const c::c_char,
+}
+
+/// Data obtained from the kernel-provided auxv array. This is initialized at
+/// program startup below.
+static mut AUXV: Auxv = Auxv {
+ page_size: 0,
+ clock_ticks_per_second: 0,
+ hwcap: 0,
+ hwcap2: 0,
+ sysinfo_ehdr: null(),
+ phdr: null(),
+ phnum: 0,
+ execfn: null(),
+};
+
+/// GLIBC passes argc, argv, and envp to functions in .init_array, as a
+/// non-standard extension. Use priority 99 so that we run before any
+/// normal user-defined constructor functions.
+#[cfg(all(target_env = "gnu", not(target_vendor = "mustang")))]
+#[used]
+#[link_section = ".init_array.00099"]
+static INIT_ARRAY: unsafe extern "C" fn(c::c_int, *mut *mut u8, *mut *mut u8) = {
+ unsafe extern "C" fn function(_argc: c::c_int, _argv: *mut *mut u8, envp: *mut *mut u8) {
+ init_from_envp(envp);
+ }
+ function
+};
+
+/// For musl, assume that `__environ` is available and points to the original
+/// environment from the kernel, so we can find the auxv array in memory after
+/// it. Use priority 99 so that we run before any normal user-defined
+/// constructor functions.
+///
+/// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---environ.html>
+#[cfg(all(target_env = "musl", not(target_vendor = "mustang")))]
+#[used]
+#[link_section = ".init_array.00099"]
+static INIT_ARRAY: unsafe extern "C" fn() = {
+ unsafe extern "C" fn function() {
+ extern "C" {
+ static __environ: *mut *mut u8;
+ }
+
+ init_from_envp(__environ)
+ }
+ function
+};
+
+/// On mustang or any non-musl non-glibic platform where we don't know that we
+/// have `.init_array`, we export a function to be called during
+/// initialization, and passed a pointer to the original environment variable
+/// block set up by the OS.
+#[cfg(any(
+ target_vendor = "mustang",
+ not(any(target_env = "gnu", target_env = "musl")),
+))]
+#[inline]
+pub(crate) unsafe fn init(envp: *mut *mut u8) {
+ init_from_envp(envp);
+}
+
+/// # Safety
+///
+/// This must be passed a pointer to the environment variable buffer
+/// provided by the kernel, which is followed in memory by the auxv array.
+unsafe fn init_from_envp(mut envp: *mut *mut u8) {
+ while !(*envp).is_null() {
+ envp = envp.add(1);
+ }
+ init_from_auxp(envp.add(1).cast())
+}
+
+/// # Safety
+///
+/// This must be passed a pointer to the auxv array provided by the kernel.
+unsafe fn init_from_auxp(mut auxp: *const Elf_auxv_t) {
+ loop {
+ let Elf_auxv_t { a_type, a_val } = *auxp;
+ match a_type as _ {
+ AT_PAGESZ => AUXV.page_size = a_val as usize,
+ AT_CLKTCK => AUXV.clock_ticks_per_second = a_val as usize,
+ AT_HWCAP => AUXV.hwcap = a_val as usize,
+ AT_HWCAP2 => AUXV.hwcap2 = a_val as usize,
+ AT_SYSINFO_EHDR => AUXV.sysinfo_ehdr = a_val.cast(),
+ AT_PHDR => AUXV.phdr = a_val.cast(),
+ AT_PHNUM => AUXV.phnum = a_val as usize,
+ AT_PHENT => assert_eq!(a_val as usize, size_of::<Elf_Phdr>()),
+ AT_EXECFN => AUXV.execfn = a_val.cast(),
+ AT_NULL => break,
+ _ => (),
+ }
+ auxp = auxp.add(1);
+ }
+}
+
+// ELF ABI
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct Elf_auxv_t {
+ a_type: usize,
+
+ // Some of the values in the auxv array are pointers, so we make `a_val` a
+ // pointer, in order to preserve their provenance. For the values which are
+ // integers, we cast this to `usize`.
+ a_val: *const (),
+}
diff --git a/vendor/rustix/src/imp/linux_raw/param/mod.rs b/vendor/rustix/src/imp/linux_raw/param/mod.rs
new file mode 100644
index 000000000..2cb2fe78a
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/param/mod.rs
@@ -0,0 +1 @@
+pub(crate) mod auxv;
diff --git a/vendor/rustix/src/imp/linux_raw/process/cpu_set.rs b/vendor/rustix/src/imp/linux_raw/process/cpu_set.rs
new file mode 100644
index 000000000..10c5f478e
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/process/cpu_set.rs
@@ -0,0 +1,47 @@
+#![allow(non_snake_case)]
+
+use super::types::RawCpuSet;
+use core::mem::size_of_val;
+
+#[inline]
+pub(crate) fn CPU_SET(cpu: usize, cpuset: &mut RawCpuSet) {
+ let size_in_bits = 8 * size_of_val(&cpuset.bits[0]); // 32, 64 etc
+ let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits);
+ cpuset.bits[idx] |= 1 << offset
+}
+
+#[inline]
+pub(crate) fn CPU_ZERO(cpuset: &mut RawCpuSet) {
+ // TODO: With, Rust 1.50, use `cpuset.bits.fill(0)` instead.
+ for element in &mut cpuset.bits {
+ *element = 0;
+ }
+}
+
+#[inline]
+pub(crate) fn CPU_CLR(cpu: usize, cpuset: &mut RawCpuSet) {
+ let size_in_bits = 8 * size_of_val(&cpuset.bits[0]); // 32, 64 etc
+ let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits);
+ cpuset.bits[idx] &= !(1 << offset)
+}
+
+#[inline]
+pub(crate) fn CPU_ISSET(cpu: usize, cpuset: &RawCpuSet) -> bool {
+ let size_in_bits = 8 * size_of_val(&cpuset.bits[0]);
+ let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits);
+ (cpuset.bits[idx] & (1 << offset)) != 0
+}
+
+#[inline]
+pub(crate) fn CPU_COUNT_S(size_in_bytes: usize, cpuset: &RawCpuSet) -> u32 {
+ let size_of_mask = size_of_val(&cpuset.bits[0]);
+ let idx = size_in_bytes / size_of_mask;
+ cpuset.bits[..idx]
+ .iter()
+ .fold(0, |acc, i| acc + i.count_ones())
+}
+
+#[inline]
+pub(crate) fn CPU_COUNT(cpuset: &RawCpuSet) -> u32 {
+ CPU_COUNT_S(core::mem::size_of::<RawCpuSet>(), cpuset)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/process/mod.rs b/vendor/rustix/src/imp/linux_raw/process/mod.rs
new file mode 100644
index 000000000..9b2c25f91
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/process/mod.rs
@@ -0,0 +1,4 @@
+pub(crate) mod cpu_set;
+pub(crate) mod syscalls;
+pub(crate) mod types;
+pub(crate) mod wait;
diff --git a/vendor/rustix/src/imp/linux_raw/process/syscalls.rs b/vendor/rustix/src/imp/linux_raw/process/syscalls.rs
new file mode 100644
index 000000000..3c833ede7
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/process/syscalls.rs
@@ -0,0 +1,517 @@
+//! linux_raw syscalls supporting `rustix::process`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::c;
+use super::super::conv::{
+ by_mut, by_ref, c_int, c_uint, negative_pid, pass_usize, ret, ret_c_int, ret_c_uint,
+ ret_infallible, ret_usize, ret_usize_infallible, size_of, slice_just_addr, slice_mut, zero,
+};
+use super::types::{RawCpuSet, RawUname};
+use crate::fd::BorrowedFd;
+use crate::ffi::CStr;
+use crate::io;
+use crate::process::{
+ Cpuid, Gid, MembarrierCommand, MembarrierQuery, Pid, RawNonZeroPid, RawPid, Resource, Rlimit,
+ Signal, Uid, WaitOptions, WaitStatus,
+};
+use core::convert::TryInto;
+use core::mem::MaybeUninit;
+use core::ptr::{null, null_mut};
+use linux_raw_sys::general::{
+ __kernel_gid_t, __kernel_pid_t, __kernel_uid_t, membarrier_cmd, membarrier_cmd_flag, rlimit,
+ rlimit64, PRIO_PGRP, PRIO_PROCESS, PRIO_USER, RLIM64_INFINITY, RLIM_INFINITY,
+};
+
+#[inline]
+pub(crate) fn chdir(filename: &CStr) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_chdir, filename)) }
+}
+
+#[inline]
+pub(crate) fn fchdir(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_fchdir, fd)) }
+}
+
+#[inline]
+pub(crate) fn getcwd(buf: &mut [u8]) -> io::Result<usize> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+ unsafe { ret_usize(syscall!(__NR_getcwd, buf_addr_mut, buf_len)) }
+}
+
+#[inline]
+pub(crate) fn membarrier_query() -> MembarrierQuery {
+ unsafe {
+ match ret_c_uint(syscall!(
+ __NR_membarrier,
+ c_int(membarrier_cmd::MEMBARRIER_CMD_QUERY as _),
+ c_uint(0)
+ )) {
+ Ok(query) => {
+ // Safety: The safety of `from_bits_unchecked` is discussed
+ // [here]. Our "source of truth" is Linux, and here, the
+ // `query` value is coming from Linux, so we know it only
+ // contains "source of truth" valid bits.
+ //
+ // [here]: https://github.com/bitflags/bitflags/pull/207#issuecomment-671668662
+ MembarrierQuery::from_bits_unchecked(query)
+ }
+ Err(_) => MembarrierQuery::empty(),
+ }
+ }
+}
+
+#[inline]
+pub(crate) fn membarrier(cmd: MembarrierCommand) -> io::Result<()> {
+ unsafe { ret(syscall!(__NR_membarrier, cmd, c_uint(0))) }
+}
+
+#[inline]
+pub(crate) fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
+ unsafe {
+ ret(syscall!(
+ __NR_membarrier,
+ cmd,
+ c_uint(membarrier_cmd_flag::MEMBARRIER_CMD_FLAG_CPU as _),
+ cpu
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn getpid() -> Pid {
+ unsafe {
+ let pid: i32 = ret_usize_infallible(syscall_readonly!(__NR_getpid)) as __kernel_pid_t;
+ debug_assert!(pid > 0);
+ Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid as u32))
+ }
+}
+
+#[inline]
+pub(crate) fn getppid() -> Option<Pid> {
+ unsafe {
+ let ppid: i32 = ret_usize_infallible(syscall_readonly!(__NR_getppid)) as __kernel_pid_t;
+ Pid::from_raw(ppid as u32)
+ }
+}
+
+#[inline]
+pub(crate) fn getgid() -> Gid {
+ #[cfg(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm"))]
+ unsafe {
+ let gid: i32 =
+ (ret_usize_infallible(syscall_readonly!(__NR_getgid32)) as __kernel_gid_t).into();
+ Gid::from_raw(gid as u32)
+ }
+ #[cfg(not(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm")))]
+ unsafe {
+ let gid = ret_usize_infallible(syscall_readonly!(__NR_getgid)) as __kernel_gid_t;
+ Gid::from_raw(gid as u32)
+ }
+}
+
+#[inline]
+pub(crate) fn getegid() -> Gid {
+ #[cfg(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm"))]
+ unsafe {
+ let gid: i32 =
+ (ret_usize_infallible(syscall_readonly!(__NR_getegid32)) as __kernel_gid_t).into();
+ Gid::from_raw(gid as u32)
+ }
+ #[cfg(not(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm")))]
+ unsafe {
+ let gid = ret_usize_infallible(syscall_readonly!(__NR_getegid)) as __kernel_gid_t;
+ Gid::from_raw(gid as u32)
+ }
+}
+
+#[inline]
+pub(crate) fn getuid() -> Uid {
+ #[cfg(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm"))]
+ unsafe {
+ let uid = (ret_usize_infallible(syscall_readonly!(__NR_getuid32)) as __kernel_uid_t).into();
+ Uid::from_raw(uid)
+ }
+ #[cfg(not(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm")))]
+ unsafe {
+ let uid = ret_usize_infallible(syscall_readonly!(__NR_getuid)) as __kernel_uid_t;
+ Uid::from_raw(uid as u32)
+ }
+}
+
+#[inline]
+pub(crate) fn geteuid() -> Uid {
+ #[cfg(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm"))]
+ unsafe {
+ let uid: i32 =
+ (ret_usize_infallible(syscall_readonly!(__NR_geteuid32)) as __kernel_uid_t).into();
+ Uid::from_raw(uid as u32)
+ }
+ #[cfg(not(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm")))]
+ unsafe {
+ let uid = ret_usize_infallible(syscall_readonly!(__NR_geteuid)) as __kernel_uid_t;
+ Uid::from_raw(uid as u32)
+ }
+}
+
+#[inline]
+pub(crate) fn sched_getaffinity(pid: Option<Pid>, cpuset: &mut RawCpuSet) -> io::Result<()> {
+ unsafe {
+ // The raw linux syscall returns the size (in bytes) of the `cpumask_t`
+ // data type that is used internally by the kernel to represent the CPU
+ // set bit mask.
+ let size = ret_usize(syscall!(
+ __NR_sched_getaffinity,
+ c_uint(Pid::as_raw(pid)),
+ size_of::<RawCpuSet, _>(),
+ by_mut(&mut cpuset.bits)
+ ))?;
+ let bytes = (cpuset as *mut RawCpuSet).cast::<u8>();
+ let rest = bytes.wrapping_add(size);
+ // Zero every byte in the cpuset not set by the kernel.
+ rest.write_bytes(0, core::mem::size_of::<RawCpuSet>() - size);
+ Ok(())
+ }
+}
+
+#[inline]
+pub(crate) fn sched_setaffinity(pid: Option<Pid>, cpuset: &RawCpuSet) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_sched_setaffinity,
+ c_uint(Pid::as_raw(pid)),
+ size_of::<RawCpuSet, _>(),
+ slice_just_addr(&cpuset.bits)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn sched_yield() {
+ unsafe {
+ // See the documentation for [`crate::process::sched_yield`] for why
+ // errors are ignored.
+ syscall_readonly!(__NR_sched_yield).decode_void();
+ }
+}
+
+#[inline]
+pub(crate) fn uname() -> RawUname {
+ let mut uname = MaybeUninit::<RawUname>::uninit();
+ unsafe {
+ ret(syscall!(__NR_uname, &mut uname)).unwrap();
+ uname.assume_init()
+ }
+}
+
+#[inline]
+pub(crate) fn nice(inc: i32) -> io::Result<i32> {
+ let priority = if inc > -40 && inc < 40 {
+ inc + getpriority_process(None)?
+ } else {
+ inc
+ }
+ // TODO: With Rust 1.50, use `.clamp` instead of `.min` and `.max`.
+ //.clamp(-20, 19);
+ .min(19)
+ .max(-20);
+ setpriority_process(None, priority)?;
+ Ok(priority)
+}
+
+#[inline]
+pub(crate) fn getpriority_user(uid: Uid) -> io::Result<i32> {
+ unsafe {
+ Ok(20
+ - ret_c_int(syscall_readonly!(
+ __NR_getpriority,
+ c_uint(PRIO_USER),
+ c_uint(uid.as_raw())
+ ))?)
+ }
+}
+
+#[inline]
+pub(crate) fn getpriority_pgrp(pgid: Option<Pid>) -> io::Result<i32> {
+ unsafe {
+ Ok(20
+ - ret_c_int(syscall_readonly!(
+ __NR_getpriority,
+ c_uint(PRIO_PGRP),
+ c_uint(Pid::as_raw(pgid))
+ ))?)
+ }
+}
+
+#[inline]
+pub(crate) fn getpriority_process(pid: Option<Pid>) -> io::Result<i32> {
+ unsafe {
+ Ok(20
+ - ret_c_int(syscall_readonly!(
+ __NR_getpriority,
+ c_uint(PRIO_PROCESS),
+ c_uint(Pid::as_raw(pid))
+ ))?)
+ }
+}
+
+#[inline]
+pub(crate) fn setpriority_user(uid: Uid, priority: i32) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_setpriority,
+ c_uint(PRIO_USER),
+ c_uint(uid.as_raw()),
+ c_int(priority)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn setpriority_pgrp(pgid: Option<Pid>, priority: i32) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_setpriority,
+ c_uint(PRIO_PGRP),
+ c_uint(Pid::as_raw(pgid)),
+ c_int(priority)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn setpriority_process(pid: Option<Pid>, priority: i32) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_setpriority,
+ c_uint(PRIO_PROCESS),
+ c_uint(Pid::as_raw(pid)),
+ c_int(priority)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn getrlimit(limit: Resource) -> Rlimit {
+ let mut result = MaybeUninit::<rlimit64>::uninit();
+ unsafe {
+ match ret(syscall!(
+ __NR_prlimit64,
+ c_uint(0),
+ limit,
+ null::<c::c_void>(),
+ &mut result
+ )) {
+ Ok(()) => rlimit_from_linux(result.assume_init()),
+ Err(e) => {
+ debug_assert_eq!(e, io::Errno::NOSYS);
+ getrlimit_old(limit)
+ }
+ }
+ }
+}
+
+/// The old 32-bit-only `getrlimit` syscall, for when we lack the new
+/// `prlimit64`.
+unsafe fn getrlimit_old(limit: Resource) -> Rlimit {
+ let mut result = MaybeUninit::<rlimit>::uninit();
+
+ // On these platforms, `__NR_getrlimit` is called `__NR_ugetrlimit`.
+ #[cfg(any(
+ target_arch = "arm",
+ target_arch = "powerpc",
+ target_arch = "powerpc64",
+ target_arch = "x86",
+ ))]
+ {
+ ret_infallible(syscall!(__NR_ugetrlimit, limit, &mut result));
+ }
+
+ // On these platforms, it's just `__NR_getrlimit`.
+ #[cfg(not(any(
+ target_arch = "arm",
+ target_arch = "powerpc",
+ target_arch = "powerpc64",
+ target_arch = "x86",
+ )))]
+ {
+ ret_infallible(syscall!(__NR_getrlimit, limit, &mut result));
+ }
+
+ rlimit_from_linux_old(result.assume_init())
+}
+
+#[inline]
+pub(crate) fn setrlimit(limit: Resource, new: Rlimit) -> io::Result<()> {
+ unsafe {
+ let lim = rlimit_to_linux(new.clone())?;
+ match ret(syscall_readonly!(
+ __NR_prlimit64,
+ c_uint(0),
+ limit,
+ by_ref(&lim),
+ null_mut::<c::c_void>()
+ )) {
+ Ok(()) => Ok(()),
+ Err(io::Errno::NOSYS) => setrlimit_old(limit, new),
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// The old 32-bit-only `setrlimit` syscall, for when we lack the new
+/// `prlimit64`.
+unsafe fn setrlimit_old(limit: Resource, new: Rlimit) -> io::Result<()> {
+ let lim = rlimit_to_linux_old(new)?;
+ ret(syscall_readonly!(__NR_setrlimit, limit, by_ref(&lim)))
+}
+
+#[inline]
+pub(crate) fn prlimit(pid: Option<Pid>, limit: Resource, new: Rlimit) -> io::Result<Rlimit> {
+ let lim = rlimit_to_linux(new)?;
+ let mut result = MaybeUninit::<rlimit64>::uninit();
+ unsafe {
+ match ret(syscall!(
+ __NR_prlimit64,
+ c_uint(Pid::as_raw(pid)),
+ limit,
+ by_ref(&lim),
+ &mut result
+ )) {
+ Ok(()) => Ok(rlimit_from_linux(result.assume_init())),
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// Convert a Rust [`Rlimit`] to a C `rlimit64`.
+#[inline]
+fn rlimit_from_linux(lim: rlimit64) -> Rlimit {
+ let current = if lim.rlim_cur == RLIM64_INFINITY as _ {
+ None
+ } else {
+ Some(lim.rlim_cur)
+ };
+ let maximum = if lim.rlim_max == RLIM64_INFINITY as _ {
+ None
+ } else {
+ Some(lim.rlim_max)
+ };
+ Rlimit { current, maximum }
+}
+
+/// Convert a C `rlimit64` to a Rust `Rlimit`.
+#[inline]
+fn rlimit_to_linux(lim: Rlimit) -> io::Result<rlimit64> {
+ let rlim_cur = match lim.current {
+ Some(r) => r,
+ None => RLIM64_INFINITY as _,
+ };
+ let rlim_max = match lim.maximum {
+ Some(r) => r,
+ None => RLIM64_INFINITY as _,
+ };
+ Ok(rlimit64 { rlim_cur, rlim_max })
+}
+
+/// Like `rlimit_from_linux` but uses Linux's old 32-bit `rlimit`.
+#[allow(clippy::useless_conversion)]
+fn rlimit_from_linux_old(lim: rlimit) -> Rlimit {
+ let current = if lim.rlim_cur == RLIM_INFINITY as _ {
+ None
+ } else {
+ Some(lim.rlim_cur.into())
+ };
+ let maximum = if lim.rlim_max == RLIM_INFINITY as _ {
+ None
+ } else {
+ Some(lim.rlim_max.into())
+ };
+ Rlimit { current, maximum }
+}
+
+/// Like `rlimit_to_linux` but uses Linux's old 32-bit `rlimit`.
+#[allow(clippy::useless_conversion)]
+fn rlimit_to_linux_old(lim: Rlimit) -> io::Result<rlimit> {
+ let rlim_cur = match lim.current {
+ Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?,
+ None => RLIM_INFINITY as _,
+ };
+ let rlim_max = match lim.maximum {
+ Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?,
+ None => RLIM_INFINITY as _,
+ };
+ Ok(rlimit { rlim_cur, rlim_max })
+}
+
+#[inline]
+pub(crate) fn wait(waitopts: WaitOptions) -> io::Result<Option<(Pid, WaitStatus)>> {
+ _waitpid(!0, waitopts)
+}
+
+#[inline]
+pub(crate) fn waitpid(
+ pid: Option<Pid>,
+ waitopts: WaitOptions,
+) -> io::Result<Option<(Pid, WaitStatus)>> {
+ _waitpid(Pid::as_raw(pid), waitopts)
+}
+
+#[inline]
+pub(crate) fn _waitpid(
+ pid: RawPid,
+ waitopts: WaitOptions,
+) -> io::Result<Option<(Pid, WaitStatus)>> {
+ unsafe {
+ let mut status = MaybeUninit::<u32>::uninit();
+ let pid = ret_c_uint(syscall!(
+ __NR_wait4,
+ c_int(pid as _),
+ &mut status,
+ c_int(waitopts.bits() as _),
+ zero()
+ ))?;
+ Ok(RawNonZeroPid::new(pid).map(|non_zero| {
+ (
+ Pid::from_raw_nonzero(non_zero),
+ WaitStatus::new(status.assume_init()),
+ )
+ }))
+ }
+}
+
+#[cfg(feature = "runtime")]
+#[inline]
+pub(crate) fn exit_group(code: c::c_int) -> ! {
+ unsafe { syscall_noreturn!(__NR_exit_group, c_int(code)) }
+}
+
+#[inline]
+pub(crate) fn setsid() -> io::Result<Pid> {
+ unsafe {
+ let pid = ret_usize(syscall_readonly!(__NR_setsid))?;
+ debug_assert!(pid > 0);
+ Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(
+ pid as u32,
+ )))
+ }
+}
+
+#[inline]
+pub(crate) fn kill_process(pid: Pid, sig: Signal) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_kill, pid, sig)) }
+}
+
+#[inline]
+pub(crate) fn kill_process_group(pid: Pid, sig: Signal) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_kill, negative_pid(pid), sig)) }
+}
+
+#[inline]
+pub(crate) fn kill_current_process_group(sig: Signal) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_kill, pass_usize(0), sig)) }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/process/types.rs b/vendor/rustix/src/imp/linux_raw/process/types.rs
new file mode 100644
index 000000000..53e2c7db1
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/process/types.rs
@@ -0,0 +1,246 @@
+use super::super::c;
+use linux_raw_sys::general::membarrier_cmd;
+
+/// A command for use with [`membarrier`] and [`membarrier_cpu`].
+///
+/// For `MEMBARRIER_CMD_QUERY`, see [`membarrier_query`].
+///
+/// [`membarrier`]: crate::process::membarrier
+/// [`membarrier_cpu`]: crate::process::membarrier_cpu
+/// [`membarrier_query`]: crate::process::membarrier_query
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+#[repr(u32)]
+pub enum MembarrierCommand {
+ /// `MEMBARRIER_CMD_GLOBAL`
+ #[doc(alias = "Shared")]
+ #[doc(alias = "MEMBARRIER_CMD_SHARED")]
+ Global = membarrier_cmd::MEMBARRIER_CMD_GLOBAL as _,
+ /// `MEMBARRIER_CMD_GLOBAL_EXPEDITED`
+ GlobalExpedited = membarrier_cmd::MEMBARRIER_CMD_GLOBAL_EXPEDITED as _,
+ /// `MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED`
+ RegisterGlobalExpedited = membarrier_cmd::MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED as _,
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED`
+ PrivateExpedited = membarrier_cmd::MEMBARRIER_CMD_PRIVATE_EXPEDITED as _,
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED`
+ RegisterPrivateExpedited = membarrier_cmd::MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED as _,
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE`
+ PrivateExpeditedSyncCore = membarrier_cmd::MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE as _,
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE`
+ RegisterPrivateExpeditedSyncCore =
+ membarrier_cmd::MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE as _,
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
+ PrivateExpeditedRseq = membarrier_cmd::MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ as _,
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
+ RegisterPrivateExpeditedRseq =
+ membarrier_cmd::MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ as _,
+}
+
+/// A resource value for use with [`getrlimit`], [`setrlimit`], and
+/// [`prlimit`].
+///
+/// [`getrlimit`]: crate::process::getrlimit
+/// [`setrlimit`]: crate::process::setrlimit
+/// [`prlimit`]: crate::process::prlimit
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[repr(u32)]
+pub enum Resource {
+ /// `RLIMIT_CPU`
+ Cpu = linux_raw_sys::general::RLIMIT_CPU,
+ /// `RLIMIT_FSIZE`
+ Fsize = linux_raw_sys::general::RLIMIT_FSIZE,
+ /// `RLIMIT_DATA`
+ Data = linux_raw_sys::general::RLIMIT_DATA,
+ /// `RLIMIT_STACK`
+ Stack = linux_raw_sys::general::RLIMIT_STACK,
+ /// `RLIMIT_CORE`
+ Core = linux_raw_sys::general::RLIMIT_CORE,
+ /// `RLIMIT_RSS`
+ Rss = linux_raw_sys::general::RLIMIT_RSS,
+ /// `RLIMIT_NPROC`
+ Nproc = linux_raw_sys::general::RLIMIT_NPROC,
+ /// `RLIMIT_NOFILE`
+ Nofile = linux_raw_sys::general::RLIMIT_NOFILE,
+ /// `RLIMIT_MEMLOCK`
+ Memlock = linux_raw_sys::general::RLIMIT_MEMLOCK,
+ /// `RLIMIT_AS`
+ As = linux_raw_sys::general::RLIMIT_AS,
+ /// `RLIMIT_LOCKS`
+ Locks = linux_raw_sys::general::RLIMIT_LOCKS,
+ /// `RLIMIT_SIGPENDING`
+ Sigpending = linux_raw_sys::general::RLIMIT_SIGPENDING,
+ /// `RLIMIT_MSGQUEUE`
+ Msgqueue = linux_raw_sys::general::RLIMIT_MSGQUEUE,
+ /// `RLIMIT_NICE`
+ Nice = linux_raw_sys::general::RLIMIT_NICE,
+ /// `RLIMIT_RTPRIO`
+ Rtprio = linux_raw_sys::general::RLIMIT_RTPRIO,
+ /// `RLIMIT_RTTIME`
+ Rttime = linux_raw_sys::general::RLIMIT_RTTIME,
+}
+
+/// A signal number for use with [`kill_process`] and [`kill_process_group`].
+///
+/// [`kill_process`]: crate::process::kill_process
+/// [`kill_process_group`]: crate::process::kill_process_group
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[repr(u32)]
+pub enum Signal {
+ /// `SIGHUP`
+ Hup = linux_raw_sys::general::SIGHUP,
+ /// `SIGINT`
+ Int = linux_raw_sys::general::SIGINT,
+ /// `SIGQUIT`
+ Quit = linux_raw_sys::general::SIGQUIT,
+ /// `SIGILL`
+ Ill = linux_raw_sys::general::SIGILL,
+ /// `SIGTRAP`
+ Trap = linux_raw_sys::general::SIGTRAP,
+ /// `SIGABRT`, aka `SIGIOT`
+ #[doc(alias = "Iot")]
+ #[doc(alias = "Abrt")]
+ Abort = linux_raw_sys::general::SIGABRT,
+ /// `SIGBUS`
+ Bus = linux_raw_sys::general::SIGBUS,
+ /// `SIGFPE`
+ Fpe = linux_raw_sys::general::SIGFPE,
+ /// `SIGKILL`
+ Kill = linux_raw_sys::general::SIGKILL,
+ /// `SIGUSR1`
+ Usr1 = linux_raw_sys::general::SIGUSR1,
+ /// `SIGSEGV`
+ Segv = linux_raw_sys::general::SIGSEGV,
+ /// `SIGUSR2`
+ Usr2 = linux_raw_sys::general::SIGUSR2,
+ /// `SIGPIPE`
+ Pipe = linux_raw_sys::general::SIGPIPE,
+ /// `SIGALRM`
+ #[doc(alias = "Alrm")]
+ Alarm = linux_raw_sys::general::SIGALRM,
+ /// `SIGTERM`
+ Term = linux_raw_sys::general::SIGTERM,
+ /// `SIGSTKFLT`
+ #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+ Stkflt = linux_raw_sys::general::SIGSTKFLT,
+ /// `SIGCHLD`
+ #[doc(alias = "Chld")]
+ Child = linux_raw_sys::general::SIGCHLD,
+ /// `SIGCONT`
+ Cont = linux_raw_sys::general::SIGCONT,
+ /// `SIGSTOP`
+ Stop = linux_raw_sys::general::SIGSTOP,
+ /// `SIGTSTP`
+ Tstp = linux_raw_sys::general::SIGTSTP,
+ /// `SIGTTIN`
+ Ttin = linux_raw_sys::general::SIGTTIN,
+ /// `SIGTTOU`
+ Ttou = linux_raw_sys::general::SIGTTOU,
+ /// `SIGURG`
+ Urg = linux_raw_sys::general::SIGURG,
+ /// `SIGXCPU`
+ Xcpu = linux_raw_sys::general::SIGXCPU,
+ /// `SIGXFSZ`
+ Xfsz = linux_raw_sys::general::SIGXFSZ,
+ /// `SIGVTALRM`
+ #[doc(alias = "Vtalrm")]
+ Vtalarm = linux_raw_sys::general::SIGVTALRM,
+ /// `SIGPROF`
+ Prof = linux_raw_sys::general::SIGPROF,
+ /// `SIGWINCH`
+ Winch = linux_raw_sys::general::SIGWINCH,
+ /// `SIGIO`, aka `SIGPOLL`
+ #[doc(alias = "Poll")]
+ Io = linux_raw_sys::general::SIGIO,
+ /// `SIGPWR`
+ #[doc(alias = "Pwr")]
+ Power = linux_raw_sys::general::SIGPWR,
+ /// `SIGSYS`, aka `SIGUNUSED`
+ #[doc(alias = "Unused")]
+ Sys = linux_raw_sys::general::SIGSYS,
+ /// `SIGRTMIN`
+ Rtmin = linux_raw_sys::general::SIGRTMIN,
+}
+
+impl Signal {
+ /// Convert a raw signal number into a `Signal`, if possible.
+ pub fn from_raw(sig: i32) -> Option<Self> {
+ match sig as _ {
+ linux_raw_sys::general::SIGHUP => Some(Self::Hup),
+ linux_raw_sys::general::SIGINT => Some(Self::Int),
+ linux_raw_sys::general::SIGQUIT => Some(Self::Quit),
+ linux_raw_sys::general::SIGILL => Some(Self::Ill),
+ linux_raw_sys::general::SIGTRAP => Some(Self::Trap),
+ linux_raw_sys::general::SIGABRT => Some(Self::Abort),
+ linux_raw_sys::general::SIGBUS => Some(Self::Bus),
+ linux_raw_sys::general::SIGFPE => Some(Self::Fpe),
+ linux_raw_sys::general::SIGKILL => Some(Self::Kill),
+ linux_raw_sys::general::SIGUSR1 => Some(Self::Usr1),
+ linux_raw_sys::general::SIGSEGV => Some(Self::Segv),
+ linux_raw_sys::general::SIGUSR2 => Some(Self::Usr2),
+ linux_raw_sys::general::SIGPIPE => Some(Self::Pipe),
+ linux_raw_sys::general::SIGALRM => Some(Self::Alarm),
+ linux_raw_sys::general::SIGTERM => Some(Self::Term),
+ #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+ linux_raw_sys::general::SIGSTKFLT => Some(Self::Stkflt),
+ linux_raw_sys::general::SIGCHLD => Some(Self::Child),
+ linux_raw_sys::general::SIGCONT => Some(Self::Cont),
+ linux_raw_sys::general::SIGSTOP => Some(Self::Stop),
+ linux_raw_sys::general::SIGTSTP => Some(Self::Tstp),
+ linux_raw_sys::general::SIGTTIN => Some(Self::Ttin),
+ linux_raw_sys::general::SIGTTOU => Some(Self::Ttou),
+ linux_raw_sys::general::SIGURG => Some(Self::Urg),
+ linux_raw_sys::general::SIGXCPU => Some(Self::Xcpu),
+ linux_raw_sys::general::SIGXFSZ => Some(Self::Xfsz),
+ linux_raw_sys::general::SIGVTALRM => Some(Self::Vtalarm),
+ linux_raw_sys::general::SIGPROF => Some(Self::Prof),
+ linux_raw_sys::general::SIGWINCH => Some(Self::Winch),
+ linux_raw_sys::general::SIGIO => Some(Self::Io),
+ linux_raw_sys::general::SIGPWR => Some(Self::Power),
+ linux_raw_sys::general::SIGSYS => Some(Self::Sys),
+ linux_raw_sys::general::SIGRTMIN => Some(Self::Rtmin),
+ _ => None,
+ }
+ }
+}
+
+/// `EXIT_SUCCESS`
+pub const EXIT_SUCCESS: c::c_int = 0;
+/// `EXIT_FAILURE`
+pub const EXIT_FAILURE: c::c_int = 1;
+/// The status value of a child terminated with `SIGABRT`.
+pub const EXIT_SIGNALED_SIGABRT: c::c_int = 128 + linux_raw_sys::general::SIGABRT as i32;
+
+/// A process identifier as a raw integer.
+pub type RawPid = u32;
+/// A non-zero process identifier as a raw non-zero integer.
+pub type RawNonZeroPid = core::num::NonZeroU32;
+/// A group identifier as a raw integer.
+pub type RawGid = u32;
+/// A user identifier as a raw integer.
+pub type RawUid = u32;
+/// A CPU identifier as a raw integer.
+pub type RawCpuid = u32;
+
+pub(crate) type RawUname = linux_raw_sys::general::new_utsname;
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub(crate) struct RawCpuSet {
+ #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))]
+ pub(crate) bits: [u32; 32],
+ #[cfg(not(all(target_pointer_width = "32", not(target_arch = "x86_64"))))]
+ pub(crate) bits: [u64; 16],
+}
+
+#[inline]
+pub(crate) fn raw_cpu_set_new() -> RawCpuSet {
+ #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))]
+ {
+ RawCpuSet { bits: [0; 32] }
+ }
+ #[cfg(not(all(target_pointer_width = "32", not(target_arch = "x86_64"))))]
+ {
+ RawCpuSet { bits: [0; 16] }
+ }
+}
+
+pub(crate) const CPU_SETSIZE: usize = 8 * core::mem::size_of::<RawCpuSet>();
diff --git a/vendor/rustix/src/imp/linux_raw/process/wait.rs b/vendor/rustix/src/imp/linux_raw/process/wait.rs
new file mode 100644
index 000000000..701b4ac0c
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/process/wait.rs
@@ -0,0 +1,39 @@
+// The functions replacing the C macros use the same names as in libc.
+#![allow(non_snake_case)]
+
+pub(crate) use linux_raw_sys::general::{WCONTINUED, WNOHANG, WUNTRACED};
+
+#[inline]
+pub(crate) fn WIFSTOPPED(status: u32) -> bool {
+ (status & 0xff) == 0x7f
+}
+
+#[inline]
+pub(crate) fn WSTOPSIG(status: u32) -> u32 {
+ (status >> 8) & 0xff
+}
+
+#[inline]
+pub(crate) fn WIFCONTINUED(status: u32) -> bool {
+ status == 0xffff
+}
+
+#[inline]
+pub(crate) fn WIFSIGNALED(status: u32) -> bool {
+ ((status & 0x7f) + 1) as i8 >= 2
+}
+
+#[inline]
+pub(crate) fn WTERMSIG(status: u32) -> u32 {
+ status & 0x7f
+}
+
+#[inline]
+pub(crate) fn WIFEXITED(status: u32) -> bool {
+ (status & 0x7f) == 0
+}
+
+#[inline]
+pub(crate) fn WEXITSTATUS(status: u32) -> u32 {
+ (status >> 8) & 0xff
+}
diff --git a/vendor/rustix/src/imp/linux_raw/rand/mod.rs b/vendor/rustix/src/imp/linux_raw/rand/mod.rs
new file mode 100644
index 000000000..1e0181a99
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/rand/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/linux_raw/rand/syscalls.rs b/vendor/rustix/src/imp/linux_raw/rand/syscalls.rs
new file mode 100644
index 000000000..2b5ca28e5
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/rand/syscalls.rs
@@ -0,0 +1,17 @@
+//! linux_raw syscalls supporting `rustix::rand`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::conv::{ret_usize, slice_mut};
+use crate::io;
+use crate::rand::GetRandomFlags;
+
+#[inline]
+pub(crate) fn getrandom(buf: &mut [u8], flags: GetRandomFlags) -> io::Result<usize> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+ unsafe { ret_usize(syscall!(__NR_getrandom, buf_addr_mut, buf_len, flags)) }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/rand/types.rs b/vendor/rustix/src/imp/linux_raw/rand/types.rs
new file mode 100644
index 000000000..75f17443e
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/rand/types.rs
@@ -0,0 +1,15 @@
+use bitflags::bitflags;
+
+bitflags! {
+ /// `GRND_*` flags for use with [`getrandom`].
+ ///
+ /// [`getrandom`]: crate::rand::getrandom
+ pub struct GetRandomFlags: u32 {
+ /// `GRND_RANDOM`
+ const RANDOM = linux_raw_sys::general::GRND_RANDOM;
+ /// `GRND_NONBLOCK`
+ const NONBLOCK = linux_raw_sys::general::GRND_NONBLOCK;
+ /// `GRND_INSECURE`
+ const INSECURE = linux_raw_sys::general::GRND_INSECURE;
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/reg.rs b/vendor/rustix/src/imp/linux_raw/reg.rs
new file mode 100644
index 000000000..afe99c5f4
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/reg.rs
@@ -0,0 +1,258 @@
+//! Encapsulation for system call arguments and return values.
+//!
+//! The inline-asm and outline-asm code paths do some amount of reordering
+//! of arguments; to ensure that we don't accidentally misroute an argument
+//! or return value, we use distinct types for each argument index and
+//! return value.
+//!
+//! # Safety
+//!
+//! The `ToAsm` and `FromAsm` traits are unsafe to use; they should only be
+//! used by the syscall code which executes actual syscall machine
+//! instructions.
+
+#![allow(unsafe_code)]
+
+use super::c;
+use super::fd::RawFd;
+use core::marker::PhantomData;
+
+pub(super) trait ToAsm: private::Sealed {
+ /// Convert `self` to a `usize` ready to be passed to a syscall
+ /// machine instruction.
+ ///
+ /// # Safety
+ ///
+ /// This should be used immediately before the syscall instruction, and
+ /// the returned value shouldn't be used for any other purpose.
+ #[must_use]
+ unsafe fn to_asm(self) -> *mut Opaque;
+}
+
+pub(super) trait FromAsm: private::Sealed {
+ /// Convert `raw` from a value produced by a syscall machine instruction
+ /// into a `Self`.
+ ///
+ /// # Safety
+ ///
+ /// This should be used immediately after the syscall instruction, and
+ /// the operand value shouldn't be used for any other purpose.
+ #[must_use]
+ unsafe fn from_asm(raw: *mut Opaque) -> Self;
+}
+
+/// To preserve provenance, syscall arguments and return values are passed as
+/// pointer types. They need a type to point to, so we define a custom private
+/// type, to prevent it from being used for anything else.
+#[repr(transparent)]
+pub(super) struct Opaque(c::c_void);
+
+// Argument numbers.
+pub(super) struct A0(());
+pub(super) struct A1(());
+pub(super) struct A2(());
+pub(super) struct A3(());
+pub(super) struct A4(());
+pub(super) struct A5(());
+#[cfg(target_arch = "mips")]
+pub(super) struct A6(());
+#[cfg(target_arch = "x86")]
+pub(super) struct SocketArg;
+
+pub(super) trait ArgNumber: private::Sealed {}
+impl ArgNumber for A0 {}
+impl ArgNumber for A1 {}
+impl ArgNumber for A2 {}
+impl ArgNumber for A3 {}
+impl ArgNumber for A4 {}
+impl ArgNumber for A5 {}
+#[cfg(target_arch = "mips")]
+impl ArgNumber for A6 {}
+#[cfg(target_arch = "x86")]
+impl ArgNumber for SocketArg {}
+
+// Return value numbers.
+pub(super) struct R0(());
+
+pub(super) trait RetNumber: private::Sealed {}
+impl RetNumber for R0 {}
+
+/// Syscall arguments use register-sized types. We use a newtype to
+/// discourage accidental misuse of the raw integer values.
+///
+/// This type doesn't implement `Clone` or `Copy`; it should be used exactly
+/// once. And it has a lifetime to ensure that it doesn't outlive any resources
+/// it might be pointing to.
+#[repr(transparent)]
+#[must_use]
+pub(super) struct ArgReg<'a, Num: ArgNumber> {
+ raw: *mut Opaque,
+ _phantom: PhantomData<(&'a (), Num)>,
+}
+
+impl<'a, Num: ArgNumber> ToAsm for ArgReg<'a, Num> {
+ #[inline]
+ unsafe fn to_asm(self) -> *mut Opaque {
+ self.raw
+ }
+}
+
+/// Syscall return values use register-sized types. We use a newtype to
+/// discourage accidental misuse of the raw integer values.
+///
+/// This type doesn't implement `Clone` or `Copy`; it should be used exactly
+/// once.
+#[repr(transparent)]
+#[must_use]
+pub(super) struct RetReg<Num: RetNumber> {
+ raw: *mut Opaque,
+ _phantom: PhantomData<Num>,
+}
+
+impl<Num: RetNumber> RetReg<Num> {
+ #[inline]
+ pub(super) fn decode_usize(self) -> usize {
+ debug_assert!(!(-4095..0).contains(&(self.raw as isize)));
+ self.raw as usize
+ }
+
+ #[inline]
+ pub(super) fn decode_raw_fd(self) -> RawFd {
+ let bits = self.decode_usize();
+ let raw_fd = bits as RawFd;
+
+ // Converting `raw` to `RawFd` should be lossless.
+ debug_assert_eq!(raw_fd as usize, bits);
+
+ raw_fd
+ }
+
+ #[inline]
+ pub(super) fn decode_c_int(self) -> c::c_int {
+ let bits = self.decode_usize();
+ let c_int_ = bits as c::c_int;
+
+ // Converting `raw` to `c_int` should be lossless.
+ debug_assert_eq!(c_int_ as usize, bits);
+
+ c_int_
+ }
+
+ #[inline]
+ pub(super) fn decode_c_uint(self) -> c::c_uint {
+ let bits = self.decode_usize();
+ let c_uint_ = bits as c::c_uint;
+
+ // Converting `raw` to `c_uint` should be lossless.
+ debug_assert_eq!(c_uint_ as usize, bits);
+
+ c_uint_
+ }
+
+ #[inline]
+ pub(super) fn decode_void_star(self) -> *mut c::c_void {
+ self.raw.cast()
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ #[inline]
+ pub(super) fn decode_u64(self) -> u64 {
+ self.decode_usize() as u64
+ }
+
+ #[inline]
+ pub(super) fn decode_void(self) {
+ let ignore = self.decode_usize();
+ debug_assert_eq!(ignore, 0);
+ }
+
+ #[inline]
+ pub(super) fn decode_error_code(self) -> u16 {
+ let bits = self.raw as usize;
+
+ // `raw` must be in `-4095..0`. Linux always returns errors in
+ // `-4095..0`, and we double-check it here.
+ debug_assert!((-4095..0).contains(&(bits as isize)));
+
+ bits as u16
+ }
+
+ #[inline]
+ pub(super) fn is_nonzero(&self) -> bool {
+ !self.raw.is_null()
+ }
+
+ #[inline]
+ pub(super) fn is_negative(&self) -> bool {
+ (self.raw as isize) < 0
+ }
+
+ #[inline]
+ pub(super) fn is_in_range(&self, range: core::ops::Range<isize>) -> bool {
+ range.contains(&(self.raw as isize))
+ }
+}
+
+impl<Num: RetNumber> FromAsm for RetReg<Num> {
+ #[inline]
+ unsafe fn from_asm(raw: *mut Opaque) -> Self {
+ Self {
+ raw,
+ _phantom: PhantomData,
+ }
+ }
+}
+
+#[repr(transparent)]
+pub(super) struct SyscallNumber<'a> {
+ nr: usize,
+ _phantom: PhantomData<&'a ()>,
+}
+
+impl<'a> ToAsm for SyscallNumber<'a> {
+ #[inline]
+ unsafe fn to_asm(self) -> *mut Opaque {
+ self.nr as usize as *mut Opaque
+ }
+}
+
+/// Encode a system call argument as an `ArgReg`.
+#[inline]
+pub(super) fn raw_arg<'a, Num: ArgNumber>(raw: *mut Opaque) -> ArgReg<'a, Num> {
+ ArgReg {
+ raw,
+ _phantom: PhantomData,
+ }
+}
+
+/// Encode a system call number (a `__NR_*` constant) as a `SyscallNumber`.
+#[inline]
+pub(super) const fn nr<'a>(nr: u32) -> SyscallNumber<'a> {
+ SyscallNumber {
+ nr: nr as usize,
+ _phantom: PhantomData,
+ }
+}
+
+/// Seal our various traits using the technique documented [here].
+///
+/// [here]: https://rust-lang.github.io/api-guidelines/future-proofing.html
+mod private {
+ pub trait Sealed {}
+
+ // Implement for those same types, but no others.
+ impl<'a, Num: super::ArgNumber> Sealed for super::ArgReg<'a, Num> {}
+ impl<Num: super::RetNumber> Sealed for super::RetReg<Num> {}
+ impl<'a> Sealed for super::SyscallNumber<'a> {}
+ impl Sealed for super::A0 {}
+ impl Sealed for super::A1 {}
+ impl Sealed for super::A2 {}
+ impl Sealed for super::A3 {}
+ impl Sealed for super::A4 {}
+ impl Sealed for super::A5 {}
+ #[cfg(target_arch = "mips")]
+ impl Sealed for super::A6 {}
+ #[cfg(target_arch = "x86")]
+ impl Sealed for super::SocketArg {}
+ impl Sealed for super::R0 {}
+}
diff --git a/vendor/rustix/src/imp/linux_raw/runtime/mod.rs b/vendor/rustix/src/imp/linux_raw/runtime/mod.rs
new file mode 100644
index 000000000..0b48649ce
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/runtime/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod syscalls;
+pub(crate) mod tls;
diff --git a/vendor/rustix/src/imp/linux_raw/runtime/syscalls.rs b/vendor/rustix/src/imp/linux_raw/runtime/syscalls.rs
new file mode 100644
index 000000000..49a29b2a2
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/runtime/syscalls.rs
@@ -0,0 +1,104 @@
+//! linux_raw syscalls supporting `rustix::runtime`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::c;
+#[cfg(target_arch = "x86")]
+use super::super::conv::by_mut;
+use super::super::conv::{c_int, c_uint, ret, ret_c_uint, ret_error, ret_usize_infallible, zero};
+use crate::fd::BorrowedFd;
+use crate::ffi::CStr;
+use crate::fs::AtFlags;
+use crate::io;
+use crate::process::{Pid, RawNonZeroPid};
+use linux_raw_sys::general::{__kernel_pid_t, PR_SET_NAME, SIGCHLD};
+#[cfg(target_arch = "x86_64")]
+use {super::super::conv::ret_infallible, linux_raw_sys::general::ARCH_SET_FS};
+
+#[inline]
+pub(crate) unsafe fn fork() -> io::Result<Option<Pid>> {
+ let pid = ret_c_uint(syscall_readonly!(
+ __NR_clone,
+ c_uint(SIGCHLD),
+ zero(),
+ zero(),
+ zero(),
+ zero()
+ ))?;
+ Ok(Pid::from_raw(pid))
+}
+
+pub(crate) unsafe fn execveat(
+ dirfd: BorrowedFd<'_>,
+ path: &CStr,
+ args: *const *const u8,
+ env_vars: *const *const u8,
+ flags: AtFlags,
+) -> io::Errno {
+ ret_error(syscall_readonly!(
+ __NR_execveat,
+ dirfd,
+ path,
+ args,
+ env_vars,
+ flags
+ ))
+}
+
+pub(crate) unsafe fn execve(
+ path: &CStr,
+ args: *const *const u8,
+ env_vars: *const *const u8,
+) -> io::Errno {
+ ret_error(syscall_readonly!(__NR_execve, path, args, env_vars))
+}
+
+pub(crate) mod tls {
+ #[cfg(target_arch = "x86")]
+ use super::super::tls::UserDesc;
+ use super::*;
+
+ #[cfg(target_arch = "x86")]
+ #[inline]
+ pub(crate) unsafe fn set_thread_area(u_info: &mut UserDesc) -> io::Result<()> {
+ ret(syscall!(__NR_set_thread_area, by_mut(u_info)))
+ }
+
+ #[cfg(target_arch = "arm")]
+ #[inline]
+ pub(crate) unsafe fn arm_set_tls(data: *mut c::c_void) -> io::Result<()> {
+ ret(syscall_readonly!(__ARM_NR_set_tls, data))
+ }
+
+ #[cfg(target_arch = "x86_64")]
+ #[inline]
+ pub(crate) unsafe fn set_fs(data: *mut c::c_void) {
+ ret_infallible(syscall_readonly!(
+ __NR_arch_prctl,
+ c_uint(ARCH_SET_FS),
+ data
+ ))
+ }
+
+ #[inline]
+ pub(crate) unsafe fn set_tid_address(data: *mut c::c_void) -> Pid {
+ let tid: i32 =
+ ret_usize_infallible(syscall_readonly!(__NR_set_tid_address, data)) as __kernel_pid_t;
+ debug_assert_ne!(tid, 0);
+ Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(tid as u32))
+ }
+
+ #[inline]
+ pub(crate) unsafe fn set_thread_name(name: &CStr) -> io::Result<()> {
+ ret(syscall_readonly!(__NR_prctl, c_uint(PR_SET_NAME), name))
+ }
+
+ #[inline]
+ pub(crate) fn exit_thread(code: c::c_int) -> ! {
+ unsafe { syscall_noreturn!(__NR_exit, c_int(code)) }
+ }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/runtime/tls.rs b/vendor/rustix/src/imp/linux_raw/runtime/tls.rs
new file mode 100644
index 000000000..63eed9bbd
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/runtime/tls.rs
@@ -0,0 +1,62 @@
+#![allow(unsafe_code)]
+
+use super::super::c;
+use super::super::elf::*;
+use super::super::param::auxv::exe_phdrs_slice;
+use core::ptr::null;
+
+/// For use with [`set_thread_area`].
+///
+/// [`set_thread_area`]: crate::runtime::set_thread_area
+#[cfg(target_arch = "x86")]
+pub type UserDesc = linux_raw_sys::general::user_desc;
+
+pub(crate) fn startup_tls_info() -> StartupTlsInfo {
+ let mut base = null();
+ let mut tls_phdr = null();
+ let mut stack_size = 0;
+
+ let phdrs = exe_phdrs_slice();
+
+ // Safety: We assume the phdr array pointer and length the kernel provided
+ // to the process describe a valid phdr array.
+ unsafe {
+ for phdr in phdrs {
+ match (*phdr).p_type {
+ PT_PHDR => {
+ base = phdrs
+ .as_ptr()
+ .cast::<u8>()
+ .offset(-((*phdr).p_vaddr as isize))
+ }
+ PT_TLS => tls_phdr = phdr,
+ PT_GNU_STACK => stack_size = (*phdr).p_memsz,
+ _ => {}
+ }
+ }
+
+ StartupTlsInfo {
+ addr: base.cast::<u8>().add((*tls_phdr).p_vaddr).cast(),
+ mem_size: (*tls_phdr).p_memsz,
+ file_size: (*tls_phdr).p_filesz,
+ align: (*tls_phdr).p_align,
+ stack_size,
+ }
+ }
+}
+
+/// The values returned from [`startup_tls_info`].
+///
+/// [`startup_tls_info`]: crate::runtime::startup_tls_info
+pub struct StartupTlsInfo {
+ /// The base address of the TLS segment.
+ pub addr: *const c::c_void,
+ /// The size of the memory region.
+ pub mem_size: usize,
+ /// The size beyond which all memory is zero-initialized.
+ pub file_size: usize,
+ /// The required alignment for the TLS segment.
+ pub align: usize,
+ /// The requested minimum size for stacks.
+ pub stack_size: usize,
+}
diff --git a/vendor/rustix/src/imp/linux_raw/termios/mod.rs b/vendor/rustix/src/imp/linux_raw/termios/mod.rs
new file mode 100644
index 000000000..1e0181a99
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/termios/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/linux_raw/termios/syscalls.rs b/vendor/rustix/src/imp/linux_raw/termios/syscalls.rs
new file mode 100644
index 000000000..b62a033e0
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/termios/syscalls.rs
@@ -0,0 +1,249 @@
+//! linux_raw syscalls supporting `rustix::termios`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::conv::{by_ref, c_uint, ret};
+use crate::fd::BorrowedFd;
+use crate::io;
+use crate::process::{Pid, RawNonZeroPid};
+use crate::termios::{
+ Action, OptionalActions, QueueSelector, Termios, Winsize, BRKINT, CBAUD, CS8, CSIZE, ECHO,
+ ECHONL, ICANON, ICRNL, IEXTEN, IGNBRK, IGNCR, INLCR, ISIG, ISTRIP, IXON, OPOST, PARENB, PARMRK,
+ VMIN, VTIME,
+};
+#[cfg(feature = "procfs")]
+use crate::{ffi::CStr, fs::FileType, path::DecInt};
+use core::mem::MaybeUninit;
+use linux_raw_sys::general::__kernel_pid_t;
+use linux_raw_sys::ioctl::{
+ TCFLSH, TCGETS, TCSBRK, TCSETS, TCXONC, TIOCGPGRP, TIOCGSID, TIOCGWINSZ, TIOCSPGRP, TIOCSWINSZ,
+};
+
+#[inline]
+pub(crate) fn tcgetwinsize(fd: BorrowedFd<'_>) -> io::Result<Winsize> {
+ unsafe {
+ let mut result = MaybeUninit::<Winsize>::uninit();
+ ret(syscall!(__NR_ioctl, fd, c_uint(TIOCGWINSZ), &mut result))
+ .map(|()| result.assume_init())
+ }
+}
+
+#[inline]
+pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
+ unsafe {
+ let mut result = MaybeUninit::<Termios>::uninit();
+ ret(syscall!(__NR_ioctl, fd, c_uint(TCGETS), &mut result)).map(|()| result.assume_init())
+ }
+}
+
+#[inline]
+pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
+ unsafe {
+ let mut result = MaybeUninit::<__kernel_pid_t>::uninit();
+ ret(syscall!(__NR_ioctl, fd, c_uint(TIOCGPGRP), &mut result)).map(|()| {
+ let pid = result.assume_init();
+ debug_assert!(pid > 0);
+ Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid as u32))
+ })
+ }
+}
+
+#[inline]
+pub(crate) fn tcsetattr(
+ fd: BorrowedFd,
+ optional_actions: OptionalActions,
+ termios: &Termios,
+) -> io::Result<()> {
+ // Translate from `optional_actions` into an ioctl request code. On MIPS,
+ // `optional_actions` already has `TCGETS` added to it.
+ let request = if cfg!(any(target_arch = "mips", target_arch = "mips64")) {
+ optional_actions as u32
+ } else {
+ TCSETS + optional_actions as u32
+ };
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_ioctl,
+ fd,
+ c_uint(request as u32),
+ by_ref(termios)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TCSBRK), c_uint(0))) }
+}
+
+#[inline]
+pub(crate) fn tcdrain(fd: BorrowedFd) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TCSBRK), c_uint(1))) }
+}
+
+#[inline]
+pub(crate) fn tcflush(fd: BorrowedFd, queue_selector: QueueSelector) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_ioctl,
+ fd,
+ c_uint(TCFLSH),
+ c_uint(queue_selector as u32)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn tcflow(fd: BorrowedFd, action: Action) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_ioctl,
+ fd,
+ c_uint(TCXONC),
+ c_uint(action as u32)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn tcgetsid(fd: BorrowedFd) -> io::Result<Pid> {
+ unsafe {
+ let mut result = MaybeUninit::<__kernel_pid_t>::uninit();
+ ret(syscall!(__NR_ioctl, fd, c_uint(TIOCGSID), &mut result)).map(|()| {
+ let pid = result.assume_init();
+ debug_assert!(pid > 0);
+ Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid as u32))
+ })
+ }
+}
+
+#[inline]
+pub(crate) fn tcsetwinsize(fd: BorrowedFd, winsize: Winsize) -> io::Result<()> {
+ unsafe {
+ ret(syscall!(
+ __NR_ioctl,
+ fd,
+ c_uint(TIOCSWINSZ),
+ by_ref(&winsize)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn tcsetpgrp(fd: BorrowedFd<'_>, pid: Pid) -> io::Result<()> {
+ unsafe { ret(syscall!(__NR_ioctl, fd, c_uint(TIOCSPGRP), pid)) }
+}
+
+#[inline]
+#[must_use]
+#[allow(clippy::missing_const_for_fn)]
+pub(crate) fn cfgetospeed(termios: &Termios) -> u32 {
+ termios.c_cflag & CBAUD
+}
+
+#[inline]
+#[must_use]
+#[allow(clippy::missing_const_for_fn)]
+pub(crate) fn cfgetispeed(termios: &Termios) -> u32 {
+ termios.c_cflag & CBAUD
+}
+
+#[inline]
+pub(crate) fn cfmakeraw(termios: &mut Termios) {
+ // From the Linux [`cfmakeraw` man page]:
+ //
+ // [`cfmakeraw` man page]: https://man7.org/linux/man-pages/man3/cfmakeraw.3.html
+ termios.c_iflag &= !(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+ termios.c_oflag &= !OPOST;
+ termios.c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ termios.c_cflag &= !(CSIZE | PARENB);
+ termios.c_cflag |= CS8;
+
+ // Musl and glibc also do these:
+ termios.c_cc[VMIN] = 1;
+ termios.c_cc[VTIME] = 0;
+}
+
+#[inline]
+pub(crate) fn cfsetospeed(termios: &mut Termios, speed: u32) -> io::Result<()> {
+ if (speed & !CBAUD) != 0 {
+ return Err(io::Errno::INVAL);
+ }
+ termios.c_cflag &= !CBAUD;
+ termios.c_cflag |= speed;
+ Ok(())
+}
+
+#[inline]
+pub(crate) fn cfsetispeed(termios: &mut Termios, speed: u32) -> io::Result<()> {
+ if speed == 0 {
+ return Ok(());
+ }
+ if (speed & !CBAUD) != 0 {
+ return Err(io::Errno::INVAL);
+ }
+ termios.c_cflag &= !CBAUD;
+ termios.c_cflag |= speed;
+ Ok(())
+}
+
+#[inline]
+pub(crate) fn cfsetspeed(termios: &mut Termios, speed: u32) -> io::Result<()> {
+ if (speed & !CBAUD) != 0 {
+ return Err(io::Errno::INVAL);
+ }
+ termios.c_cflag &= !CBAUD;
+ termios.c_cflag |= speed;
+ Ok(())
+}
+
+#[inline]
+pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool {
+ // On error, Linux will return either `EINVAL` (2.6.32) or `ENOTTY`
+ // (otherwise), because we assume we're never passing an invalid
+ // file descriptor (which would get `EBADF`). Either way, an error
+ // means we don't have a tty.
+ tcgetwinsize(fd).is_ok()
+}
+
+#[cfg(feature = "procfs")]
+pub(crate) fn ttyname(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize> {
+ let fd_stat = super::super::fs::syscalls::fstat(fd)?;
+
+ // Quick check: if `fd` isn't a character device, it's not a tty.
+ if FileType::from_raw_mode(fd_stat.st_mode) != FileType::CharacterDevice {
+ return Err(crate::io::Errno::NOTTY);
+ }
+
+ // Check that `fd` is really a tty.
+ tcgetwinsize(fd)?;
+
+ // Get a fd to '/proc/self/fd'.
+ let proc_self_fd = io::proc_self_fd()?;
+
+ // Gather the ttyname by reading the 'fd' file inside 'proc_self_fd'.
+ let r =
+ super::super::fs::syscalls::readlinkat(proc_self_fd, DecInt::from_fd(&fd).as_c_str(), buf)?;
+
+ // If the number of bytes is equal to the buffer length, truncation may
+ // have occurred. This check also ensures that we have enough space for
+ // adding a NUL terminator.
+ if r == buf.len() {
+ return Err(io::Errno::RANGE);
+ }
+ buf[r] = b'\0';
+
+ // Check that the path we read refers to the same file as `fd`.
+ let path = CStr::from_bytes_with_nul(&buf[..=r]).unwrap();
+
+ let path_stat = super::super::fs::syscalls::stat(path)?;
+ if path_stat.st_dev != fd_stat.st_dev || path_stat.st_ino != fd_stat.st_ino {
+ return Err(crate::io::Errno::NODEV);
+ }
+
+ Ok(r)
+}
diff --git a/vendor/rustix/src/imp/linux_raw/termios/types.rs b/vendor/rustix/src/imp/linux_raw/termios/types.rs
new file mode 100644
index 000000000..ce8832455
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/termios/types.rs
@@ -0,0 +1,456 @@
+use super::super::c;
+
+/// `TCSA*` values for use with [`tcsetattr`].
+///
+/// [`tcsetattr`]: crate::termios::tcsetattr
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u32)]
+pub enum OptionalActions {
+ /// `TCSANOW`—Make the change immediately.
+ Now = linux_raw_sys::general::TCSANOW,
+
+ /// `TCSADRAIN`—Make the change after all output has been transmitted.
+ Drain = linux_raw_sys::general::TCSADRAIN,
+
+ /// `TCSAFLUSH`—Discard any pending input and then make the change
+ /// after all output has been transmitted.
+ Flush = linux_raw_sys::general::TCSAFLUSH,
+}
+
+/// `TC*` values for use with [`tcflush`].
+///
+/// [`tcflush`]: crate::termios::tcflush
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u32)]
+pub enum QueueSelector {
+ /// `TCIFLUSH`—Flush data received but not read.
+ IFlush = linux_raw_sys::general::TCIFLUSH,
+
+ /// `TCOFLUSH`—Flush data written but not transmitted.
+ OFlush = linux_raw_sys::general::TCOFLUSH,
+
+ /// `TCIOFLUSH`—`IFlush` and `OFlush` combined.
+ IOFlush = linux_raw_sys::general::TCIOFLUSH,
+}
+
+/// `TC*` values for use with [`tcflow`].
+///
+/// [`tcflow`]: crate::termios::tcflow
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u32)]
+pub enum Action {
+ /// `TCOOFF`—Suspend output.
+ OOff = linux_raw_sys::general::TCOOFF,
+
+ /// `TCOON`—Restart suspended output.
+ OOn = linux_raw_sys::general::TCOON,
+
+ /// `TCIOFF`—Transmits a STOP byte.
+ IOff = linux_raw_sys::general::TCIOFF,
+
+ /// `TCION`—Transmits a START byte.
+ IOn = linux_raw_sys::general::TCION,
+}
+
+/// `struct termios` for use with [`tcgetattr`].
+///
+/// [`tcgetattr`]: crate::termios::tcgetattr
+pub type Termios = linux_raw_sys::general::termios;
+
+/// `struct winsize` for use with [`tcgetwinsize`].
+///
+/// [`tcgetwinsize`]: crate::termios::tcgetwinsize
+pub type Winsize = linux_raw_sys::general::winsize;
+
+/// `tcflag_t`—A type for the flags fields of [`Termios`].
+pub type Tcflag = linux_raw_sys::general::tcflag_t;
+
+/// `speed_t`—A return type for [`cfsetspeed`] and similar.
+///
+/// [`cfsetspeed`]: crate::termios::cfsetspeed
+pub type Speed = linux_raw_sys::general::speed_t;
+
+/// `VINTR`
+pub const VINTR: usize = linux_raw_sys::general::VINTR as usize;
+
+/// `VQUIT`
+pub const VQUIT: usize = linux_raw_sys::general::VQUIT as usize;
+
+/// `VERASE`
+pub const VERASE: usize = linux_raw_sys::general::VERASE as usize;
+
+/// `VKILL`
+pub const VKILL: usize = linux_raw_sys::general::VKILL as usize;
+
+/// `VEOF`
+pub const VEOF: usize = linux_raw_sys::general::VEOF as usize;
+
+/// `VTIME`
+pub const VTIME: usize = linux_raw_sys::general::VTIME as usize;
+
+/// `VMIN`
+pub const VMIN: usize = linux_raw_sys::general::VMIN as usize;
+
+/// `VSWTC`
+pub const VSWTC: usize = linux_raw_sys::general::VSWTC as usize;
+
+/// `VSTART`
+pub const VSTART: usize = linux_raw_sys::general::VSTART as usize;
+
+/// `VSTOP`
+pub const VSTOP: usize = linux_raw_sys::general::VSTOP as usize;
+
+/// `VSUSP`
+pub const VSUSP: usize = linux_raw_sys::general::VSUSP as usize;
+
+/// `VEOL`
+pub const VEOL: usize = linux_raw_sys::general::VEOL as usize;
+
+/// `VREPRINT`
+pub const VREPRINT: usize = linux_raw_sys::general::VREPRINT as usize;
+
+/// `VDISCARD`
+pub const VDISCARD: usize = linux_raw_sys::general::VDISCARD as usize;
+
+/// `VWERASE`
+pub const VWERASE: usize = linux_raw_sys::general::VWERASE as usize;
+
+/// `VLNEXT`
+pub const VLNEXT: usize = linux_raw_sys::general::VLNEXT as usize;
+
+/// `VEOL2`
+pub const VEOL2: usize = linux_raw_sys::general::VEOL2 as usize;
+
+/// `IGNBRK`
+pub const IGNBRK: c::c_uint = linux_raw_sys::general::IGNBRK;
+
+/// `BRKINT`
+pub const BRKINT: c::c_uint = linux_raw_sys::general::BRKINT;
+
+/// `IGNPAR`
+pub const IGNPAR: c::c_uint = linux_raw_sys::general::IGNPAR;
+
+/// `PARMRK`
+pub const PARMRK: c::c_uint = linux_raw_sys::general::PARMRK;
+
+/// `INPCK`
+pub const INPCK: c::c_uint = linux_raw_sys::general::INPCK;
+
+/// `ISTRIP`
+pub const ISTRIP: c::c_uint = linux_raw_sys::general::ISTRIP;
+
+/// `INLCR`
+pub const INLCR: c::c_uint = linux_raw_sys::general::INLCR;
+
+/// `IGNCR`
+pub const IGNCR: c::c_uint = linux_raw_sys::general::IGNCR;
+
+/// `ICRNL`
+pub const ICRNL: c::c_uint = linux_raw_sys::general::ICRNL;
+
+/// `IUCLC`
+pub const IUCLC: c::c_uint = linux_raw_sys::general::IUCLC;
+
+/// `IXON`
+pub const IXON: c::c_uint = linux_raw_sys::general::IXON;
+
+/// `IXANY`
+pub const IXANY: c::c_uint = linux_raw_sys::general::IXANY;
+
+/// `IXOFF`
+pub const IXOFF: c::c_uint = linux_raw_sys::general::IXOFF;
+
+/// `IMAXBEL`
+pub const IMAXBEL: c::c_uint = linux_raw_sys::general::IMAXBEL;
+
+/// `IUTF8`
+pub const IUTF8: c::c_uint = linux_raw_sys::general::IUTF8;
+
+/// `OPOST`
+pub const OPOST: c::c_uint = linux_raw_sys::general::OPOST;
+
+/// `OLCUC`
+pub const OLCUC: c::c_uint = linux_raw_sys::general::OLCUC;
+
+/// `ONLCR`
+pub const ONLCR: c::c_uint = linux_raw_sys::general::ONLCR;
+
+/// `OCRNL`
+pub const OCRNL: c::c_uint = linux_raw_sys::general::OCRNL;
+
+/// `ONOCR`
+pub const ONOCR: c::c_uint = linux_raw_sys::general::ONOCR;
+
+/// `ONLRET`
+pub const ONLRET: c::c_uint = linux_raw_sys::general::ONLRET;
+
+/// `OFILL`
+pub const OFILL: c::c_uint = linux_raw_sys::general::OFILL;
+
+/// `OFDEL`
+pub const OFDEL: c::c_uint = linux_raw_sys::general::OFDEL;
+
+/// `NLDLY`
+pub const NLDLY: c::c_uint = linux_raw_sys::general::NLDLY;
+
+/// `NL0`
+pub const NL0: c::c_uint = linux_raw_sys::general::NL0;
+
+/// `NL1`
+pub const NL1: c::c_uint = linux_raw_sys::general::NL1;
+
+/// `CRDLY`
+pub const CRDLY: c::c_uint = linux_raw_sys::general::CRDLY;
+
+/// `CR0`
+pub const CR0: c::c_uint = linux_raw_sys::general::CR0;
+
+/// `CR1`
+pub const CR1: c::c_uint = linux_raw_sys::general::CR1;
+
+/// `CR2`
+pub const CR2: c::c_uint = linux_raw_sys::general::CR2;
+
+/// `CR3`
+pub const CR3: c::c_uint = linux_raw_sys::general::CR3;
+
+/// `TABDLY`
+pub const TABDLY: c::c_uint = linux_raw_sys::general::TABDLY;
+
+/// `TAB0`
+pub const TAB0: c::c_uint = linux_raw_sys::general::TAB0;
+
+/// `TAB1`
+pub const TAB1: c::c_uint = linux_raw_sys::general::TAB1;
+
+/// `TAB2`
+pub const TAB2: c::c_uint = linux_raw_sys::general::TAB2;
+
+/// `TAB3`
+pub const TAB3: c::c_uint = linux_raw_sys::general::TAB3;
+
+/// `BSDLY`
+pub const BSDLY: c::c_uint = linux_raw_sys::general::BSDLY;
+
+/// `BS0`
+pub const BS0: c::c_uint = linux_raw_sys::general::BS0;
+
+/// `BS1`
+pub const BS1: c::c_uint = linux_raw_sys::general::BS1;
+
+/// `FFDLY`
+pub const FFDLY: c::c_uint = linux_raw_sys::general::FFDLY;
+
+/// `FF0`
+pub const FF0: c::c_uint = linux_raw_sys::general::FF0;
+
+/// `FF1`
+pub const FF1: c::c_uint = linux_raw_sys::general::FF1;
+
+/// `VTDLY`
+pub const VTDLY: c::c_uint = linux_raw_sys::general::VTDLY;
+
+/// `VT0`
+pub const VT0: c::c_uint = linux_raw_sys::general::VT0;
+
+/// `VT1`
+pub const VT1: c::c_uint = linux_raw_sys::general::VT1;
+
+/// `B0`
+pub const B0: Speed = linux_raw_sys::general::B0;
+
+/// `B50`
+pub const B50: Speed = linux_raw_sys::general::B50;
+
+/// `B75`
+pub const B75: Speed = linux_raw_sys::general::B75;
+
+/// `B110`
+pub const B110: Speed = linux_raw_sys::general::B110;
+
+/// `B134`
+pub const B134: Speed = linux_raw_sys::general::B134;
+
+/// `B150`
+pub const B150: Speed = linux_raw_sys::general::B150;
+
+/// `B200`
+pub const B200: Speed = linux_raw_sys::general::B200;
+
+/// `B300`
+pub const B300: Speed = linux_raw_sys::general::B300;
+
+/// `B600`
+pub const B600: Speed = linux_raw_sys::general::B600;
+
+/// `B1200`
+pub const B1200: Speed = linux_raw_sys::general::B1200;
+
+/// `B1800`
+pub const B1800: Speed = linux_raw_sys::general::B1800;
+
+/// `B2400`
+pub const B2400: Speed = linux_raw_sys::general::B2400;
+
+/// `B4800`
+pub const B4800: Speed = linux_raw_sys::general::B4800;
+
+/// `B9600`
+pub const B9600: Speed = linux_raw_sys::general::B9600;
+
+/// `B19200`
+pub const B19200: Speed = linux_raw_sys::general::B19200;
+
+/// `B38400`
+pub const B38400: Speed = linux_raw_sys::general::B38400;
+
+/// `B57600`
+pub const B57600: Speed = linux_raw_sys::general::B57600;
+
+/// `B115200`
+pub const B115200: Speed = linux_raw_sys::general::B115200;
+
+/// `B230400`
+pub const B230400: Speed = linux_raw_sys::general::B230400;
+
+/// `B460800`
+pub const B460800: Speed = linux_raw_sys::general::B460800;
+
+/// `B500000`
+pub const B500000: Speed = linux_raw_sys::general::B500000;
+
+/// `B576000`
+pub const B576000: Speed = linux_raw_sys::general::B576000;
+
+/// `B921600`
+pub const B921600: Speed = linux_raw_sys::general::B921600;
+
+/// `B1000000`
+pub const B1000000: Speed = linux_raw_sys::general::B1000000;
+
+/// `B1152000`
+pub const B1152000: Speed = linux_raw_sys::general::B1152000;
+
+/// `B1500000`
+pub const B1500000: Speed = linux_raw_sys::general::B1500000;
+
+/// `B2000000`
+pub const B2000000: Speed = linux_raw_sys::general::B2000000;
+
+/// `B2500000`
+pub const B2500000: Speed = linux_raw_sys::general::B2500000;
+
+/// `B3000000`
+pub const B3000000: Speed = linux_raw_sys::general::B3000000;
+
+/// `B3500000`
+pub const B3500000: Speed = linux_raw_sys::general::B3500000;
+
+/// `B4000000`
+pub const B4000000: Speed = linux_raw_sys::general::B4000000;
+
+/// `CSIZE`
+pub const CSIZE: c::c_uint = linux_raw_sys::general::CSIZE;
+
+/// `CS5`
+pub const CS5: c::c_uint = linux_raw_sys::general::CS5;
+
+/// `CS6`
+pub const CS6: c::c_uint = linux_raw_sys::general::CS6;
+
+/// `CS7`
+pub const CS7: c::c_uint = linux_raw_sys::general::CS7;
+
+/// `CS8`
+pub const CS8: c::c_uint = linux_raw_sys::general::CS8;
+
+/// `CSTOPB`
+pub const CSTOPB: c::c_uint = linux_raw_sys::general::CSTOPB;
+
+/// `CREAD`
+pub const CREAD: c::c_uint = linux_raw_sys::general::CREAD;
+
+/// `PARENB`
+pub const PARENB: c::c_uint = linux_raw_sys::general::PARENB;
+
+/// `PARODD`
+pub const PARODD: c::c_uint = linux_raw_sys::general::PARODD;
+
+/// `HUPCL`
+pub const HUPCL: c::c_uint = linux_raw_sys::general::HUPCL;
+
+/// `CLOCAL`
+pub const CLOCAL: c::c_uint = linux_raw_sys::general::CLOCAL;
+
+/// `ISIG`
+pub const ISIG: c::c_uint = linux_raw_sys::general::ISIG;
+
+/// `ICANON`—A flag for the `c_lflag` field of [`Termios`] indicating
+/// canonical mode.
+pub const ICANON: Tcflag = linux_raw_sys::general::ICANON;
+
+/// `ECHO`
+pub const ECHO: c::c_uint = linux_raw_sys::general::ECHO;
+
+/// `ECHOE`
+pub const ECHOE: c::c_uint = linux_raw_sys::general::ECHOE;
+
+/// `ECHOK`
+pub const ECHOK: c::c_uint = linux_raw_sys::general::ECHOK;
+
+/// `ECHONL`
+pub const ECHONL: c::c_uint = linux_raw_sys::general::ECHONL;
+
+/// `NOFLSH`
+pub const NOFLSH: c::c_uint = linux_raw_sys::general::NOFLSH;
+
+/// `TOSTOP`
+pub const TOSTOP: c::c_uint = linux_raw_sys::general::TOSTOP;
+
+/// `IEXTEN`
+pub const IEXTEN: c::c_uint = linux_raw_sys::general::IEXTEN;
+
+/// `EXTA`
+pub const EXTA: c::c_uint = linux_raw_sys::general::EXTA;
+
+/// `EXTB`
+pub const EXTB: c::c_uint = linux_raw_sys::general::EXTB;
+
+/// `CBAUD`
+pub const CBAUD: c::c_uint = linux_raw_sys::general::CBAUD;
+
+/// `CBAUDEX`
+pub const CBAUDEX: c::c_uint = linux_raw_sys::general::CBAUDEX;
+
+/// `CIBAUD`
+pub const CIBAUD: c::c_uint = linux_raw_sys::general::CIBAUD;
+
+/// `CMSPAR`
+pub const CMSPAR: c::c_uint = linux_raw_sys::general::CMSPAR;
+
+/// `CRTSCTS`
+pub const CRTSCTS: c::c_uint = linux_raw_sys::general::CRTSCTS;
+
+/// `XCASE`
+pub const XCASE: c::c_uint = linux_raw_sys::general::XCASE;
+
+/// `ECHOCTL`
+pub const ECHOCTL: c::c_uint = linux_raw_sys::general::ECHOCTL;
+
+/// `ECHOPRT`
+pub const ECHOPRT: c::c_uint = linux_raw_sys::general::ECHOPRT;
+
+/// `ECHOKE`
+pub const ECHOKE: c::c_uint = linux_raw_sys::general::ECHOKE;
+
+/// `FLUSHO`
+pub const FLUSHO: c::c_uint = linux_raw_sys::general::FLUSHO;
+
+/// `PENDIN`
+pub const PENDIN: c::c_uint = linux_raw_sys::general::PENDIN;
+
+/// `EXTPROC`
+pub const EXTPROC: c::c_uint = linux_raw_sys::general::EXTPROC;
+
+/// `XTABS`
+pub const XTABS: c::c_uint = linux_raw_sys::general::XTABS;
diff --git a/vendor/rustix/src/imp/linux_raw/thread/futex.rs b/vendor/rustix/src/imp/linux_raw/thread/futex.rs
new file mode 100644
index 000000000..9e087f9f1
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/thread/futex.rs
@@ -0,0 +1,39 @@
+bitflags::bitflags! {
+ /// Flags for use with [`futex`].
+ ///
+ /// [`futex`]: crate::thread::futex
+ pub struct FutexFlags: u32 {
+ /// `FUTEX_PRIVATE_FLAG`
+ const PRIVATE = linux_raw_sys::general::FUTEX_PRIVATE_FLAG;
+ /// `FUTEX_CLOCK_REALTIME`
+ const CLOCK_REALTIME = linux_raw_sys::general::FUTEX_CLOCK_REALTIME;
+ }
+}
+
+/// Operations for use with [`futex`].
+///
+/// [`futex`]: crate::thread::futex
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[repr(u32)]
+pub enum FutexOperation {
+ /// `FUTEX_WAIT`
+ Wait = linux_raw_sys::general::FUTEX_WAIT,
+ /// `FUTEX_WAKE`
+ Wake = linux_raw_sys::general::FUTEX_WAKE,
+ /// `FUTEX_FD`
+ Fd = linux_raw_sys::general::FUTEX_FD,
+ /// `FUTEX_REQUEUE`
+ Requeue = linux_raw_sys::general::FUTEX_REQUEUE,
+ /// `FUTEX_CMP_REQUEUE`
+ CmpRequeue = linux_raw_sys::general::FUTEX_CMP_REQUEUE,
+ /// `FUTEX_WAKE_OP`
+ WakeOp = linux_raw_sys::general::FUTEX_WAKE_OP,
+ /// `FUTEX_LOCK_PI`
+ LockPi = linux_raw_sys::general::FUTEX_LOCK_PI,
+ /// `FUTEX_UNLOCK_PI`
+ UnlockPi = linux_raw_sys::general::FUTEX_UNLOCK_PI,
+ /// `FUTEX_TRYLOCK_PI`
+ TrylockPi = linux_raw_sys::general::FUTEX_TRYLOCK_PI,
+ /// `FUTEX_WAIT_BITSET`
+ WaitBitset = linux_raw_sys::general::FUTEX_WAIT_BITSET,
+}
diff --git a/vendor/rustix/src/imp/linux_raw/thread/mod.rs b/vendor/rustix/src/imp/linux_raw/thread/mod.rs
new file mode 100644
index 000000000..8bb80c33a
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/thread/mod.rs
@@ -0,0 +1,4 @@
+mod futex;
+pub(crate) mod syscalls;
+
+pub use futex::{FutexFlags, FutexOperation};
diff --git a/vendor/rustix/src/imp/linux_raw/thread/syscalls.rs b/vendor/rustix/src/imp/linux_raw/thread/syscalls.rs
new file mode 100644
index 000000000..600b4649d
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/thread/syscalls.rs
@@ -0,0 +1,280 @@
+//! linux_raw syscalls supporting `rustix::thread`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::conv::{by_ref, c_int, c_uint, ret, ret_usize, ret_usize_infallible, zero};
+use crate::io;
+use crate::process::{Pid, RawNonZeroPid};
+use crate::thread::{ClockId, FutexFlags, FutexOperation, NanosleepRelativeResult, Timespec};
+use core::mem::MaybeUninit;
+use linux_raw_sys::general::{__kernel_pid_t, __kernel_timespec, TIMER_ABSTIME};
+#[cfg(target_pointer_width = "32")]
+use {
+ core::convert::TryInto, core::ptr, linux_raw_sys::general::timespec as __kernel_old_timespec,
+};
+
+#[inline]
+pub(crate) fn clock_nanosleep_relative(
+ id: ClockId,
+ req: &__kernel_timespec,
+) -> NanosleepRelativeResult {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ let mut rem = MaybeUninit::<__kernel_timespec>::uninit();
+ match ret(syscall!(
+ __NR_clock_nanosleep_time64,
+ id,
+ c_int(0),
+ by_ref(req),
+ &mut rem
+ ))
+ .or_else(|err| {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ if err == io::Errno::NOSYS {
+ clock_nanosleep_relative_old(id, req, &mut rem)
+ } else {
+ Err(err)
+ }
+ }) {
+ Ok(()) => NanosleepRelativeResult::Ok,
+ Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(rem.assume_init()),
+ Err(err) => NanosleepRelativeResult::Err(err),
+ }
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ let mut rem = MaybeUninit::<__kernel_timespec>::uninit();
+ match ret(syscall!(
+ __NR_clock_nanosleep,
+ id,
+ c_int(0),
+ by_ref(req),
+ &mut rem
+ )) {
+ Ok(()) => NanosleepRelativeResult::Ok,
+ Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(rem.assume_init()),
+ Err(err) => NanosleepRelativeResult::Err(err),
+ }
+ }
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn clock_nanosleep_relative_old(
+ id: ClockId,
+ req: &__kernel_timespec,
+ rem: &mut MaybeUninit<__kernel_timespec>,
+) -> io::Result<()> {
+ let old_req = __kernel_old_timespec {
+ tv_sec: req.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?,
+ tv_nsec: req.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
+ };
+ let mut old_rem = MaybeUninit::<__kernel_old_timespec>::uninit();
+ ret(syscall!(
+ __NR_clock_nanosleep,
+ id,
+ c_int(0),
+ by_ref(&old_req),
+ &mut old_rem
+ ))?;
+ let old_rem = old_rem.assume_init();
+ // TODO: With Rust 1.55, we can use MaybeUninit::write here.
+ ptr::write(
+ rem.as_mut_ptr(),
+ __kernel_timespec {
+ tv_sec: old_rem.tv_sec.into(),
+ tv_nsec: old_rem.tv_nsec.into(),
+ },
+ );
+ Ok(())
+}
+
+#[inline]
+pub(crate) fn clock_nanosleep_absolute(id: ClockId, req: &__kernel_timespec) -> io::Result<()> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_clock_nanosleep_time64,
+ id,
+ c_uint(TIMER_ABSTIME),
+ by_ref(req),
+ zero()
+ ))
+ .or_else(|err| {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ if err == io::Errno::NOSYS {
+ clock_nanosleep_absolute_old(id, req)
+ } else {
+ Err(err)
+ }
+ })
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_clock_nanosleep,
+ id,
+ c_uint(TIMER_ABSTIME),
+ by_ref(req),
+ zero()
+ ))
+ }
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn clock_nanosleep_absolute_old(id: ClockId, req: &__kernel_timespec) -> io::Result<()> {
+ let old_req = __kernel_old_timespec {
+ tv_sec: req.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?,
+ tv_nsec: req.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
+ };
+ ret(syscall_readonly!(
+ __NR_clock_nanosleep,
+ id,
+ c_int(0),
+ by_ref(&old_req),
+ zero()
+ ))
+}
+
+#[inline]
+pub(crate) fn nanosleep(req: &__kernel_timespec) -> NanosleepRelativeResult {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ let mut rem = MaybeUninit::<__kernel_timespec>::uninit();
+ match ret(syscall!(
+ __NR_clock_nanosleep_time64,
+ ClockId::Realtime,
+ c_int(0),
+ by_ref(req),
+ &mut rem
+ ))
+ .or_else(|err| {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ if err == io::Errno::NOSYS {
+ nanosleep_old(req, &mut rem)
+ } else {
+ Err(err)
+ }
+ }) {
+ Ok(()) => NanosleepRelativeResult::Ok,
+ Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(rem.assume_init()),
+ Err(err) => NanosleepRelativeResult::Err(err),
+ }
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ let mut rem = MaybeUninit::<__kernel_timespec>::uninit();
+ match ret(syscall!(__NR_nanosleep, by_ref(req), &mut rem)) {
+ Ok(()) => NanosleepRelativeResult::Ok,
+ Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(rem.assume_init()),
+ Err(err) => NanosleepRelativeResult::Err(err),
+ }
+ }
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn nanosleep_old(
+ req: &__kernel_timespec,
+ rem: &mut MaybeUninit<__kernel_timespec>,
+) -> io::Result<()> {
+ let old_req = __kernel_old_timespec {
+ tv_sec: req.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?,
+ tv_nsec: req.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
+ };
+ let mut old_rem = MaybeUninit::<__kernel_old_timespec>::uninit();
+ ret(syscall!(__NR_nanosleep, by_ref(&old_req), &mut old_rem))?;
+ let old_rem = old_rem.assume_init();
+ // TODO: With Rust 1.55, we can use MaybeUninit::write here.
+ ptr::write(
+ rem.as_mut_ptr(),
+ __kernel_timespec {
+ tv_sec: old_rem.tv_sec.into(),
+ tv_nsec: old_rem.tv_nsec.into(),
+ },
+ );
+ Ok(())
+}
+
+#[inline]
+pub(crate) fn gettid() -> Pid {
+ unsafe {
+ let tid: i32 = ret_usize_infallible(syscall_readonly!(__NR_gettid)) as __kernel_pid_t;
+ debug_assert_ne!(tid, 0);
+ Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(tid as u32))
+ }
+}
+
+// TODO: This could be de-multiplexed.
+#[inline]
+pub(crate) unsafe fn futex(
+ uaddr: *mut u32,
+ op: FutexOperation,
+ flags: FutexFlags,
+ val: u32,
+ utime: *const Timespec,
+ uaddr2: *mut u32,
+ val3: u32,
+) -> io::Result<usize> {
+ #[cfg(target_pointer_width = "32")]
+ {
+ ret_usize(syscall!(
+ __NR_futex_time64,
+ uaddr,
+ (op, flags),
+ c_uint(val),
+ utime,
+ uaddr2,
+ c_uint(val3)
+ ))
+ .or_else(|err| {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ if err == io::Errno::NOSYS {
+ futex_old(uaddr, op, flags, val, utime, uaddr2, val3)
+ } else {
+ Err(err)
+ }
+ })
+ }
+ #[cfg(target_pointer_width = "64")]
+ ret_usize(syscall!(
+ __NR_futex,
+ uaddr,
+ (op, flags),
+ c_uint(val),
+ utime,
+ uaddr2,
+ c_uint(val3)
+ ))
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn futex_old(
+ uaddr: *mut u32,
+ op: FutexOperation,
+ flags: FutexFlags,
+ val: u32,
+ utime: *const Timespec,
+ uaddr2: *mut u32,
+ val3: u32,
+) -> io::Result<usize> {
+ let old_utime = __kernel_old_timespec {
+ tv_sec: (*utime).tv_sec.try_into().map_err(|_| io::Errno::INVAL)?,
+ tv_nsec: (*utime).tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
+ };
+ ret_usize(syscall!(
+ __NR_futex,
+ uaddr,
+ (op, flags),
+ c_uint(val),
+ by_ref(&old_utime),
+ uaddr2,
+ c_uint(val3)
+ ))
+}
diff --git a/vendor/rustix/src/imp/linux_raw/time/mod.rs b/vendor/rustix/src/imp/linux_raw/time/mod.rs
new file mode 100644
index 000000000..c42592c4f
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/time/mod.rs
@@ -0,0 +1,3 @@
+#[cfg(any(feature = "time", target_arch = "x86"))]
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/imp/linux_raw/time/syscalls.rs b/vendor/rustix/src/imp/linux_raw/time/syscalls.rs
new file mode 100644
index 000000000..93651e499
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/time/syscalls.rs
@@ -0,0 +1,229 @@
+//! linux_raw syscalls supporting `rustix::time`.
+//!
+//! # Safety
+//!
+//! See the `rustix::imp` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+#[cfg(feature = "time")]
+use super::super::conv::{by_ref, ret_owned_fd};
+use super::super::conv::{ret, ret_infallible};
+use super::types::ClockId;
+#[cfg(feature = "time")]
+use crate::fd::BorrowedFd;
+use crate::io;
+#[cfg(feature = "time")]
+use crate::io::OwnedFd;
+#[cfg(feature = "time")]
+use crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags};
+use core::mem::MaybeUninit;
+use linux_raw_sys::general::__kernel_timespec;
+#[cfg(feature = "time")]
+#[cfg(target_pointer_width = "32")]
+use {core::convert::TryInto, linux_raw_sys::general::itimerspec as __kernel_old_itimerspec};
+#[cfg(target_pointer_width = "32")]
+use {core::ptr, linux_raw_sys::general::timespec as __kernel_old_timespec};
+
+// `clock_gettime` has special optimizations via the vDSO.
+#[cfg(feature = "time")]
+pub(crate) use super::super::vdso_wrappers::{clock_gettime, clock_gettime_dynamic};
+
+#[inline]
+pub(crate) fn clock_getres(which_clock: ClockId) -> __kernel_timespec {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ let mut result = MaybeUninit::<__kernel_timespec>::uninit();
+ if let Err(err) = ret(syscall!(__NR_clock_getres_time64, which_clock, &mut result)) {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ debug_assert_eq!(err, io::Errno::NOSYS);
+ clock_getres_old(which_clock, &mut result);
+ }
+ result.assume_init()
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ let mut result = MaybeUninit::<__kernel_timespec>::uninit();
+ ret_infallible(syscall!(__NR_clock_getres, which_clock, &mut result));
+ result.assume_init()
+ }
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn clock_getres_old(which_clock: ClockId, result: &mut MaybeUninit<__kernel_timespec>) {
+ let mut old_result = MaybeUninit::<__kernel_old_timespec>::uninit();
+ ret_infallible(syscall!(__NR_clock_getres, which_clock, &mut old_result));
+ let old_result = old_result.assume_init();
+ // TODO: With Rust 1.55, we can use MaybeUninit::write here.
+ ptr::write(
+ result.as_mut_ptr(),
+ __kernel_timespec {
+ tv_sec: old_result.tv_sec.into(),
+ tv_nsec: old_result.tv_nsec.into(),
+ },
+ );
+}
+
+#[cfg(feature = "time")]
+#[inline]
+pub(crate) fn timerfd_create(clockid: TimerfdClockId, flags: TimerfdFlags) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(syscall!(__NR_timerfd_create, clockid, flags)) }
+}
+
+#[cfg(feature = "time")]
+#[inline]
+pub(crate) fn timerfd_settime(
+ fd: BorrowedFd<'_>,
+ flags: TimerfdTimerFlags,
+ new_value: &Itimerspec,
+) -> io::Result<Itimerspec> {
+ let mut result = MaybeUninit::<Itimerspec>::uninit();
+
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall!(
+ __NR_timerfd_settime,
+ fd,
+ flags,
+ by_ref(new_value),
+ &mut result
+ ))
+ .map(|()| result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall!(
+ __NR_timerfd_settime64,
+ fd,
+ flags,
+ by_ref(new_value),
+ &mut result
+ ))
+ .or_else(|err| {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ if err == io::Errno::NOSYS {
+ timerfd_settime_old(fd, flags, new_value, &mut result)
+ } else {
+ Err(err)
+ }
+ })
+ .map(|()| result.assume_init())
+ }
+}
+
+#[cfg(feature = "time")]
+#[cfg(target_pointer_width = "32")]
+unsafe fn timerfd_settime_old(
+ fd: BorrowedFd<'_>,
+ flags: TimerfdTimerFlags,
+ new_value: &Itimerspec,
+ result: &mut MaybeUninit<Itimerspec>,
+) -> io::Result<()> {
+ let mut old_result = MaybeUninit::<__kernel_old_itimerspec>::uninit();
+
+ // Convert `new_value` to the old `__kernel_old_itimerspec` format.
+ let old_new_value = __kernel_old_itimerspec {
+ it_interval: __kernel_old_timespec {
+ tv_sec: new_value
+ .it_interval
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: new_value
+ .it_interval
+ .tv_nsec
+ .try_into()
+ .map_err(|_| io::Errno::INVAL)?,
+ },
+ it_value: __kernel_old_timespec {
+ tv_sec: new_value
+ .it_value
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: new_value
+ .it_value
+ .tv_nsec
+ .try_into()
+ .map_err(|_| io::Errno::INVAL)?,
+ },
+ };
+ ret(syscall!(
+ __NR_timerfd_settime,
+ fd,
+ flags,
+ by_ref(&old_new_value),
+ &mut old_result
+ ))?;
+ let old_result = old_result.assume_init();
+ // TODO: With Rust 1.55, we can use MaybeUninit::write here.
+ ptr::write(
+ result.as_mut_ptr(),
+ Itimerspec {
+ it_interval: __kernel_timespec {
+ tv_sec: old_result.it_interval.tv_sec.into(),
+ tv_nsec: old_result.it_interval.tv_nsec.into(),
+ },
+ it_value: __kernel_timespec {
+ tv_sec: old_result.it_value.tv_sec.into(),
+ tv_nsec: old_result.it_value.tv_nsec.into(),
+ },
+ },
+ );
+ Ok(())
+}
+
+#[cfg(feature = "time")]
+#[inline]
+pub(crate) fn timerfd_gettime(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
+ let mut result = MaybeUninit::<Itimerspec>::uninit();
+
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall!(__NR_timerfd_gettime, fd, &mut result)).map(|()| result.assume_init())
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ ret(syscall!(__NR_timerfd_gettime64, fd, &mut result))
+ .or_else(|err| {
+ // See the comments in `rustix_clock_gettime_via_syscall` about
+ // emulation.
+ if err == io::Errno::NOSYS {
+ timerfd_gettime_old(fd, &mut result)
+ } else {
+ Err(err)
+ }
+ })
+ .map(|()| result.assume_init())
+ }
+}
+
+#[cfg(feature = "time")]
+#[cfg(target_pointer_width = "32")]
+unsafe fn timerfd_gettime_old(
+ fd: BorrowedFd<'_>,
+ result: &mut MaybeUninit<Itimerspec>,
+) -> io::Result<()> {
+ let mut old_result = MaybeUninit::<__kernel_old_itimerspec>::uninit();
+ ret(syscall!(__NR_timerfd_gettime, fd, &mut old_result))?;
+ let old_result = old_result.assume_init();
+ // TODO: With Rust 1.55, we can use MaybeUninit::write here.
+ ptr::write(
+ result.as_mut_ptr(),
+ Itimerspec {
+ it_interval: __kernel_timespec {
+ tv_sec: old_result.it_interval.tv_sec.into(),
+ tv_nsec: old_result.it_interval.tv_nsec.into(),
+ },
+ it_value: __kernel_timespec {
+ tv_sec: old_result.it_value.tv_sec.into(),
+ tv_nsec: old_result.it_value.tv_nsec.into(),
+ },
+ },
+ );
+ Ok(())
+}
diff --git a/vendor/rustix/src/imp/linux_raw/time/types.rs b/vendor/rustix/src/imp/linux_raw/time/types.rs
new file mode 100644
index 000000000..5a0fcc6f5
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/time/types.rs
@@ -0,0 +1,154 @@
+use super::super::c;
+use crate::fd::BorrowedFd;
+use bitflags::bitflags;
+
+/// `struct timespec`
+pub type Timespec = linux_raw_sys::general::__kernel_timespec;
+
+/// A type for the `tv_sec` field of [`Timespec`].
+pub type Secs = linux_raw_sys::general::__kernel_time64_t;
+
+/// A type for the `tv_nsec` field of [`Timespec`].
+pub type Nsecs = i64;
+
+/// `struct itimerspec` for use with [`timerfd_gettime`] and
+/// [`timerfd_settime`].
+///
+/// [`timerfd_gettime`]: crate::time::timerfd_gettime
+/// [`timerfd_settime`]: crate::time::timerfd_settime
+pub type Itimerspec = linux_raw_sys::general::__kernel_itimerspec;
+
+/// `CLOCK_*` constants for use with [`clock_gettime`].
+///
+/// These constants are always supported at runtime, so `clock_gettime` never
+/// has to fail with `INVAL` due to an unsupported clock. See
+/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not
+/// all of them are always supported.
+///
+/// [`clock_gettime`]: crate::time::clock_gettime
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum ClockId {
+ /// `CLOCK_REALTIME`
+ Realtime = linux_raw_sys::general::CLOCK_REALTIME,
+
+ /// `CLOCK_MONOTONIC`
+ Monotonic = linux_raw_sys::general::CLOCK_MONOTONIC,
+
+ /// `CLOCK_PROCESS_CPUTIME_ID`
+ ProcessCPUTime = linux_raw_sys::general::CLOCK_PROCESS_CPUTIME_ID,
+
+ /// `CLOCK_THREAD_CPUTIME_ID`
+ ThreadCPUTime = linux_raw_sys::general::CLOCK_THREAD_CPUTIME_ID,
+
+ /// `CLOCK_REALTIME_COARSE`
+ RealtimeCoarse = linux_raw_sys::general::CLOCK_REALTIME_COARSE,
+
+ /// `CLOCK_MONOTONIC_COARSE`
+ MonotonicCoarse = linux_raw_sys::general::CLOCK_MONOTONIC_COARSE,
+
+ /// `CLOCK_MONOTONIC_RAW`
+ MonotonicRaw = linux_raw_sys::general::CLOCK_MONOTONIC_RAW,
+}
+
+/// `CLOCK_*` constants for use with [`clock_gettime_dynamic`].
+///
+/// These constants may be unsupported at runtime, depending on the OS version,
+/// and `clock_gettime_dynamic` may fail with `INVAL`. See [`ClockId`] for
+/// clocks which are always supported at runtime.
+///
+/// [`clock_gettime_dynamic`]: crate::time::clock_gettime_dynamic
+#[derive(Debug, Copy, Clone)]
+#[non_exhaustive]
+pub enum DynamicClockId<'a> {
+ /// `ClockId` values that are always supported at runtime.
+ Known(ClockId),
+
+ /// Linux dynamic clocks.
+ Dynamic(BorrowedFd<'a>),
+
+ /// `CLOCK_REALTIME_ALARM`, available on Linux >= 3.0
+ RealtimeAlarm,
+
+ /// `CLOCK_TAI`, available on Linux >= 3.10
+ Tai,
+
+ /// `CLOCK_BOOTTIME`, available on Linux >= 2.6.39
+ Boottime,
+
+ /// `CLOCK_BOOTTIME_ALARM`, available on Linux >= 2.6.39
+ BoottimeAlarm,
+}
+
+bitflags! {
+ /// `TFD_*` flags for use with [`timerfd_create`].
+ ///
+ /// [`timerfd_create`]: crate::time::timerfd_create
+ pub struct TimerfdFlags: c::c_uint {
+ /// `TFD_NONBLOCK`
+ const NONBLOCK = linux_raw_sys::general::TFD_NONBLOCK;
+
+ /// `TFD_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::TFD_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `TFD_TIMER_*` flags for use with [`timerfd_settime`].
+ ///
+ /// [`timerfd_settime`]: crate::time::timerfd_settime
+ pub struct TimerfdTimerFlags: c::c_uint {
+ /// `TFD_TIMER_ABSTIME`
+ const ABSTIME = linux_raw_sys::general::TFD_TIMER_ABSTIME;
+
+ /// `TFD_TIMER_CANCEL_ON_SET`
+ const CANCEL_ON_SET = linux_raw_sys::general::TFD_TIMER_CANCEL_ON_SET;
+ }
+}
+
+/// `CLOCK_*` constants for use with [`timerfd_create`].
+///
+/// [`timerfd_create`]: crate::time::timerfd_create
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[repr(u32)]
+#[non_exhaustive]
+pub enum TimerfdClockId {
+ /// `CLOCK_REALTIME`—A clock that tells the "real" time.
+ ///
+ /// This is a clock that tells the amount of time elapsed since the
+ /// Unix epoch, 1970-01-01T00:00:00Z. The clock is externally settable, so
+ /// it is not monotonic. Successive reads may see decreasing times, so it
+ /// isn't reliable for measuring durations.
+ Realtime = linux_raw_sys::general::CLOCK_REALTIME,
+
+ /// `CLOCK_MONOTONIC`—A clock that tells an abstract time.
+ ///
+ /// Unlike `Realtime`, this clock is not based on a fixed known epoch, so
+ /// individual times aren't meaningful. However, since it isn't settable,
+ /// it is reliable for measuring durations.
+ ///
+ /// This clock does not advance while the system is suspended; see
+ /// `Boottime` for a clock that does.
+ Monotonic = linux_raw_sys::general::CLOCK_MONOTONIC,
+
+ /// `CLOCK_BOOTTIME`—Like `Monotonic`, but advances while suspended.
+ ///
+ /// This clock is similar to `Monotonic`, but does advance while the system
+ /// is suspended.
+ Boottime = linux_raw_sys::general::CLOCK_BOOTTIME,
+
+ /// `CLOCK_REALTIME_ALARM`—Like `Realtime`, but wakes a suspended system.
+ ///
+ /// This clock is like `Realtime`, but can wake up a suspended system.
+ ///
+ /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
+ RealtimeAlarm = linux_raw_sys::general::CLOCK_REALTIME_ALARM,
+
+ /// `CLOCK_BOOTTIME_ALARM`—Like `Boottime`, but wakes a suspended system.
+ ///
+ /// This clock is like `Boottime`, but can wake up a suspended system.
+ ///
+ /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
+ BoottimeAlarm = linux_raw_sys::general::CLOCK_BOOTTIME_ALARM,
+}
diff --git a/vendor/rustix/src/imp/linux_raw/vdso.rs b/vendor/rustix/src/imp/linux_raw/vdso.rs
new file mode 100644
index 000000000..bda0a4773
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/vdso.rs
@@ -0,0 +1,435 @@
+//! Parse the Linux vDSO.
+//!
+//! The following code is transliterated from
+//! tools/testing/selftests/vDSO/parse_vdso.c in Linux 5.11, which is licensed
+//! with Creative Commons Zero License, version 1.0,
+//! available at <https://creativecommons.org/publicdomain/zero/1.0/legalcode>
+//!
+//! # Safety
+//!
+//! Parsing the vDSO involves a lot of raw pointer manipulation. This
+//! implementation follows Linux's reference implementation, and adds several
+//! additional safety checks.
+#![allow(unsafe_code)]
+
+use super::c;
+use super::elf::*;
+use super::mm::syscalls::madvise;
+use super::mm::types::Advice;
+use crate::ffi::CStr;
+use crate::io;
+use core::ffi::c_void;
+use core::mem::{align_of, size_of};
+use core::ptr::{null, null_mut};
+
+pub(super) struct Vdso {
+ // Load information
+ load_addr: *const Elf_Ehdr,
+ load_end: *const c_void, // the end of the `PT_LOAD` segment
+ pv_offset: usize, // recorded paddr - recorded vaddr
+
+ // Symbol table
+ symtab: *const Elf_Sym,
+ symstrings: *const u8,
+ bucket: *const u32,
+ chain: *const u32,
+ nbucket: u32,
+ //nchain: u32,
+
+ // Version table
+ versym: *const u16,
+ verdef: *const Elf_Verdef,
+}
+
+// Straight from the ELF specification.
+fn elf_hash(name: &CStr) -> u32 {
+ let mut h: u32 = 0;
+ for b in name.to_bytes() {
+ h = (h << 4).wrapping_add(u32::from(*b));
+ let g = h & 0xf000_0000;
+ if g != 0 {
+ h ^= g >> 24;
+ }
+ h &= !g;
+ }
+ h
+}
+
+/// Cast `value` to a pointer type, doing some checks for validity.
+fn make_pointer<T>(value: *const c_void) -> Option<*const T> {
+ if value.is_null()
+ || (value as usize).checked_add(size_of::<T>()).is_none()
+ || (value as usize) % align_of::<T>() != 0
+ {
+ return None;
+ }
+
+ Some(value.cast())
+}
+
+/// Create a `Vdso` value by parsing the vDSO at the given address.
+///
+/// # Safety
+///
+/// `base` must be a valid pointer to an ELF image in memory.
+unsafe fn init_from_sysinfo_ehdr(base: *const Elf_Ehdr) -> Option<Vdso> {
+ // Check that `base` is a valid pointer to the kernel-provided vDSO.
+ let hdr = check_vdso_base(base)?;
+
+ let mut vdso = Vdso {
+ load_addr: base,
+ load_end: base.cast(),
+ pv_offset: 0,
+ symtab: null(),
+ symstrings: null(),
+ bucket: null(),
+ chain: null(),
+ nbucket: 0,
+ //nchain: 0,
+ versym: null(),
+ verdef: null(),
+ };
+
+ let pt = make_pointer::<Elf_Phdr>(vdso.base_plus(hdr.e_phoff)?)?;
+ let mut dyn_: *const Elf_Dyn = null();
+ let mut num_dyn = 0;
+
+ // We need two things from the segment table: the load offset
+ // and the dynamic table.
+ let mut found_vaddr = false;
+ for i in 0..hdr.e_phnum {
+ let phdr = &*pt.add(i as usize);
+ if phdr.p_flags & PF_W != 0 {
+ // Don't trust any vDSO that claims to be loading writable
+ // segments into memory.
+ return None;
+ }
+ if phdr.p_type == PT_LOAD && !found_vaddr {
+ // The segment should be readable and executable, because it
+ // contains the symbol table and the function bodies.
+ if phdr.p_flags & (PF_R | PF_X) != (PF_R | PF_X) {
+ return None;
+ }
+ found_vaddr = true;
+ vdso.load_end = vdso.base_plus(phdr.p_offset.checked_add(phdr.p_memsz)?)?;
+ vdso.pv_offset = phdr.p_offset.wrapping_sub(phdr.p_vaddr);
+ } else if phdr.p_type == PT_DYNAMIC {
+ // If `p_offset` is zero, it's more likely that we're looking at memory
+ // that has been zeroed than that the kernel has somehow aliased the
+ // `Ehdr` and the `Elf_Dyn` array.
+ if phdr.p_offset < size_of::<Elf_Ehdr>() {
+ return None;
+ }
+
+ dyn_ = make_pointer::<Elf_Dyn>(vdso.base_plus(phdr.p_offset)?)?;
+ num_dyn = phdr.p_memsz / size_of::<Elf_Dyn>();
+ } else if phdr.p_type == PT_INTERP || phdr.p_type == PT_GNU_RELRO {
+ // Don't trust any ELF image that has an "interpreter" or that uses
+ // RELRO, which is likely to be a user ELF image rather and not the
+ // kernel vDSO.
+ return None;
+ }
+ }
+
+ if !found_vaddr || dyn_.is_null() {
+ return None; // Failed
+ }
+
+ // Fish out the useful bits of the dynamic table.
+ let mut hash: *const u32 = null();
+ vdso.symstrings = null();
+ vdso.symtab = null();
+ vdso.versym = null();
+ vdso.verdef = null();
+ let mut i = 0;
+ loop {
+ if i == num_dyn {
+ return None;
+ }
+ let d = &*dyn_.add(i);
+ match d.d_tag {
+ DT_STRTAB => {
+ vdso.symstrings = make_pointer::<u8>(vdso.addr_from_elf(d.d_val)?)?;
+ }
+ DT_SYMTAB => {
+ vdso.symtab = make_pointer::<Elf_Sym>(vdso.addr_from_elf(d.d_val)?)?;
+ }
+ DT_HASH => {
+ hash = make_pointer::<u32>(vdso.addr_from_elf(d.d_val)?)?;
+ }
+ DT_VERSYM => {
+ vdso.versym = make_pointer::<u16>(vdso.addr_from_elf(d.d_val)?)?;
+ }
+ DT_VERDEF => {
+ vdso.verdef = make_pointer::<Elf_Verdef>(vdso.addr_from_elf(d.d_val)?)?;
+ }
+ DT_SYMENT => {
+ if d.d_val != size_of::<Elf_Sym>() {
+ return None; // Failed
+ }
+ }
+ DT_NULL => break,
+ _ => {}
+ }
+ i = i.checked_add(1)?;
+ }
+ if vdso.symstrings.is_null() || vdso.symtab.is_null() || hash.is_null() {
+ return None; // Failed
+ }
+
+ if vdso.verdef.is_null() {
+ vdso.versym = null();
+ }
+
+ // Parse the hash table header.
+ vdso.nbucket = *hash.add(0);
+ //vdso.nchain = *hash.add(1);
+ vdso.bucket = hash.add(2);
+ vdso.chain = hash.add(vdso.nbucket as usize + 2);
+
+ // That's all we need.
+ Some(vdso)
+}
+
+/// Check that `base` is a valid pointer to the kernel-provided vDSO.
+///
+/// `base` is some value we got from a `AT_SYSINFO_EHDR` aux record somewhere,
+/// which hopefully holds the value of the kernel-provided vDSO in memory. Do a
+/// series of checks to be as sure as we can that it's safe to use.
+unsafe fn check_vdso_base<'vdso>(base: *const Elf_Ehdr) -> Option<&'vdso Elf_Ehdr> {
+ // In theory, we could check that we're not attempting to parse our own ELF
+ // image, as an additional check. However, older Linux toolchains don't
+ // support this, and Rust's `#[linkage = "extern_weak"]` isn't stable yet,
+ // so just disable this for now.
+ /*
+ {
+ extern "C" {
+ static __ehdr_start: c::c_void;
+ }
+
+ let ehdr_start: *const c::c_void = &__ehdr_start;
+ if base == ehdr_start {
+ return None;
+ }
+ }
+ */
+
+ let hdr = &*make_pointer::<Elf_Ehdr>(base.cast())?;
+
+ // Check that the vDSO is page-aligned and appropriately mapped. We call
+ // this after `make_pointer` so that we don't do a syscall if there's no
+ // chance the pointer is valid.
+ madvise(base as *mut c_void, size_of::<Elf_Ehdr>(), Advice::Normal).ok()?;
+
+ if hdr.e_ident[..SELFMAG] != ELFMAG {
+ return None; // Wrong ELF magic
+ }
+ if hdr.e_ident[EI_CLASS] != ELFCLASS {
+ return None; // Wrong ELF class
+ }
+ if hdr.e_ident[EI_DATA] != ELFDATA {
+ return None; // Wrong ELF data
+ }
+ if !matches!(hdr.e_ident[EI_OSABI], ELFOSABI_SYSV | ELFOSABI_LINUX) {
+ return None; // Unrecognized ELF OS ABI
+ }
+ if hdr.e_ident[EI_ABIVERSION] != ELFABIVERSION {
+ return None; // Unrecognized ELF ABI version
+ }
+ if hdr.e_type != ET_DYN {
+ return None; // Wrong ELF type
+ }
+ // Verify that the `e_machine` matches the architecture we're running as.
+ // This helps catch cases where we're running under qemu.
+ if hdr.e_machine != EM_CURRENT {
+ return None; // Wrong machine type
+ }
+
+ // If ELF is extended, we'll need to adjust.
+ if hdr.e_ident[EI_VERSION] != EV_CURRENT
+ || hdr.e_ehsize as usize != size_of::<Elf_Ehdr>()
+ || hdr.e_phentsize as usize != size_of::<Elf_Phdr>()
+ {
+ return None;
+ }
+ // We don't currently support extra-large numbers of segments.
+ if hdr.e_phnum == PN_XNUM {
+ return None;
+ }
+
+ // If `e_phoff` is zero, it's more likely that we're looking at memory that
+ // has been zeroed than that the kernel has somehow aliased the `Ehdr` and
+ // the `Phdr`.
+ if hdr.e_phoff < size_of::<Elf_Ehdr>() {
+ return None;
+ }
+
+ // Check that the vDSO is not writable, since that would indicate that this
+ // isn't the kernel vDSO. Here we're just using `clock_getres` just as an
+ // arbitrary system call which writes to a buffer and fails with `EFAULT`
+ // if the buffer is not writable.
+ {
+ use super::conv::ret;
+ use super::time::types::ClockId;
+ if ret(syscall!(__NR_clock_getres, ClockId::Monotonic, base)) != Err(io::Errno::FAULT) {
+ // We can't gracefully fail here because we would seem to have just
+ // mutated some unknown memory.
+ #[cfg(feature = "std")]
+ {
+ std::process::abort();
+ }
+ #[cfg(all(not(feature = "std"), feature = "rustc-dep-of-std"))]
+ {
+ core::intrinsics::abort();
+ }
+ }
+ }
+
+ Some(hdr)
+}
+
+impl Vdso {
+ /// Parse the vDSO.
+ ///
+ /// Returns None if the vDSO can't be located or if it doesn't conform
+ /// to our expectations.
+ #[inline]
+ pub(super) fn new() -> Option<Self> {
+ init_from_auxv()
+ }
+
+ /// Check the version for a symbol.
+ ///
+ /// # Safety
+ ///
+ /// The raw pointers inside `self` must be valid.
+ unsafe fn match_version(&self, mut ver: u16, name: &CStr, hash: u32) -> bool {
+ // This is a helper function to check if the version indexed by
+ // ver matches name (which hashes to hash).
+ //
+ // The version definition table is a mess, and I don't know how
+ // to do this in better than linear time without allocating memory
+ // to build an index. I also don't know why the table has
+ // variable size entries in the first place.
+ //
+ // For added fun, I can't find a comprehensible specification of how
+ // to parse all the weird flags in the table.
+ //
+ // So I just parse the whole table every time.
+
+ // First step: find the version definition
+ ver &= 0x7fff; // Apparently bit 15 means "hidden"
+ let mut def = self.verdef;
+ loop {
+ if (*def).vd_version != VER_DEF_CURRENT {
+ return false; // Failed
+ }
+
+ if ((*def).vd_flags & VER_FLG_BASE) == 0 && ((*def).vd_ndx & 0x7fff) == ver {
+ break;
+ }
+
+ if (*def).vd_next == 0 {
+ return false; // No definition.
+ }
+
+ def = def
+ .cast::<u8>()
+ .add((*def).vd_next as usize)
+ .cast::<Elf_Verdef>();
+ }
+
+ // Now figure out whether it matches.
+ let aux = &*(def.cast::<u8>())
+ .add((*def).vd_aux as usize)
+ .cast::<Elf_Verdaux>();
+ (*def).vd_hash == hash
+ && (name == CStr::from_ptr(self.symstrings.add(aux.vda_name as usize).cast()))
+ }
+
+ /// Look up a symbol in the vDSO.
+ pub(super) fn sym(&self, version: &CStr, name: &CStr) -> *mut c::c_void {
+ let ver_hash = elf_hash(version);
+ let name_hash = elf_hash(name);
+
+ // Safety: The pointers in `self` must be valid.
+ unsafe {
+ let mut chain = *self.bucket.add((name_hash % self.nbucket) as usize);
+
+ while chain != STN_UNDEF {
+ let sym = &*self.symtab.add(chain as usize);
+
+ // Check for a defined global or weak function w/ right name.
+ //
+ // The reference parser in Linux's parse_vdso.c requires
+ // symbols to have type `STT_FUNC`, but on powerpc64, the vDSO
+ // uses `STT_NOTYPE`, so allow that too.
+ if (ELF_ST_TYPE(sym.st_info) != STT_FUNC &&
+ ELF_ST_TYPE(sym.st_info) != STT_NOTYPE)
+ || (ELF_ST_BIND(sym.st_info) != STB_GLOBAL
+ && ELF_ST_BIND(sym.st_info) != STB_WEAK)
+ || sym.st_shndx == SHN_UNDEF
+ || sym.st_shndx == SHN_ABS
+ || ELF_ST_VISIBILITY(sym.st_other) != STV_DEFAULT
+ || (name != CStr::from_ptr(self.symstrings.add(sym.st_name as usize).cast()))
+ // Check symbol version.
+ || (!self.versym.is_null()
+ && !self.match_version(*self.versym.add(chain as usize), version, ver_hash))
+ {
+ chain = *self.chain.add(chain as usize);
+ continue;
+ }
+
+ let sum = self.addr_from_elf(sym.st_value).unwrap();
+ assert!(
+ sum as usize >= self.load_addr as usize
+ && sum as usize <= self.load_end as usize
+ );
+ return sum as *mut c::c_void;
+ }
+ }
+
+ null_mut()
+ }
+
+ /// Add the given address to the vDSO base address.
+ unsafe fn base_plus(&self, offset: usize) -> Option<*const c_void> {
+ // Check for overflow.
+ let _ = (self.load_addr as usize).checked_add(offset)?;
+ // Add the offset to the base.
+ Some(self.load_addr.cast::<u8>().add(offset).cast())
+ }
+
+ /// Translate an ELF-address-space address into a usable virtual address.
+ unsafe fn addr_from_elf(&self, elf_addr: usize) -> Option<*const c_void> {
+ self.base_plus(elf_addr.wrapping_add(self.pv_offset))
+ }
+}
+
+// Find the `AT_SYSINFO_EHDR` in auxv records in memory. We have our own code
+// for reading the auxv records in memory, so we don't currently use this.
+//
+// # Safety
+//
+// `elf_auxv` must point to a valid array of AUXV records terminated by an
+// `AT_NULL` record.
+/*
+unsafe fn init_from_auxv(elf_auxv: *const Elf_auxv_t) -> Option<Vdso> {
+ let mut i = 0;
+ while (*elf_auxv.add(i)).a_type != AT_NULL {
+ if (*elf_auxv.add(i)).a_type == AT_SYSINFO_EHDR {
+ return init_from_sysinfo_ehdr((*elf_auxv.add(i)).a_val);
+ }
+ i += 1;
+ }
+
+ None
+}
+*/
+
+/// Find the vDSO image by following the `AT_SYSINFO_EHDR` auxv record pointer.
+fn init_from_auxv() -> Option<Vdso> {
+ // Safety: `sysinfo_ehdr` does extensive checks to ensure that the value
+ // we get really is an `AT_SYSINFO_EHDR` value from the kernel.
+ unsafe { init_from_sysinfo_ehdr(super::param::auxv::sysinfo_ehdr()) }
+}
diff --git a/vendor/rustix/src/imp/linux_raw/vdso_wrappers.rs b/vendor/rustix/src/imp/linux_raw/vdso_wrappers.rs
new file mode 100644
index 000000000..80c8dbefd
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/vdso_wrappers.rs
@@ -0,0 +1,397 @@
+//! Implement syscalls using the vDSO.
+//!
+//! <https://man7.org/linux/man-pages/man7/vdso.7.html>
+//!
+//! # Safety
+//!
+//! Similar to syscalls.rs, this file performs raw system calls, and sometimes
+//! passes them uninitialized memory buffers. This file also calls vDSO
+//! functions.
+#![allow(unsafe_code)]
+
+use super::conv::{c_int, ret};
+#[cfg(target_arch = "x86")]
+use super::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
+use super::time::types::{ClockId, DynamicClockId, Timespec};
+use super::{c, vdso};
+use crate::io;
+#[cfg(all(asm, target_arch = "x86"))]
+use core::arch::asm;
+use core::mem::{transmute, MaybeUninit};
+use core::ptr::null_mut;
+use core::sync::atomic::AtomicPtr;
+use core::sync::atomic::Ordering::Relaxed;
+#[cfg(target_pointer_width = "32")]
+use linux_raw_sys::general::timespec as __kernel_old_timespec;
+use linux_raw_sys::general::{__kernel_clockid_t, __kernel_timespec};
+
+#[inline]
+pub(crate) fn clock_gettime(which_clock: ClockId) -> __kernel_timespec {
+ // Safety: `CLOCK_GETTIME` contains either null or the address of a
+ // function with an ABI like libc `clock_gettime`, and calling it has
+ // the side effect of writing to the result buffer, and no others.
+ unsafe {
+ let mut result = MaybeUninit::<__kernel_timespec>::uninit();
+ let callee = match transmute(CLOCK_GETTIME.load(Relaxed)) {
+ Some(callee) => callee,
+ None => init_clock_gettime(),
+ };
+ let r0 = callee(which_clock as c::c_int, result.as_mut_ptr());
+ assert_eq!(r0, 0);
+ result.assume_init()
+ }
+}
+
+#[inline]
+pub(crate) fn clock_gettime_dynamic(which_clock: DynamicClockId<'_>) -> io::Result<Timespec> {
+ let id = match which_clock {
+ DynamicClockId::Known(id) => id as __kernel_clockid_t,
+
+ DynamicClockId::Dynamic(fd) => {
+ // See `FD_TO_CLOCKID` in Linux's `clock_gettime` documentation.
+ use crate::imp::fd::AsRawFd;
+ const CLOCKFD: i32 = 3;
+ ((!fd.as_raw_fd() << 3) | CLOCKFD) as __kernel_clockid_t
+ }
+
+ DynamicClockId::RealtimeAlarm => {
+ linux_raw_sys::general::CLOCK_REALTIME_ALARM as __kernel_clockid_t
+ }
+ DynamicClockId::Tai => linux_raw_sys::general::CLOCK_TAI as __kernel_clockid_t,
+ DynamicClockId::Boottime => linux_raw_sys::general::CLOCK_BOOTTIME as __kernel_clockid_t,
+ DynamicClockId::BoottimeAlarm => {
+ linux_raw_sys::general::CLOCK_BOOTTIME_ALARM as __kernel_clockid_t
+ }
+ };
+
+ // Safety: `CLOCK_GETTIME` contains either null or the address of a
+ // function with an ABI like libc `clock_gettime`, and calling it has
+ // the side effect of writing to the result buffer, and no others.
+ unsafe {
+ const EINVAL: c::c_int = -(c::EINVAL as c::c_int);
+ let mut timespec = MaybeUninit::<Timespec>::uninit();
+ let callee = match transmute(CLOCK_GETTIME.load(Relaxed)) {
+ Some(callee) => callee,
+ None => init_clock_gettime(),
+ };
+ match callee(id, timespec.as_mut_ptr()) {
+ 0 => (),
+ EINVAL => return Err(io::Errno::INVAL),
+ _ => _rustix_clock_gettime_via_syscall(id, timespec.as_mut_ptr())?,
+ }
+ Ok(timespec.assume_init())
+ }
+}
+
+#[cfg(target_arch = "x86")]
+pub(super) mod x86_via_vdso {
+ use super::{transmute, ArgReg, Relaxed, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
+ use crate::imp::arch::asm;
+
+ #[inline]
+ pub(in crate::imp) unsafe fn syscall0(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ let callee = match transmute(super::SYSCALL.load(Relaxed)) {
+ Some(callee) => callee,
+ None => super::init_syscall(),
+ };
+ asm::indirect_syscall0(callee, nr)
+ }
+
+ #[inline]
+ pub(in crate::imp) unsafe fn syscall1<'a>(
+ nr: SyscallNumber<'a>,
+ a0: ArgReg<'a, A0>,
+ ) -> RetReg<R0> {
+ let callee = match transmute(super::SYSCALL.load(Relaxed)) {
+ Some(callee) => callee,
+ None => super::init_syscall(),
+ };
+ asm::indirect_syscall1(callee, nr, a0)
+ }
+
+ #[inline]
+ pub(in crate::imp) unsafe fn syscall1_noreturn<'a>(
+ nr: SyscallNumber<'a>,
+ a0: ArgReg<'a, A0>,
+ ) -> ! {
+ let callee = match transmute(super::SYSCALL.load(Relaxed)) {
+ Some(callee) => callee,
+ None => super::init_syscall(),
+ };
+ asm::indirect_syscall1_noreturn(callee, nr, a0)
+ }
+
+ #[inline]
+ pub(in crate::imp) unsafe fn syscall2<'a>(
+ nr: SyscallNumber<'a>,
+ a0: ArgReg<'a, A0>,
+ a1: ArgReg<'a, A1>,
+ ) -> RetReg<R0> {
+ let callee = match transmute(super::SYSCALL.load(Relaxed)) {
+ Some(callee) => callee,
+ None => super::init_syscall(),
+ };
+ asm::indirect_syscall2(callee, nr, a0, a1)
+ }
+
+ #[inline]
+ pub(in crate::imp) unsafe fn syscall3<'a>(
+ nr: SyscallNumber<'a>,
+ a0: ArgReg<'a, A0>,
+ a1: ArgReg<'a, A1>,
+ a2: ArgReg<'a, A2>,
+ ) -> RetReg<R0> {
+ let callee = match transmute(super::SYSCALL.load(Relaxed)) {
+ Some(callee) => callee,
+ None => super::init_syscall(),
+ };
+ asm::indirect_syscall3(callee, nr, a0, a1, a2)
+ }
+
+ #[inline]
+ pub(in crate::imp) unsafe fn syscall4<'a>(
+ nr: SyscallNumber<'a>,
+ a0: ArgReg<'a, A0>,
+ a1: ArgReg<'a, A1>,
+ a2: ArgReg<'a, A2>,
+ a3: ArgReg<'a, A3>,
+ ) -> RetReg<R0> {
+ let callee = match transmute(super::SYSCALL.load(Relaxed)) {
+ Some(callee) => callee,
+ None => super::init_syscall(),
+ };
+ asm::indirect_syscall4(callee, nr, a0, a1, a2, a3)
+ }
+
+ #[inline]
+ pub(in crate::imp) unsafe fn syscall5<'a>(
+ nr: SyscallNumber<'a>,
+ a0: ArgReg<'a, A0>,
+ a1: ArgReg<'a, A1>,
+ a2: ArgReg<'a, A2>,
+ a3: ArgReg<'a, A3>,
+ a4: ArgReg<'a, A4>,
+ ) -> RetReg<R0> {
+ let callee = match transmute(super::SYSCALL.load(Relaxed)) {
+ Some(callee) => callee,
+ None => super::init_syscall(),
+ };
+ asm::indirect_syscall5(callee, nr, a0, a1, a2, a3, a4)
+ }
+
+ #[inline]
+ pub(in crate::imp) unsafe fn syscall6<'a>(
+ nr: SyscallNumber<'a>,
+ a0: ArgReg<'a, A0>,
+ a1: ArgReg<'a, A1>,
+ a2: ArgReg<'a, A2>,
+ a3: ArgReg<'a, A3>,
+ a4: ArgReg<'a, A4>,
+ a5: ArgReg<'a, A5>,
+ ) -> RetReg<R0> {
+ let callee = match transmute(super::SYSCALL.load(Relaxed)) {
+ Some(callee) => callee,
+ None => super::init_syscall(),
+ };
+ asm::indirect_syscall6(callee, nr, a0, a1, a2, a3, a4, a5)
+ }
+
+ // With the indirect call, it isn't meaningful to do a separate
+ // `_readonly` optimization.
+ pub(in crate::imp) use {
+ syscall0 as syscall0_readonly, syscall1 as syscall1_readonly,
+ syscall2 as syscall2_readonly, syscall3 as syscall3_readonly,
+ syscall4 as syscall4_readonly, syscall5 as syscall5_readonly,
+ syscall6 as syscall6_readonly,
+ };
+}
+
+type ClockGettimeType = unsafe extern "C" fn(c::c_int, *mut Timespec) -> c::c_int;
+
+/// The underlying syscall functions are only called from asm, using the
+/// special syscall calling convention to pass arguments and return values,
+/// which the signature here doesn't reflect.
+#[cfg(target_arch = "x86")]
+pub(super) type SyscallType = unsafe extern "C" fn();
+
+fn init_clock_gettime() -> ClockGettimeType {
+ init();
+ // Safety: Load the function address from static storage that we
+ // just initialized.
+ unsafe { transmute(CLOCK_GETTIME.load(Relaxed)) }
+}
+
+#[cfg(target_arch = "x86")]
+fn init_syscall() -> SyscallType {
+ init();
+ // Safety: Load the function address from static storage that we
+ // just initialized.
+ unsafe { transmute(SYSCALL.load(Relaxed)) }
+}
+
+/// `AtomicPtr` can't hold a `fn` pointer, so we use a `*` pointer to this
+/// placeholder type, and cast it as needed.
+struct Function;
+static mut CLOCK_GETTIME: AtomicPtr<Function> = AtomicPtr::new(null_mut());
+#[cfg(target_arch = "x86")]
+static mut SYSCALL: AtomicPtr<Function> = AtomicPtr::new(null_mut());
+
+unsafe extern "C" fn rustix_clock_gettime_via_syscall(
+ clockid: c::c_int,
+ res: *mut Timespec,
+) -> c::c_int {
+ match _rustix_clock_gettime_via_syscall(clockid, res) {
+ Ok(()) => 0,
+ Err(e) => e.raw_os_error().wrapping_neg(),
+ }
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn _rustix_clock_gettime_via_syscall(
+ clockid: c::c_int,
+ res: *mut Timespec,
+) -> io::Result<()> {
+ let r0 = syscall!(__NR_clock_gettime64, c_int(clockid), res);
+ match ret(r0) {
+ Err(io::Errno::NOSYS) => _rustix_clock_gettime_via_syscall_old(clockid, res),
+ otherwise => otherwise,
+ }
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe fn _rustix_clock_gettime_via_syscall_old(
+ clockid: c::c_int,
+ res: *mut Timespec,
+) -> io::Result<()> {
+ // Ordinarily `rustix` doesn't like to emulate system calls, but in
+ // the case of time APIs, it's specific to Linux, specific to
+ // 32-bit architectures *and* specific to old kernel versions, and
+ // it's not that hard to fix up here, so that no other code needs
+ // to worry about this.
+ let mut old_result = MaybeUninit::<__kernel_old_timespec>::uninit();
+ let r0 = syscall!(__NR_clock_gettime, c_int(clockid), &mut old_result);
+ match ret(r0) {
+ Ok(()) => {
+ let old_result = old_result.assume_init();
+ *res = Timespec {
+ tv_sec: old_result.tv_sec.into(),
+ tv_nsec: old_result.tv_nsec.into(),
+ };
+ Ok(())
+ }
+ otherwise => otherwise,
+ }
+}
+
+#[cfg(target_pointer_width = "64")]
+unsafe fn _rustix_clock_gettime_via_syscall(
+ clockid: c::c_int,
+ res: *mut Timespec,
+) -> io::Result<()> {
+ ret(syscall!(__NR_clock_gettime, c_int(clockid), res))
+}
+
+/// A symbol pointing to an `int 0x80` instruction. This "function" is only
+/// called from assembly, and only with the x86 syscall calling convention,
+/// so its signature here is not its true signature.
+#[cfg(all(asm, target_arch = "x86"))]
+#[naked]
+unsafe extern "C" fn rustix_int_0x80() {
+ asm!("int $$0x80", "ret", options(noreturn))
+}
+
+// The outline version of the `rustix_int_0x80` above.
+#[cfg(all(not(asm), target_arch = "x86"))]
+extern "C" {
+ fn rustix_int_0x80();
+}
+
+fn minimal_init() {
+ // Safety: Store default function addresses in static storage so that if we
+ // end up making any system calls while we read the vDSO, they'll work.
+ // If the memory happens to already be initialized, this is redundant, but
+ // not harmful.
+ unsafe {
+ CLOCK_GETTIME
+ .compare_exchange(
+ null_mut(),
+ rustix_clock_gettime_via_syscall as *mut Function,
+ Relaxed,
+ Relaxed,
+ )
+ .ok();
+ #[cfg(target_arch = "x86")]
+ {
+ SYSCALL
+ .compare_exchange(
+ null_mut(),
+ rustix_int_0x80 as *mut Function,
+ Relaxed,
+ Relaxed,
+ )
+ .ok();
+ }
+ }
+}
+
+fn init() {
+ minimal_init();
+
+ if let Some(vdso) = vdso::Vdso::new() {
+ // Look up the platform-specific `clock_gettime` symbol as documented
+ // [here], except on 32-bit platforms where we look up the
+ // `64`-suffixed variant and fail if we don't find it.
+ //
+ // [here]: https://man7.org/linux/man-pages/man7/vdso.7.html
+ #[cfg(target_arch = "x86_64")]
+ let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime"));
+ #[cfg(target_arch = "arm")]
+ let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64"));
+ #[cfg(target_arch = "aarch64")]
+ let ptr = vdso.sym(cstr!("LINUX_2.6.39"), cstr!("__kernel_clock_gettime"));
+ #[cfg(target_arch = "x86")]
+ let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64"));
+ #[cfg(target_arch = "riscv64")]
+ let ptr = vdso.sym(cstr!("LINUX_4.15"), cstr!("__vdso_clock_gettime"));
+ #[cfg(target_arch = "powerpc64")]
+ let ptr = vdso.sym(cstr!("LINUX_2.6.15"), cstr!("__kernel_clock_gettime"));
+ #[cfg(target_arch = "mips")]
+ let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64"));
+ #[cfg(target_arch = "mips64")]
+ let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime"));
+
+ // On all 64-bit platforms, the 64-bit `clock_gettime` symbols are
+ // always available.
+ #[cfg(any(target_pointer_width = "64"))]
+ let ok = true;
+
+ // On some 32-bit platforms, the 64-bit `clock_gettime` symbols are not
+ // available on older kernel versions.
+ #[cfg(any(target_arch = "arm", target_arch = "mips", target_arch = "x86"))]
+ let ok = !ptr.is_null();
+
+ if ok {
+ assert!(!ptr.is_null());
+
+ // Safety: Store the computed function addresses in static storage
+ // so that we don't need to compute it again (but if we do, it doesn't
+ // hurt anything).
+ unsafe {
+ CLOCK_GETTIME.store(ptr.cast(), Relaxed);
+ }
+ }
+
+ // On x86, also look up the vsyscall entry point.
+ #[cfg(target_arch = "x86")]
+ {
+ let ptr = vdso.sym(cstr!("LINUX_2.5"), cstr!("__kernel_vsyscall"));
+ assert!(!ptr.is_null());
+
+ // Safety: As above, store the computed function addresses in
+ // static storage.
+ unsafe {
+ SYSCALL.store(ptr.cast(), Relaxed);
+ }
+ }
+ }
+}
diff --git a/vendor/rustix/src/io/close.rs b/vendor/rustix/src/io/close.rs
new file mode 100644
index 000000000..2116f53bd
--- /dev/null
+++ b/vendor/rustix/src/io/close.rs
@@ -0,0 +1,41 @@
+//! The unsafe `close` for raw file descriptors.
+//!
+//! # Safety
+//!
+//! Operating on raw file descriptors is unsafe.
+#![allow(unsafe_code)]
+
+use crate::imp;
+use imp::fd::RawFd;
+
+/// `close(raw_fd)`—Closes a `RawFd` directly.
+///
+/// Most users won't need to use this, as `OwnedFd` automatically closes its
+/// file descriptor on `Drop`.
+///
+/// This function does not return a `Result`, as it is the [responsibility] of
+/// filesystem designers to not return errors from `close`. Users who chose to
+/// use NFS or similar filesystems should take care to monitor for problems
+/// externally.
+///
+/// [responsibility]: https://lwn.net/Articles/576518/
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/close.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/close.2.html#//apple_ref/doc/man/2/close
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket
+///
+/// # Safety
+///
+/// This function takes a `RawFd`, which must be valid before the call, and is
+/// not valid after the call.
+#[inline]
+pub unsafe fn close(raw_fd: RawFd) {
+ imp::io::syscalls::close(raw_fd)
+}
diff --git a/vendor/rustix/src/io/dup.rs b/vendor/rustix/src/io/dup.rs
new file mode 100644
index 000000000..ffa0401f2
--- /dev/null
+++ b/vendor/rustix/src/io/dup.rs
@@ -0,0 +1,80 @@
+//! Functions which duplicate file descriptors.
+
+use crate::imp;
+use crate::io::{self, OwnedFd};
+use imp::fd::AsFd;
+
+#[cfg(not(target_os = "wasi"))]
+pub use imp::io::types::DupFlags;
+
+/// `dup(fd)`—Creates a new `OwnedFd` instance that shares the same
+/// underlying [file description] as `fd`.
+///
+/// This function does not set the `O_CLOEXEC` flag. To do a `dup` that does
+/// set `O_CLOEXEC`, use [`fcntl_dupfd_cloexec`].
+///
+/// POSIX guarantees that `dup` will use the lowest unused file descriptor,
+/// however it is not safe in general to rely on this, as file descriptors may
+/// be unexpectedly allocated on other threads or in libraries.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
+/// [`fcntl_dupfd_cloexec`]: crate::fs::fcntl_dupfd_cloexec
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/dup.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/dup.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn dup<Fd: AsFd>(fd: Fd) -> io::Result<OwnedFd> {
+ imp::io::syscalls::dup(fd.as_fd())
+}
+
+/// `dup2(fd, new)`—Changes the [file description] of a file descriptor.
+///
+/// `dup2` conceptually closes `new` and then sets the file description for
+/// `new` to be the same as the one for `fd`. This is a very unusual operation,
+/// and should only be used on file descriptors where you know how `new` will
+/// be subsequently used.
+///
+/// This function does not set the `O_CLOEXEC` flag. To do a `dup2` that does
+/// set `O_CLOEXEC`, use [`dup3`] with [`DupFlags::CLOEXEC`] on platforms which
+/// support it, or [`fcntl_dupfd_cloexec`]
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
+/// [`fcntl_dupfd_cloexec`]: crate::fs::fcntl_dupfd_cloexec
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/dup2.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/dup2.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn dup2<Fd: AsFd>(fd: Fd, new: &mut OwnedFd) -> io::Result<()> {
+ imp::io::syscalls::dup2(fd.as_fd(), new)
+}
+
+/// `dup3(fd, new, flags)`—Changes the [file description] of a file
+/// descriptor, with flags.
+///
+/// `dup3` is the same as [`dup2`] but adds an additional flags operand, and it
+/// fails in the case that `fd` and `new` have the same file descriptor value.
+/// This additional difference is the reason this function isn't named
+/// `dup2_with`.
+///
+/// # References
+/// - [Linux]
+///
+/// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
+/// [Linux]: https://man7.org/linux/man-pages/man2/dup3.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn dup3<Fd: AsFd>(fd: Fd, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()> {
+ imp::io::syscalls::dup3(fd.as_fd(), new, flags)
+}
diff --git a/vendor/rustix/src/io/errno.rs b/vendor/rustix/src/io/errno.rs
new file mode 100644
index 000000000..84ced6a37
--- /dev/null
+++ b/vendor/rustix/src/io/errno.rs
@@ -0,0 +1,85 @@
+//! The `Errno` type, which is a minimal wrapper around an error code.
+//!
+//! We define the error constants as individual `const`s instead of an
+//! enum because we may not know about all of the host's error values
+//! and we don't want unrecognized values to create UB.
+
+use crate::imp;
+use core::{fmt, result};
+#[cfg(feature = "std")]
+use std::error;
+
+/// A specialized [`Result`] type for `rustix` APIs.
+///
+/// [`Result`]: core::result::Result
+pub type Result<T> = result::Result<T, Errno>;
+
+/// `errno`—An error code.
+///
+/// The error type for `rustix` APIs. This is similar to `std::io::Error`, but
+/// only holds an OS error code, and no extra error value.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/errno.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/errno.3.html
+pub use imp::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/vendor/rustix/src/io/eventfd.rs b/vendor/rustix/src/io/eventfd.rs
new file mode 100644
index 000000000..53e9d11f0
--- /dev/null
+++ b/vendor/rustix/src/io/eventfd.rs
@@ -0,0 +1,16 @@
+use crate::imp;
+use crate::io::{self, OwnedFd};
+
+pub use imp::io::types::EventfdFlags;
+
+/// `eventfd(initval, flags)`—Creates a file descriptor for event
+/// notification.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/eventfd.2.html
+#[inline]
+pub fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
+ imp::io::syscalls::eventfd(initval, flags)
+}
diff --git a/vendor/rustix/src/io/fd/mod.rs b/vendor/rustix/src/io/fd/mod.rs
new file mode 100644
index 000000000..0978b5421
--- /dev/null
+++ b/vendor/rustix/src/io/fd/mod.rs
@@ -0,0 +1,17 @@
+//! The following is derived from Rust's
+//! library/std/src/os/fd/mod.rs at revision
+//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9.
+//!
+//! Owned and borrowed Unix-like file descriptors.
+
+#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+#![deny(unsafe_op_in_unsafe_fn)]
+
+// `RawFd`, `AsRawFd`, etc.
+mod raw;
+
+// `OwnedFd`, `AsFd`, etc.
+mod owned;
+
+pub use owned::*;
+pub use raw::*;
diff --git a/vendor/rustix/src/io/fd/owned.rs b/vendor/rustix/src/io/fd/owned.rs
new file mode 100644
index 000000000..d99b6a0f9
--- /dev/null
+++ b/vendor/rustix/src/io/fd/owned.rs
@@ -0,0 +1,252 @@
+//! The following is derived from Rust's
+//! library/std/src/os/fd/owned.rs at revision
+//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9.
+//!
+//! Owned and borrowed Unix-like file descriptors.
+
+#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![allow(unsafe_code)]
+
+use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+use crate::io::close;
+use core::fmt;
+use core::marker::PhantomData;
+use core::mem::forget;
+
+/// A borrowed file descriptor.
+///
+/// This has a lifetime parameter to tie it to the lifetime of something that
+/// owns the file descriptor.
+///
+/// This uses `repr(transparent)` and has the representation of a host file
+/// descriptor, so it can be used in FFI in places where a file descriptor is
+/// passed as an argument, it is not captured or consumed, and it never has the
+/// value `-1`.
+///
+/// This type's `.to_owned()` implementation returns another `BorrowedFd`
+/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file
+/// descriptor, which is then borrowed under the same lifetime.
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))]
+// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
+// 32-bit c_int. Below is -2, in two's complement, but that only works out
+// because c_int is 32 bits.
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)]
+pub struct BorrowedFd<'fd> {
+ fd: RawFd,
+ _phantom: PhantomData<&'fd OwnedFd>,
+}
+
+/// An owned file descriptor.
+///
+/// This closes the file descriptor on drop.
+///
+/// This uses `repr(transparent)` and has the representation of a host file
+/// descriptor, so it can be used in FFI in places where a file descriptor is
+/// passed as a consumed argument or returned as an owned value, and it never
+/// has the value `-1`.
+#[repr(transparent)]
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))]
+// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
+// 32-bit c_int. Below is -2, in two's complement, but that only works out
+// because c_int is 32 bits.
+#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)]
+pub struct OwnedFd {
+ fd: RawFd,
+}
+
+impl BorrowedFd<'_> {
+ /// Return a `BorrowedFd` holding the given raw file descriptor.
+ ///
+ /// # Safety
+ ///
+ /// The resource pointed to by `fd` must remain open for the duration of
+ /// the returned `BorrowedFd`, and it must not have the value `-1`.
+ #[inline]
+ #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+ pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
+ assert!(fd != u32::MAX as RawFd);
+ // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
+ #[allow(unused_unsafe)]
+ unsafe {
+ Self {
+ fd,
+ _phantom: PhantomData,
+ }
+ }
+ }
+}
+
+impl OwnedFd {
+ /// Creates a new `OwnedFd` instance that shares the same underlying file handle
+ /// as the existing `OwnedFd` instance.
+ #[cfg(not(target_arch = "wasm32"))]
+ pub fn try_clone(&self) -> crate::io::Result<Self> {
+ // We want to atomically duplicate this file descriptor and set the
+ // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
+ // is a POSIX flag that was added to Linux in 2.6.24.
+ #[cfg(not(target_os = "espidf"))]
+ let fd = crate::fs::fcntl_dupfd_cloexec(self, 0)?;
+
+ // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics
+ // will never be supported, as this is a bare metal framework with
+ // no capabilities for multi-process execution. While F_DUPFD is also
+ // not supported yet, it might be (currently it returns ENOSYS).
+ #[cfg(target_os = "espidf")]
+ let fd = crate::fs::fcntl_dupfd(self)?;
+
+ Ok(fd.into())
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ pub fn try_clone(&self) -> crate::io::Result<Self> {
+ Err(crate::io::const_io_error!(
+ crate::io::ErrorKind::Unsupported,
+ "operation not supported on WASI yet",
+ ))
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl AsRawFd for BorrowedFd<'_> {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ self.fd
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl AsRawFd for OwnedFd {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ self.fd
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl IntoRawFd for OwnedFd {
+ #[inline]
+ fn into_raw_fd(self) -> RawFd {
+ let fd = self.fd;
+ forget(self);
+ fd
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl FromRawFd for OwnedFd {
+ /// Constructs a new instance of `Self` from the given raw file descriptor.
+ ///
+ /// # Safety
+ ///
+ /// The resource pointed to by `fd` must be open and suitable for assuming
+ /// ownership. The resource must not require any cleanup other than `close`.
+ #[inline]
+ unsafe fn from_raw_fd(fd: RawFd) -> Self {
+ assert_ne!(fd, u32::MAX as RawFd);
+ // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
+ #[allow(unused_unsafe)]
+ unsafe {
+ Self { fd }
+ }
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl Drop for OwnedFd {
+ #[inline]
+ fn drop(&mut self) {
+ unsafe {
+ // Errors are ignored when closing a file descriptor. The reason
+ // for this is that if an error occurs we don't actually know if
+ // the file descriptor was closed or not, and if we retried (for
+ // something like EINTR), we might close another valid file
+ // descriptor opened after we closed ours.
+ let _ = close(self.fd as _);
+ }
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl fmt::Debug for BorrowedFd<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("BorrowedFd").field("fd", &self.fd).finish()
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl fmt::Debug for OwnedFd {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("OwnedFd").field("fd", &self.fd).finish()
+ }
+}
+
+/// A trait to borrow the file descriptor from an underlying object.
+///
+/// This is only available on unix platforms and must be imported in order to
+/// call the method. Windows platforms have a corresponding `AsHandle` and
+/// `AsSocket` set of traits.
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+pub trait AsFd {
+ /// Borrows the file descriptor.
+ ///
+ /// # Example
+ ///
+ /// ```rust,no_run
+ /// # #![feature(io_safety)]
+ /// use std::fs::File;
+ /// # use std::io;
+ /// # #[cfg(target_os = "wasi")]
+ /// # use std::os::wasi::io::{AsFd, BorrowedFd};
+ /// # #[cfg(unix)]
+ /// # use std::os::unix::io::{AsFd, BorrowedFd};
+ ///
+ /// let mut f = File::open("foo.txt")?;
+ /// # #[cfg(any(unix, target_os = "wasi"))]
+ /// let borrowed_fd: BorrowedFd<'_> = f.as_fd();
+ /// # Ok::<(), io::Error>(())
+ /// ```
+ #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+ fn as_fd(&self) -> BorrowedFd<'_>;
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl<T: AsFd> AsFd for &T {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ T::as_fd(self)
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl<T: AsFd> AsFd for &mut T {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ T::as_fd(self)
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl AsFd for BorrowedFd<'_> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ *self
+ }
+}
+
+#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))]
+impl AsFd for OwnedFd {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ // Safety: `OwnedFd` and `BorrowedFd` have the same validity
+ // invariants, and the `BorrowedFd` is bounded by the lifetime
+ // of `&self`.
+ unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
+ }
+}
diff --git a/vendor/rustix/src/io/fd/raw.rs b/vendor/rustix/src/io/fd/raw.rs
new file mode 100644
index 000000000..44322d9fe
--- /dev/null
+++ b/vendor/rustix/src/io/fd/raw.rs
@@ -0,0 +1,159 @@
+//! The following is derived from Rust's
+//! library/std/src/os/fd/raw.rs at revision
+//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9.
+//!
+//! Raw Unix-like file descriptors.
+
+#![cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+#![allow(unsafe_code)]
+
+use crate::imp::c;
+
+/// Raw file descriptors.
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub type RawFd = c::c_int;
+
+/// A trait to extract the raw file descriptor from an underlying object.
+///
+/// This is only available on unix and WASI platforms and must be imported in
+/// order to call the method. Windows platforms have a corresponding
+/// `AsRawHandle` and `AsRawSocket` set of traits.
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub trait AsRawFd {
+ /// Extracts the raw file descriptor.
+ ///
+ /// This function is typically used to **borrow** an owned file descriptor.
+ /// When used in this way, this method does **not** pass ownership of the
+ /// raw file descriptor to the caller, and the file descriptor is only
+ /// guaranteed to be valid while the original object has not yet been
+ /// destroyed.
+ ///
+ /// However, borrowing is not strictly required. See [`AsFd::as_fd`]
+ /// for an API which strictly borrows a file descriptor.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// # use std::io;
+ /// #[cfg(unix)]
+ /// use std::os::unix::io::{AsRawFd, RawFd};
+ /// #[cfg(target_os = "wasi")]
+ /// use std::os::wasi::io::{AsRawFd, RawFd};
+ ///
+ /// let mut f = File::open("foo.txt")?;
+ /// // `raw_fd` is only valid as long as `f` exists.
+ /// #[cfg(any(unix, target_os = "wasi"))]
+ /// let raw_fd: RawFd = f.as_raw_fd();
+ /// # Ok::<(), io::Error>(())
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ fn as_raw_fd(&self) -> RawFd;
+}
+
+/// A trait to express the ability to construct an object from a raw file
+/// descriptor.
+#[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))]
+pub trait FromRawFd {
+ /// Constructs a new instance of `Self` from the given raw file
+ /// descriptor.
+ ///
+ /// This function is typically used to **consume ownership** of the
+ /// specified file descriptor. When used in this way, the returned object
+ /// will take responsibility for closing it when the object goes out of
+ /// scope.
+ ///
+ /// However, consuming ownership is not strictly required. Use a
+ /// [`From<OwnedFd>::from`] implementation for an API which strictly
+ /// consumes ownership.
+ ///
+ /// # Safety
+ ///
+ /// The `fd` passed in must be a valid an open file descriptor.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// # use std::io;
+ /// #[cfg(unix)]
+ /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
+ /// #[cfg(target_os = "wasi")]
+ /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd};
+ ///
+ /// let f = File::open("foo.txt")?;
+ /// # #[cfg(any(unix, target_os = "wasi"))]
+ /// let raw_fd: RawFd = f.into_raw_fd();
+ /// // SAFETY: no other functions should call `from_raw_fd`, so there
+ /// // is only one owner for the file descriptor.
+ /// # #[cfg(any(unix, target_os = "wasi"))]
+ /// let f = unsafe { File::from_raw_fd(raw_fd) };
+ /// # Ok::<(), io::Error>(())
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))]
+ unsafe fn from_raw_fd(fd: RawFd) -> Self;
+}
+
+/// A trait to express the ability to consume an object and acquire ownership of
+/// its raw file descriptor.
+#[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))]
+pub trait IntoRawFd {
+ /// Consumes this object, returning the raw underlying file descriptor.
+ ///
+ /// This function is typically used to **transfer ownership** of the underlying
+ /// file descriptor to the caller. When used in this way, callers are then the unique
+ /// owners of the file descriptor and must close it once it's no longer needed.
+ ///
+ /// However, transferring ownership is not strictly required. Use a
+ /// [`Into<OwnedFd>::into`] implementation for an API which strictly
+ /// transfers ownership.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// # use std::io;
+ /// #[cfg(unix)]
+ /// use std::os::unix::io::{IntoRawFd, RawFd};
+ /// #[cfg(target_os = "wasi")]
+ /// use std::os::wasi::io::{IntoRawFd, RawFd};
+ ///
+ /// let f = File::open("foo.txt")?;
+ /// #[cfg(any(unix, target_os = "wasi"))]
+ /// let raw_fd: RawFd = f.into_raw_fd();
+ /// # Ok::<(), io::Error>(())
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))]
+ fn into_raw_fd(self) -> RawFd;
+}
+
+#[cfg_attr(
+ staged_api,
+ stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")
+)]
+impl AsRawFd for RawFd {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ *self
+ }
+}
+#[cfg_attr(
+ staged_api,
+ stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")
+)]
+impl IntoRawFd for RawFd {
+ #[inline]
+ fn into_raw_fd(self) -> RawFd {
+ self
+ }
+}
+#[cfg_attr(
+ staged_api,
+ stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")
+)]
+impl FromRawFd for RawFd {
+ #[inline]
+ unsafe fn from_raw_fd(fd: RawFd) -> RawFd {
+ fd
+ }
+}
diff --git a/vendor/rustix/src/io/ioctl.rs b/vendor/rustix/src/io/ioctl.rs
new file mode 100644
index 000000000..be47e7958
--- /dev/null
+++ b/vendor/rustix/src/io/ioctl.rs
@@ -0,0 +1,99 @@
+//! The Unix `ioctl` function is effectively lots of different functions
+//! hidden behind a single dynamic dispatch interface. In order to provide
+//! a type-safe API, rustix makes them all separate functions so that they
+//! can have dedicated static type signatures.
+
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+/// `ioctl(fd, TIOCEXCL)`—Enables exclusive mode on a terminal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+#[inline]
+#[doc(alias = "TIOCEXCL")]
+pub fn ioctl_tiocexcl<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::io::syscalls::ioctl_tiocexcl(fd.as_fd())
+}
+
+/// `ioctl(fd, TIOCNXCL)`—Disables exclusive mode on a terminal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
+#[inline]
+#[doc(alias = "TIOCNXCL")]
+pub fn ioctl_tiocnxcl<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::io::syscalls::ioctl_tiocnxcl(fd.as_fd())
+}
+
+/// `ioctl(fd, FIOCLEX)`—Set the close-on-exec flag.
+///
+/// Also known as `fcntl(fd, F_SETFD, FD_CLOEXEC)`.
+///
+/// # References
+/// - [Linux]
+/// - [Winsock2]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ioctlsocket
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[inline]
+#[doc(alias = "FIOCLEX")]
+#[doc(alias = "FD_CLOEXEC")]
+pub fn ioctl_fioclex<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::io::syscalls::ioctl_fioclex(fd.as_fd())
+}
+
+/// `ioctl(fd, FIONBIO, &value)`—Enables or disables non-blocking mode.
+///
+/// # References
+/// - [Linux]
+/// - [Winsock2]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes
+#[inline]
+#[doc(alias = "FIONBIO")]
+pub fn ioctl_fionbio<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> {
+ imp::io::syscalls::ioctl_fionbio(fd.as_fd(), value)
+}
+
+/// `ioctl(fd, FIONREAD)`—Returns the number of bytes ready to be read.
+///
+/// The result of this function gets silently coerced into a C `int`
+/// by the OS, so it may contain a wrapped value.
+///
+/// # References
+/// - [Linux]
+/// - [Winsock2]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_tty.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes
+#[cfg(not(target_os = "redox"))]
+#[inline]
+#[doc(alias = "FIONREAD")]
+pub fn ioctl_fionread<Fd: AsFd>(fd: Fd) -> io::Result<u64> {
+ imp::io::syscalls::ioctl_fionread(fd.as_fd())
+}
+
+/// `ioctl(fd, BLKSSZGET)`—Returns the logical block size of a block device.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[doc(alias = "BLKSSZGET")]
+pub fn ioctl_blksszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
+ imp::io::syscalls::ioctl_blksszget(fd.as_fd())
+}
+
+/// `ioctl(fd, BLKPBSZGET)`—Returns the physical block size of a block device.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[doc(alias = "BLKPBSZGET")]
+pub fn ioctl_blkpbszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
+ imp::io::syscalls::ioctl_blkpbszget(fd.as_fd())
+}
diff --git a/vendor/rustix/src/io/is_read_write.rs b/vendor/rustix/src/io/is_read_write.rs
new file mode 100644
index 000000000..c6f189090
--- /dev/null
+++ b/vendor/rustix/src/io/is_read_write.rs
@@ -0,0 +1,16 @@
+//! The [`is_read_write`] function.
+
+use crate::{imp, io};
+use imp::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]
+pub fn is_read_write<Fd: AsFd>(fd: Fd) -> io::Result<(bool, bool)> {
+ imp::io::syscalls::is_read_write(fd.as_fd())
+}
diff --git a/vendor/rustix/src/io/mod.rs b/vendor/rustix/src/io/mod.rs
new file mode 100644
index 000000000..5cd5e2ec9
--- /dev/null
+++ b/vendor/rustix/src/io/mod.rs
@@ -0,0 +1,74 @@
+//! I/O operations.
+
+mod close;
+#[cfg(not(windows))]
+mod dup;
+mod errno;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod eventfd;
+#[cfg(not(feature = "std"))]
+pub(crate) mod fd;
+mod ioctl;
+#[cfg(not(any(windows, target_os = "redox")))]
+#[cfg(feature = "net")]
+mod is_read_write;
+mod owned_fd;
+#[cfg(not(any(windows, target_os = "wasi")))]
+mod pipe;
+mod poll;
+#[cfg(all(feature = "procfs", any(target_os = "android", target_os = "linux")))]
+mod procfs;
+#[cfg(not(windows))]
+mod read_write;
+#[cfg(not(feature = "std"))]
+mod seek_from;
+#[cfg(not(windows))]
+mod stdio;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use crate::imp::io::epoll;
+pub use close::close;
+#[cfg(not(any(windows, target_os = "wasi")))]
+pub use dup::{dup, dup2, dup3, DupFlags};
+pub use errno::{retry_on_intr, Errno, Result};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use eventfd::{eventfd, EventfdFlags};
+#[cfg(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 = "redox", target_os = "wasi")))]
+pub use ioctl::{ioctl_tiocexcl, ioctl_tiocnxcl};
+#[cfg(not(any(windows, target_os = "redox")))]
+#[cfg(feature = "net")]
+pub use is_read_write::is_read_write;
+pub use owned_fd::OwnedFd;
+#[cfg(not(any(windows, target_os = "wasi")))]
+pub use pipe::pipe;
+#[cfg(not(any(
+ windows,
+ target_os = "illumos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub use pipe::PIPE_BUF;
+#[cfg(not(any(windows, target_os = "ios", target_os = "macos", target_os = "wasi")))]
+pub use pipe::{pipe_with, PipeFlags};
+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};
+#[cfg(not(windows))]
+pub use read_write::{pread, pwrite, read, readv, write, writev, IoSlice, IoSliceMut};
+#[cfg(not(any(windows, target_os = "redox")))]
+pub use read_write::{preadv, pwritev};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use read_write::{preadv2, pwritev2, ReadWriteFlags};
+#[cfg(not(feature = "std"))]
+pub use seek_from::SeekFrom;
+#[cfg(feature = "std")]
+pub use std::io::SeekFrom;
+#[cfg(not(windows))]
+pub use stdio::{stderr, stdin, stdout, take_stderr, take_stdin, take_stdout};
diff --git a/vendor/rustix/src/io/owned_fd.rs b/vendor/rustix/src/io/owned_fd.rs
new file mode 100644
index 000000000..63c6145b0
--- /dev/null
+++ b/vendor/rustix/src/io/owned_fd.rs
@@ -0,0 +1,272 @@
+//! A wrapper around [`io_lifetimes::OwnedFd`].
+//!
+//! rustix needs to wrap io-lifetimes' `OwnedFd` type so that it can call its
+//! own [`close`] function when the `OwnedFd` is dropped.
+//!
+//! [`close`]: crate::io::close
+//!
+//! # Safety
+//!
+//! We wrap an `OwnedFd` in a `ManuallyDrop` so that we can extract the
+//! file descriptor and close it ourselves.
+#![allow(unsafe_code)]
+
+use crate::imp::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
+#[cfg(all(not(io_lifetimes_use_std), feature = "std"))]
+use crate::imp::fd::{FromFd, IntoFd};
+use crate::io::close;
+use core::fmt;
+use core::mem::{forget, ManuallyDrop};
+
+/// A wrapper around [`io_lifetimes::OwnedFd`] which closes the file descriptor
+/// using rustix's own [`close`] rather than libc's `close`.
+///
+/// [`close`]: crate::io::close
+#[repr(transparent)]
+pub struct OwnedFd {
+ inner: ManuallyDrop<crate::imp::fd::OwnedFd>,
+}
+
+impl OwnedFd {
+ /// Creates a new `OwnedFd` instance that shares the same underlying file
+ /// handle as the existing `OwnedFd` instance.
+ #[cfg(all(unix, not(target_os = "wasi")))]
+ pub fn try_clone(&self) -> crate::io::Result<Self> {
+ // We want to atomically duplicate this file descriptor and set the
+ // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
+ // is a POSIX flag that was added to Linux in 2.6.24.
+ #[cfg(not(target_os = "espidf"))]
+ let fd = crate::fs::fcntl_dupfd_cloexec(self, 0)?;
+
+ // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics
+ // will never be supported, as this is a bare metal framework with
+ // no capabilities for multi-process execution. While F_DUPFD is also
+ // not supported yet, it might be (currently it returns ENOSYS).
+ #[cfg(target_os = "espidf")]
+ let fd = crate::fs::fcntl_dupfd(self)?;
+
+ Ok(fd)
+ }
+
+ /// Creates a new `OwnedFd` instance that shares the same underlying file
+ /// handle as the existing `OwnedFd` instance.
+ #[cfg(target_os = "wasi")]
+ pub fn try_clone(&self) -> std::io::Result<Self> {
+ Err(std::io::Error::new(
+ std::io::ErrorKind::Unsupported,
+ "operation not supported on WASI yet",
+ ))
+ }
+
+ /// Creates a new `OwnedFd` instance that shares the same underlying file
+ /// handle as the existing `OwnedFd` instance.
+ #[cfg(target_os = "windows")]
+ pub fn try_clone(&self) -> std::io::Result<Self> {
+ use windows_sys::Win32::Networking::WinSock::{
+ WSADuplicateSocketW, WSAGetLastError, WSASocketW, INVALID_SOCKET, SOCKET_ERROR,
+ WSAEINVAL, WSAEPROTOTYPE, WSAPROTOCOL_INFOW, WSA_FLAG_NO_HANDLE_INHERIT,
+ WSA_FLAG_OVERLAPPED,
+ };
+ use windows_sys::Win32::System::Threading::GetCurrentProcessId;
+
+ let mut info = unsafe { std::mem::zeroed::<WSAPROTOCOL_INFOW>() };
+ let result =
+ unsafe { WSADuplicateSocketW(self.as_raw_fd() as _, GetCurrentProcessId(), &mut info) };
+ match result {
+ SOCKET_ERROR => return Err(std::io::Error::last_os_error()),
+ 0 => (),
+ _ => panic!(),
+ }
+ let socket = unsafe {
+ WSASocketW(
+ info.iAddressFamily,
+ info.iSocketType,
+ info.iProtocol,
+ &mut info,
+ 0,
+ WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT,
+ )
+ };
+
+ if socket != INVALID_SOCKET {
+ unsafe { Ok(Self::from_raw_fd(socket as _)) }
+ } else {
+ let error = unsafe { WSAGetLastError() };
+
+ if error != WSAEPROTOTYPE && error != WSAEINVAL {
+ return Err(std::io::Error::from_raw_os_error(error));
+ }
+
+ let socket = unsafe {
+ WSASocketW(
+ info.iAddressFamily,
+ info.iSocketType,
+ info.iProtocol,
+ &mut info,
+ 0,
+ WSA_FLAG_OVERLAPPED,
+ )
+ };
+
+ if socket == INVALID_SOCKET {
+ return Err(std::io::Error::last_os_error());
+ }
+
+ unsafe {
+ let socket = Self::from_raw_fd(socket as _);
+ socket.set_no_inherit()?;
+ Ok(socket)
+ }
+ }
+ }
+
+ #[cfg(windows)]
+ #[cfg(not(target_vendor = "uwp"))]
+ fn set_no_inherit(&self) -> std::io::Result<()> {
+ use windows_sys::Win32::Foundation::{SetHandleInformation, HANDLE, HANDLE_FLAG_INHERIT};
+ match unsafe { SetHandleInformation(self.as_raw_fd() as HANDLE, HANDLE_FLAG_INHERIT, 0) } {
+ 0 => return Err(std::io::Error::last_os_error()),
+ _ => Ok(()),
+ }
+ }
+
+ #[cfg(windows)]
+ #[cfg(target_vendor = "uwp")]
+ fn set_no_inherit(&self) -> std::io::Result<()> {
+ Err(std::io::Error::new(
+ std::io::ErrorKind::Unsupported,
+ "Unavailable on UWP",
+ ))
+ }
+}
+
+#[cfg(not(windows))]
+impl AsFd for OwnedFd {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.inner.as_fd()
+ }
+}
+
+#[cfg(windows)]
+impl io_lifetimes::AsSocket for OwnedFd {
+ #[inline]
+ fn as_socket(&self) -> BorrowedFd<'_> {
+ self.inner.as_socket()
+ }
+}
+
+#[cfg(any(io_lifetimes_use_std, not(feature = "std")))]
+impl From<OwnedFd> for crate::imp::fd::OwnedFd {
+ #[inline]
+ fn from(owned_fd: OwnedFd) -> Self {
+ let raw_fd = owned_fd.inner.as_fd().as_raw_fd();
+ forget(owned_fd);
+
+ // Safety: We use `as_fd().as_raw_fd()` to extract the raw file
+ // descriptor from `self.inner`, and then `forget` `self` so
+ // that they remain valid until the new `OwnedFd` acquires them.
+ unsafe { crate::imp::fd::OwnedFd::from_raw_fd(raw_fd) }
+ }
+}
+
+#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))]
+impl IntoFd for OwnedFd {
+ #[inline]
+ fn into_fd(self) -> crate::imp::fd::OwnedFd {
+ let raw_fd = self.inner.as_fd().as_raw_fd();
+ forget(self);
+
+ // Safety: We use `as_fd().as_raw_fd()` to extract the raw file
+ // descriptor from `self.inner`, and then `forget` `self` so
+ // that they remain valid until the new `OwnedFd` acquires them.
+ unsafe { crate::imp::fd::OwnedFd::from_raw_fd(raw_fd) }
+ }
+}
+
+#[cfg(any(io_lifetimes_use_std, not(feature = "std")))]
+impl From<crate::imp::fd::OwnedFd> for OwnedFd {
+ #[inline]
+ fn from(owned_fd: crate::imp::fd::OwnedFd) -> Self {
+ Self {
+ inner: ManuallyDrop::new(owned_fd),
+ }
+ }
+}
+
+#[cfg(all(not(io_lifetimes_use_std), feature = "std"))]
+impl FromFd for OwnedFd {
+ #[inline]
+ fn from_fd(owned_fd: crate::imp::fd::OwnedFd) -> Self {
+ Self {
+ inner: ManuallyDrop::new(owned_fd),
+ }
+ }
+}
+
+#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))]
+impl From<crate::imp::fd::OwnedFd> for OwnedFd {
+ #[inline]
+ fn from(fd: crate::imp::fd::OwnedFd) -> Self {
+ Self {
+ inner: ManuallyDrop::new(fd),
+ }
+ }
+}
+
+#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))]
+impl From<OwnedFd> for crate::imp::fd::OwnedFd {
+ #[inline]
+ fn from(fd: OwnedFd) -> Self {
+ let raw_fd = fd.inner.as_fd().as_raw_fd();
+ forget(fd);
+
+ // Safety: We use `as_fd().as_raw_fd()` to extract the raw file
+ // descriptor from `self.inner`, and then `forget` `self` so
+ // that they remain valid until the new `OwnedFd` acquires them.
+ unsafe { Self::from_raw_fd(raw_fd) }
+ }
+}
+
+impl AsRawFd for OwnedFd {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ self.inner.as_raw_fd()
+ }
+}
+
+impl IntoRawFd for OwnedFd {
+ #[inline]
+ fn into_raw_fd(self) -> RawFd {
+ let raw_fd = self.inner.as_fd().as_raw_fd();
+ forget(self);
+ raw_fd
+ }
+}
+
+impl FromRawFd for OwnedFd {
+ #[inline]
+ unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
+ Self {
+ inner: ManuallyDrop::new(crate::imp::fd::OwnedFd::from_raw_fd(raw_fd)),
+ }
+ }
+}
+
+impl Drop for OwnedFd {
+ #[inline]
+ fn drop(&mut self) {
+ // Safety: We use `as_fd().as_raw_fd()` to extract the raw file
+ // descriptor from `self.inner`. `self.inner` is wrapped with
+ // `ManuallyDrop` so dropping it doesn't invalid them.
+ unsafe {
+ close(self.as_fd().as_raw_fd());
+ }
+ }
+}
+
+impl fmt::Debug for OwnedFd {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.inner.fmt(f)
+ }
+}
diff --git a/vendor/rustix/src/io/pipe.rs b/vendor/rustix/src/io/pipe.rs
new file mode 100644
index 000000000..2878d10b1
--- /dev/null
+++ b/vendor/rustix/src/io/pipe.rs
@@ -0,0 +1,53 @@
+use crate::imp;
+use crate::io::{self, OwnedFd};
+
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::io::types::PipeFlags;
+
+/// `PIPE_BUF`—The maximum length at which writes to a pipe are atomic.
+///
+/// # References
+/// - [Linux]
+/// - [POSIX]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man7/pipe.7.html
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
+#[cfg(not(any(
+ windows,
+ target_os = "illumos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub const PIPE_BUF: usize = imp::io::types::PIPE_BUF;
+
+/// `pipe()`—Creates a pipe.
+///
+/// This function creates a pipe and returns two file descriptors, for the
+/// reading and writing ends of the pipe, respectively.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/pipe.2.html
+#[inline]
+pub fn pipe() -> io::Result<(OwnedFd, OwnedFd)> {
+ imp::io::syscalls::pipe()
+}
+
+/// `pipe2(flags)`—Creates a pipe, with flags.
+///
+/// This function creates a pipe and returns two file descriptors, for the
+/// reading and writing ends of the pipe, respectively.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/pipe2.2.html
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+#[inline]
+#[doc(alias = "pipe2")]
+pub fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> {
+ imp::io::syscalls::pipe_with(flags)
+}
diff --git a/vendor/rustix/src/io/poll.rs b/vendor/rustix/src/io/poll.rs
new file mode 100644
index 000000000..efa25045c
--- /dev/null
+++ b/vendor/rustix/src/io/poll.rs
@@ -0,0 +1,20 @@
+use crate::{imp, io};
+
+pub use imp::io::poll_fd::{PollFd, PollFlags};
+
+/// `poll(self.fds, timeout)`
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/poll.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/poll.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsapoll
+#[inline]
+pub fn poll(fds: &mut [PollFd<'_>], timeout: i32) -> io::Result<usize> {
+ imp::io::syscalls::poll(fds, timeout)
+}
diff --git a/vendor/rustix/src/io/procfs.rs b/vendor/rustix/src/io/procfs.rs
new file mode 100644
index 000000000..a947a4e06
--- /dev/null
+++ b/vendor/rustix/src/io/procfs.rs
@@ -0,0 +1,482 @@
+//! Utilities for working with `/proc`, where Linux's `procfs` is typically
+//! mounted. `/proc` serves as an adjunct to Linux's main syscall surface area,
+//! providing additional features with an awkward interface.
+//!
+//! This module does a considerable amount of work to determine whether `/proc`
+//! is mounted, with actual `procfs`, and without any additional mount points
+//! on top of the paths we open.
+//!
+//! Why all the effort to detect bind mount points? People are doing all kinds
+//! of things with Linux containers these days, with many different privilege
+//! schemes, and we want to avoid making any unnecessary assumptions. Rustix
+//! and its users will sometimes use procfs *implicitly* (when Linux gives them
+//! no better options), in ways that aren't obvious from their public APIs.
+//! These filesystem accesses might not be visible to someone auditing the main
+//! code of an application for places which may be influenced by the filesystem
+//! namespace. So with the checking here, they may fail, but they won't be able
+//! to succeed with bogus results.
+
+use crate::fd::{AsFd, BorrowedFd};
+use crate::ffi::CStr;
+use crate::fs::{
+ cwd, fstat, fstatfs, major, openat, renameat, Dir, FileType, Mode, OFlags, Stat,
+ PROC_SUPER_MAGIC,
+};
+use crate::io::{self, OwnedFd};
+use crate::path::DecInt;
+use crate::process::{getgid, getpid, getuid, Gid, RawGid, RawUid, Uid};
+#[cfg(feature = "rustc-dep-of-std")]
+use core::lazy::OnceCell;
+#[cfg(not(feature = "rustc-dep-of-std"))]
+use once_cell::sync::OnceCell;
+
+/// Linux's procfs always uses inode 1 for its root directory.
+const PROC_ROOT_INO: u64 = 1;
+
+// Identify an entry within "/proc", to determine which anomalies to check for.
+#[derive(Copy, Clone, Debug)]
+enum Kind {
+ Proc,
+ Pid,
+ Fd,
+ File,
+}
+
+/// Check a subdirectory of "/proc" for anomalies.
+fn check_proc_entry(
+ kind: Kind,
+ entry: BorrowedFd<'_>,
+ proc_stat: Option<&Stat>,
+ uid: RawUid,
+ gid: RawGid,
+) -> io::Result<Stat> {
+ let entry_stat = fstat(entry)?;
+ check_proc_entry_with_stat(kind, entry, entry_stat, proc_stat, uid, gid)
+}
+
+/// Check a subdirectory of "/proc" for anomalies, using the provided `Stat`.
+fn check_proc_entry_with_stat(
+ kind: Kind,
+ entry: BorrowedFd<'_>,
+ entry_stat: Stat,
+ proc_stat: Option<&Stat>,
+ uid: RawUid,
+ gid: RawGid,
+) -> io::Result<Stat> {
+ // Check the filesystem magic.
+ check_procfs(entry)?;
+
+ match kind {
+ Kind::Proc => check_proc_root(entry, &entry_stat)?,
+ Kind::Pid | Kind::Fd => check_proc_subdir(entry, &entry_stat, proc_stat)?,
+ Kind::File => check_proc_file(&entry_stat, proc_stat)?,
+ }
+
+ // Check the ownership of the directory. We can't do that for the toplevel
+ // "/proc" though, because in e.g. a user namespace scenario, root outside
+ // the container may be mapped to another uid like `nobody`.
+ if !matches!(kind, Kind::Proc) && (entry_stat.st_uid, entry_stat.st_gid) != (uid, gid) {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ // "/proc" directories are typically mounted r-xr-xr-x.
+ // "/proc/self/fd" is r-x------. Allow them to have fewer permissions, but
+ // not more.
+ let expected_mode = if let Kind::Fd = kind { 0o500 } else { 0o555 };
+ if entry_stat.st_mode & 0o777 & !expected_mode != 0 {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ match kind {
+ Kind::Fd => {
+ // Check that the "/proc/self/fd" directory doesn't have any extraneous
+ // links into it (which might include unexpected subdirectories).
+ if entry_stat.st_nlink != 2 {
+ return Err(io::Errno::NOTSUP);
+ }
+ }
+ Kind::Pid | Kind::Proc => {
+ // Check that the "/proc" and "/proc/self" directories aren't empty.
+ if entry_stat.st_nlink <= 2 {
+ return Err(io::Errno::NOTSUP);
+ }
+ }
+ Kind::File => {
+ // Check that files in procfs don't have extraneous hard links to
+ // them (which might indicate hard links to other things).
+ if entry_stat.st_nlink != 1 {
+ return Err(io::Errno::NOTSUP);
+ }
+ }
+ }
+
+ Ok(entry_stat)
+}
+
+fn check_proc_root(entry: BorrowedFd<'_>, stat: &Stat) -> io::Result<()> {
+ // We use `O_DIRECTORY` for proc directories, so open should fail if we
+ // don't get a directory when we expect one.
+ assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory);
+
+ // Check the root inode number.
+ if stat.st_ino != PROC_ROOT_INO {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ // Proc is a non-device filesystem, so check for major number 0.
+ // <https://www.kernel.org/doc/Documentation/admin-guide/devices.txt>
+ if major(stat.st_dev) != 0 {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ // Check that "/proc" is a mountpoint.
+ if !is_mountpoint(entry) {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ Ok(())
+}
+
+fn check_proc_subdir(
+ entry: BorrowedFd<'_>,
+ stat: &Stat,
+ proc_stat: Option<&Stat>,
+) -> io::Result<()> {
+ // We use `O_DIRECTORY` for proc directories, so open should fail if we
+ // don't get a directory when we expect one.
+ assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory);
+
+ check_proc_nonroot(stat, proc_stat)?;
+
+ // Check that subdirectories of "/proc" are not mount points.
+ if is_mountpoint(entry) {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ Ok(())
+}
+
+fn check_proc_file(stat: &Stat, proc_stat: Option<&Stat>) -> io::Result<()> {
+ // Check that we have a regular file.
+ if FileType::from_raw_mode(stat.st_mode) != FileType::RegularFile {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ check_proc_nonroot(stat, proc_stat)?;
+
+ Ok(())
+}
+
+fn check_proc_nonroot(stat: &Stat, proc_stat: Option<&Stat>) -> io::Result<()> {
+ // Check that we haven't been linked back to the root of "/proc".
+ if stat.st_ino == PROC_ROOT_INO {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ // Check that we're still in procfs.
+ if stat.st_dev != proc_stat.unwrap().st_dev {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ Ok(())
+}
+
+/// Check that `file` is opened on a `procfs` filesystem.
+fn check_procfs(file: BorrowedFd<'_>) -> io::Result<()> {
+ let statfs = fstatfs(file)?;
+ let f_type = statfs.f_type;
+ if f_type != PROC_SUPER_MAGIC {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ Ok(())
+}
+
+/// Check whether the given directory handle is a mount point. We use a
+/// `renameat` call that would otherwise fail, but which fails with `EXDEV`
+/// first if it would cross a mount point.
+fn is_mountpoint(file: BorrowedFd<'_>) -> bool {
+ let err = renameat(file, cstr!("../."), file, cstr!(".")).unwrap_err();
+ match err {
+ io::Errno::XDEV => true, // the rename failed due to crossing a mount point
+ io::Errno::BUSY => false, // the rename failed normally
+ _ => panic!("Unexpected error from `renameat`: {:?}", err),
+ }
+}
+
+/// Open a directory in `/proc`, mapping all errors to `io::Errno::NOTSUP`.
+fn proc_opendirat<P: crate::path::Arg, Fd: AsFd>(dirfd: Fd, path: P) -> io::Result<OwnedFd> {
+ // We could add `PATH`|`NOATIME` here but Linux 2.6.32 doesn't support it.
+ let oflags = OFlags::NOFOLLOW | OFlags::DIRECTORY | OFlags::CLOEXEC | OFlags::NOCTTY;
+ openat(dirfd, path, oflags, Mode::empty()).map_err(|_err| io::Errno::NOTSUP)
+}
+
+/// Returns a handle to Linux's `/proc` directory.
+///
+/// This ensures that `/proc` is procfs, that nothing is mounted on top of it,
+/// and that it looks normal. It also returns the `Stat` of `/proc`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+fn proc() -> io::Result<(BorrowedFd<'static>, &'static Stat)> {
+ static PROC: StaticFd = StaticFd::new();
+
+ // `OnceBox` is "racey" in that the initialization function may run
+ // multiple times. We're ok with that, since the initialization function
+ // has no side effects.
+ PROC.get_or_try_init(|| {
+ // Open "/proc".
+ let proc = proc_opendirat(cwd(), cstr!("/proc"))?;
+ let proc_stat = check_proc_entry(
+ Kind::Proc,
+ proc.as_fd(),
+ None,
+ Uid::ROOT.as_raw(),
+ Gid::ROOT.as_raw(),
+ )
+ .map_err(|_err| io::Errno::NOTSUP)?;
+
+ Ok(new_static_fd(proc, proc_stat))
+ })
+ .map(|(fd, stat)| (fd.as_fd(), stat))
+}
+
+/// Returns a handle to Linux's `/proc/self` directory.
+///
+/// This ensures that `/proc/self` is procfs, that nothing is mounted on top of
+/// it, and that it looks normal. It also returns the `Stat` of `/proc/self`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+fn proc_self() -> io::Result<(BorrowedFd<'static>, &'static Stat)> {
+ static PROC_SELF: StaticFd = StaticFd::new();
+
+ // The init function here may run multiple times; see above.
+ PROC_SELF
+ .get_or_try_init(|| {
+ let (proc, proc_stat) = proc()?;
+
+ let (uid, gid, pid) = (getuid(), getgid(), getpid());
+
+ // Open "/proc/self". Use our pid to compute the name rather than literally
+ // using "self", as "self" is a symlink.
+ let proc_self = proc_opendirat(proc, DecInt::new(pid.as_raw_nonzero().get()))?;
+ let proc_self_stat = check_proc_entry(
+ Kind::Pid,
+ proc_self.as_fd(),
+ Some(proc_stat),
+ uid.as_raw(),
+ gid.as_raw(),
+ )
+ .map_err(|_err| io::Errno::NOTSUP)?;
+
+ Ok(new_static_fd(proc_self, proc_self_stat))
+ })
+ .map(|(owned, stat)| (owned.as_fd(), stat))
+}
+
+/// Returns a handle to Linux's `/proc/self/fd` directory.
+///
+/// This ensures that `/proc/self/fd` is `procfs`, that nothing is mounted on
+/// top of it, and that it looks normal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub fn proc_self_fd() -> io::Result<BorrowedFd<'static>> {
+ static PROC_SELF_FD: StaticFd = StaticFd::new();
+
+ // The init function here may run multiple times; see above.
+ PROC_SELF_FD
+ .get_or_try_init(|| {
+ let (_, proc_stat) = proc()?;
+
+ let (proc_self, proc_self_stat) = proc_self()?;
+
+ // Open "/proc/self/fd".
+ let proc_self_fd = proc_opendirat(proc_self, cstr!("fd"))?;
+ let proc_self_fd_stat = check_proc_entry(
+ Kind::Fd,
+ proc_self_fd.as_fd(),
+ Some(proc_stat),
+ proc_self_stat.st_uid,
+ proc_self_stat.st_gid,
+ )
+ .map_err(|_err| io::Errno::NOTSUP)?;
+
+ Ok(new_static_fd(proc_self_fd, proc_self_fd_stat))
+ })
+ .map(|(owned, _stat)| owned.as_fd())
+}
+
+type StaticFd = OnceCell<(OwnedFd, Stat)>;
+
+#[inline]
+fn new_static_fd(fd: OwnedFd, stat: Stat) -> (OwnedFd, Stat) {
+ (fd, stat)
+}
+
+/// Returns a handle to Linux's `/proc/self/fdinfo` directory.
+///
+/// This ensures that `/proc/self/fdinfo` is `procfs`, that nothing is mounted
+/// on top of it, and that it looks normal. It also returns the `Stat` of
+/// `/proc/self/fd`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+fn proc_self_fdinfo() -> io::Result<(BorrowedFd<'static>, &'static Stat)> {
+ static PROC_SELF_FDINFO: OnceCell<(OwnedFd, Stat)> = OnceCell::new();
+
+ PROC_SELF_FDINFO
+ .get_or_try_init(|| {
+ let (_, proc_stat) = proc()?;
+
+ let (proc_self, proc_self_stat) = proc_self()?;
+
+ // Open "/proc/self/fdinfo".
+ let proc_self_fdinfo = proc_opendirat(proc_self, cstr!("fdinfo"))?;
+ let proc_self_fdinfo_stat = check_proc_entry(
+ Kind::Fd,
+ proc_self_fdinfo.as_fd(),
+ Some(proc_stat),
+ proc_self_stat.st_uid,
+ proc_self_stat.st_gid,
+ )
+ .map_err(|_err| io::Errno::NOTSUP)?;
+
+ Ok((proc_self_fdinfo, proc_self_fdinfo_stat))
+ })
+ .map(|(owned, stat)| (owned.as_fd(), stat))
+}
+
+/// Returns a handle to a Linux `/proc/self/fdinfo/<fd>` file.
+///
+/// This ensures that `/proc/self/fdinfo/<fd>` is `procfs`, that nothing is
+/// mounted on top of it, and that it looks normal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+#[inline]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub fn proc_self_fdinfo_fd<Fd: AsFd>(fd: Fd) -> io::Result<OwnedFd> {
+ _proc_self_fdinfo(fd.as_fd())
+}
+
+fn _proc_self_fdinfo(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
+ let (proc_self_fdinfo, proc_self_fdinfo_stat) = proc_self_fdinfo()?;
+ let fd_str = DecInt::from_fd(fd);
+ open_and_check_file(proc_self_fdinfo, proc_self_fdinfo_stat, fd_str.as_c_str())
+}
+
+/// Returns a handle to a Linux `/proc/self/pagemap` file.
+///
+/// This ensures that `/proc/self/pagemap` is `procfs`, that nothing is
+/// mounted on top of it, and that it looks normal.
+///
+/// # References
+/// - [Linux]
+/// - [Linux pagemap]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+/// [Linux pagemap]: https://www.kernel.org/doc/Documentation/vm/pagemap.txt
+#[inline]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub fn proc_self_pagemap() -> io::Result<OwnedFd> {
+ proc_self_file(cstr!("pagemap"))
+}
+
+/// Returns a handle to a Linux `/proc/self/maps` file.
+///
+/// This ensures that `/proc/self/maps` is `procfs`, that nothing is
+/// mounted on top of it, and that it looks normal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html
+#[inline]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+pub fn proc_self_maps() -> io::Result<OwnedFd> {
+ proc_self_file(cstr!("maps"))
+}
+
+/// Open a file under `/proc/self`.
+fn proc_self_file(name: &CStr) -> io::Result<OwnedFd> {
+ let (proc_self, proc_self_stat) = proc_self()?;
+ open_and_check_file(proc_self, proc_self_stat, name)
+}
+
+/// Open a procfs file within in `dir` and check it for bind mounts.
+fn open_and_check_file(dir: BorrowedFd, dir_stat: &Stat, name: &CStr) -> io::Result<OwnedFd> {
+ let (_, proc_stat) = proc()?;
+
+ let oflags =
+ OFlags::RDONLY | OFlags::CLOEXEC | OFlags::NOFOLLOW | OFlags::NOCTTY | OFlags::NOATIME;
+ let file = openat(&dir, name, oflags, Mode::empty()).map_err(|_err| io::Errno::NOTSUP)?;
+ let file_stat = fstat(&file)?;
+
+ // `is_mountpoint` only works on directory mount points, not file mount
+ // points. To detect file mount points, scan the parent directory to see
+ // if we can find a regular file with an inode and name that matches the
+ // file we just opened. If we can't find it, there could be a file bind
+ // mount on top of the file we want.
+ //
+ // As we scan, we also check for ".", to make sure it's the same directory
+ // as our original directory, to detect mount points, since
+ // `Dir::read_from` reopens ".".
+ //
+ // TODO: With Linux 5.8 we might be able to use `statx` and
+ // `STATX_ATTR_MOUNT_ROOT` to detect mountpoints directly instead of doing
+ // this scanning.
+ let dir = Dir::read_from(dir).map_err(|_err| io::Errno::NOTSUP)?;
+
+ // Confirm that we got the same inode.
+ let dot_stat = dir.stat().map_err(|_err| io::Errno::NOTSUP)?;
+ if (dot_stat.st_dev, dot_stat.st_ino) != (dir_stat.st_dev, dir_stat.st_ino) {
+ return Err(io::Errno::NOTSUP);
+ }
+
+ let mut found_file = false;
+ let mut found_dot = false;
+ for entry in dir {
+ let entry = entry.map_err(|_err| io::Errno::NOTSUP)?;
+ if entry.ino() == file_stat.st_ino
+ && entry.file_type() == FileType::RegularFile
+ && entry.file_name() == name
+ {
+ // We found the file. Proceed to check the file handle.
+ let _ = check_proc_entry_with_stat(
+ Kind::File,
+ file.as_fd(),
+ file_stat,
+ Some(proc_stat),
+ dir_stat.st_uid,
+ dir_stat.st_gid,
+ )?;
+
+ found_file = true;
+ } else if entry.ino() == dir_stat.st_ino
+ && entry.file_type() == FileType::Directory
+ && entry.file_name() == cstr!(".")
+ {
+ // We found ".", and it's the right ".".
+ found_dot = true;
+ }
+ }
+
+ if found_file && found_dot {
+ Ok(file)
+ } else {
+ Err(io::Errno::NOTSUP)
+ }
+}
diff --git a/vendor/rustix/src/io/read_write.rs b/vendor/rustix/src/io/read_write.rs
new file mode 100644
index 000000000..abb96e9c1
--- /dev/null
+++ b/vendor/rustix/src/io/read_write.rs
@@ -0,0 +1,170 @@
+//! `read` and `write`, optionally positioned, optionally vectored
+
+use crate::{imp, io};
+use imp::fd::AsFd;
+
+// Declare `IoSlice` and `IoSliceMut`.
+#[cfg(not(windows))]
+#[cfg(not(feature = "std"))]
+pub use imp::io::io_slice::{IoSlice, IoSliceMut};
+#[cfg(not(windows))]
+#[cfg(feature = "std")]
+pub use std::io::{IoSlice, IoSliceMut};
+
+/// `RWF_*` constants for use with [`preadv2`] and [`pwritev2`].
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use imp::io::types::ReadWriteFlags;
+
+/// `read(fd, buf)`—Reads from a stream.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/read.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/read.2.html
+#[inline]
+pub fn read<Fd: AsFd>(fd: Fd, buf: &mut [u8]) -> io::Result<usize> {
+ imp::io::syscalls::read(fd.as_fd(), buf)
+}
+
+/// `write(fd, buf)`—Writes to a stream.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/write.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/write.2.html
+#[inline]
+pub fn write<Fd: AsFd>(fd: Fd, buf: &[u8]) -> io::Result<usize> {
+ imp::io::syscalls::write(fd.as_fd(), buf)
+}
+
+/// `pread(fd, buf, offset)`—Reads from a file at a given position.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/pread.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/pread.2.html
+#[inline]
+pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+ imp::io::syscalls::pread(fd.as_fd(), buf, offset)
+}
+
+/// `pwrite(fd, bufs)`—Writes to a file at a given position.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/pwrite.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/pwrite.2.html
+#[inline]
+pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: u64) -> io::Result<usize> {
+ imp::io::syscalls::pwrite(fd.as_fd(), buf, offset)
+}
+
+/// `readv(fd, bufs)`—Reads from a stream into multiple buffers.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/readv.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/readv.2.html
+#[inline]
+pub fn readv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+ imp::io::syscalls::readv(fd.as_fd(), bufs)
+}
+
+/// `writev(fd, bufs)`—Writes to a stream from multiple buffers.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/writev.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/writev.2.html
+#[inline]
+pub fn writev<Fd: AsFd>(fd: Fd, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+ imp::io::syscalls::writev(fd.as_fd(), bufs)
+}
+
+/// `preadv(fd, bufs, offset)`—Reads from a file at a given position into
+/// multiple buffers.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/preadv.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+pub fn preadv<Fd: AsFd>(fd: Fd, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ imp::io::syscalls::preadv(fd.as_fd(), bufs, offset)
+}
+
+/// `pwritev(fd, bufs, offset)`—Writes to a file at a given position from
+/// multiple buffers.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/pwritev.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+pub fn pwritev<Fd: AsFd>(fd: Fd, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ imp::io::syscalls::pwritev(fd.as_fd(), bufs, offset)
+}
+
+/// `preadv2(fd, bufs, offset, flags)`—Reads data, with several options.
+///
+/// An `offset` of `u64::MAX` means to use and update the current file offset.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/preadv2.2.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub fn preadv2<Fd: AsFd>(
+ fd: Fd,
+ bufs: &mut [IoSliceMut<'_>],
+ offset: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ imp::io::syscalls::preadv2(fd.as_fd(), bufs, offset, flags)
+}
+
+/// `pwritev2(fd, bufs, offset, flags)`—Writes data, with several options.
+///
+/// An `offset` of `u64::MAX` means to use and update the current file offset.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/pwritev2.2.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub fn pwritev2<Fd: AsFd>(
+ fd: Fd,
+ bufs: &[IoSlice<'_>],
+ offset: u64,
+ flags: ReadWriteFlags,
+) -> io::Result<usize> {
+ imp::io::syscalls::pwritev2(fd.as_fd(), bufs, offset, flags)
+}
diff --git a/vendor/rustix/src/io/seek_from.rs b/vendor/rustix/src/io/seek_from.rs
new file mode 100644
index 000000000..265369b6b
--- /dev/null
+++ b/vendor/rustix/src/io/seek_from.rs
@@ -0,0 +1,30 @@
+//! The following is derived from Rust's
+//! library/std/src/io/mod.rs at revision
+//! dca3f1b786efd27be3b325ed1e01e247aa589c3b.
+
+/// Enumeration of possible methods to seek within an I/O object.
+///
+/// It is used by the [`Seek`] trait.
+#[derive(Copy, PartialEq, Eq, Clone, Debug)]
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub enum SeekFrom {
+ /// Sets the offset to the provided number of bytes.
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ Start(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] u64),
+
+ /// Sets the offset to the size of this object plus the specified number of
+ /// bytes.
+ ///
+ /// It is possible to seek beyond the end of an object, but it's an error
+ /// to seek before byte 0.
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ End(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64),
+
+ /// Sets the offset to the current position plus the specified number of
+ /// bytes.
+ ///
+ /// It is possible to seek beyond the end of an object, but it's an error
+ /// to seek before byte 0.
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ Current(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64),
+}
diff --git a/vendor/rustix/src/io/stdio.rs b/vendor/rustix/src/io/stdio.rs
new file mode 100644
index 000000000..f9d03a701
--- /dev/null
+++ b/vendor/rustix/src/io/stdio.rs
@@ -0,0 +1,194 @@
+//! Functions returning the stdio file descriptors.
+//!
+//! # Safety
+//!
+//! These access the file descriptors by absolute index value, and nothing
+//! prevents them from being closed and reused. They should only be used in
+//! `main` or other situations where one is in control of the process'
+//! stdio streams.
+#![allow(unsafe_code)]
+
+use crate::imp;
+use crate::io::OwnedFd;
+use imp::fd::{BorrowedFd, FromRawFd, RawFd};
+
+/// `STDIN_FILENO`—Standard input, borrowed.
+///
+/// # Safety
+///
+/// This function must be called from code which knows how the process'
+/// standard input is being used. Often, this will be the `main` function or
+/// code that knows its relationship with the `main` function.
+///
+/// The stdin file descriptor can be closed, potentially on other threads, in
+/// which case the file descriptor index value could be dynamically reused for
+/// other purposes, potentially on different threads.
+///
+/// # Other hazards
+///
+/// Stdin could be redirected from arbitrary input sources, and unless one
+/// knows how the process' standard input is being used, one could consume
+/// bytes that are expected to be consumed by other parts of the process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
+#[inline]
+pub unsafe fn stdin() -> BorrowedFd<'static> {
+ BorrowedFd::borrow_raw(imp::io::types::STDIN_FILENO as RawFd)
+}
+
+/// `STDIN_FILENO`—Standard input, owned.
+///
+/// This is similar to [`stdin`], however it returns an `OwnedFd` which closes
+/// standard input when it is dropped.
+///
+/// # Safety
+///
+/// This is unsafe for the same reasons as [`stdin`].
+///
+/// # Other hazards
+///
+/// This has the same hazards as [`stdin`].
+///
+/// And, when the `OwnedFd` is dropped, subsequent newly created file
+/// descriptors may unknowingly reuse the stdin file descriptor number, which
+/// may break common assumptions, so it should typically only be dropped at the
+/// end of a program when no more file descriptors will be created.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html
+#[inline]
+pub unsafe fn take_stdin() -> OwnedFd {
+ OwnedFd::from(imp::fd::OwnedFd::from_raw_fd(
+ imp::io::types::STDIN_FILENO as RawFd,
+ ))
+}
+
+/// `STDOUT_FILENO`—Standard output, borrowed.
+///
+/// # Safety
+///
+/// This function must be called from code which knows how the process'
+/// standard output is being used. Often, this will be the `main` function or
+/// code that knows its relationship with the `main` function.
+///
+/// The stdout file descriptor can be closed, potentially on other threads, in
+/// which case the file descriptor index value could be dynamically reused for
+/// other purposes, potentially on different threads.
+///
+/// # Other hazards
+///
+/// Stdout could be redirected to arbitrary output sinks, and unless one
+/// knows how the process' standard output is being used, one could
+/// unexpectedly inject bytes into a stream being written by another part of
+/// the process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
+#[inline]
+pub unsafe fn stdout() -> BorrowedFd<'static> {
+ BorrowedFd::borrow_raw(imp::io::types::STDOUT_FILENO as RawFd)
+}
+
+/// `STDOUT_FILENO`—Standard output, owned.
+///
+/// This is similar to [`stdout`], however it returns an `OwnedFd` which closes
+/// standard output when it is dropped.
+///
+/// # Safety
+///
+/// This is unsafe for the same reasons as [`stdout`].
+///
+/// # Other hazards
+///
+/// This has the same hazards as [`stdout`].
+///
+/// And, when the `OwnedFd` is dropped, subsequent newly created file
+/// descriptors may unknowingly reuse the stdout file descriptor number, which
+/// may break common assumptions, so it should typically only be dropped at the
+/// end of a program when no more file descriptors will be created.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html
+#[inline]
+pub unsafe fn take_stdout() -> OwnedFd {
+ OwnedFd::from(imp::fd::OwnedFd::from_raw_fd(
+ imp::io::types::STDOUT_FILENO as RawFd,
+ ))
+}
+
+/// `STDERR_FILENO`—Standard error, borrowed.
+///
+/// # Safety
+///
+/// This function must be called from code which knows how the process'
+/// standard error is being used. Often, this will be the `main` function or
+/// code that knows its relationship with the `main` function.
+///
+/// The stderr file descriptor can be closed, potentially on other threads, in
+/// which case the file descriptor index value could be dynamically reused for
+/// other purposes, potentially on different threads.
+///
+/// # Other hazards
+///
+/// Stderr could be redirected to arbitrary output sinks, and unless one
+/// knows how the process' standard error is being used, one could unexpectedly
+/// inject bytes into a stream being written by another part of the process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
+#[inline]
+pub unsafe fn stderr() -> BorrowedFd<'static> {
+ BorrowedFd::borrow_raw(imp::io::types::STDERR_FILENO as RawFd)
+}
+
+/// `STDERR_FILENO`—Standard error, owned.
+///
+/// This is similar to [`stdout`], however it returns an `OwnedFd` which closes
+/// standard output when it is dropped.
+///
+/// # Safety
+///
+/// This is unsafe for the same reasons as [`stderr`].
+///
+/// # Other hazards
+///
+/// This has the same hazards as [`stderr`].
+///
+/// And, when the `OwnedFd` is dropped, subsequent newly created file
+/// descriptors may unknowingly reuse the stderr file descriptor number, which
+/// may break common assumptions, so it should typically only be dropped at the
+/// end of a program when no more file descriptors will be created.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html
+#[inline]
+pub unsafe fn take_stderr() -> OwnedFd {
+ OwnedFd::from(imp::fd::OwnedFd::from_raw_fd(
+ imp::io::types::STDERR_FILENO as RawFd,
+ ))
+}
diff --git a/vendor/rustix/src/io_uring.rs b/vendor/rustix/src/io_uring.rs
new file mode 100644
index 000000000..13f3bbd10
--- /dev/null
+++ b/vendor/rustix/src/io_uring.rs
@@ -0,0 +1,1141 @@
+//! Linux [io_uring].
+//!
+//! This API is very low-level. The main adaptations it makes from the raw
+//! Linux io_uring API are the use of appropriately-sized `bitflags`, `enum`,
+//! `Result`, `OwnedFd`, `AsFd`, `RawFd`, and `*mut c_void` in place of plain
+//! integers.
+//!
+//! # Safety
+//!
+//! io_uring operates on raw pointers and raw file descriptors. Rustix does not
+//! attempt to provide a safe API for these, because the abstraction level is
+//! too low for this to be practical. Safety should be introduced in
+//! higher-level abstraction layers.
+//!
+//! # References
+//! - [Linux]
+//!
+//! [Linux]: https://man.archlinux.org/man/io_uring.7.en
+//! [io_uring]: https://en.wikipedia.org/wiki/Io_uring
+#![allow(unsafe_code)]
+
+use crate::fd::{AsFd, BorrowedFd, RawFd};
+use crate::imp;
+use crate::io::{self, OwnedFd};
+use core::ffi::c_void;
+use core::ptr::null_mut;
+use linux_raw_sys::general as sys;
+
+/// `io_uring_setup(entries, params)`—Setup a context for performing
+/// asynchronous I/O.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man.archlinux.org/man/io_uring_setup.2.en
+#[inline]
+pub fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd> {
+ imp::io_uring::syscalls::io_uring_setup(entries, params)
+}
+
+/// `io_uring_register(fd, opcode, arg, nr_args)`—Register files or user
+/// buffers for asynchronous I/O.
+///
+/// # Safety
+///
+/// io_uring operates on raw pointers and raw file descriptors. Users are
+/// responsible for ensuring that memory and resources are only accessed in
+/// valid ways.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man.archlinux.org/man/io_uring_register.2.en
+#[inline]
+pub unsafe fn io_uring_register<Fd: AsFd>(
+ fd: Fd,
+ opcode: IoringRegisterOp,
+ arg: *const c_void,
+ nr_args: u32,
+) -> io::Result<()> {
+ imp::io_uring::syscalls::io_uring_register(fd.as_fd(), opcode, arg, nr_args)
+}
+
+/// `io_uring_enter(fd, to_submit, min_complete, flags, arg, size)`—Initiate
+/// and/or complete asynchronous I/O.
+///
+/// # Safety
+///
+/// io_uring operates on raw pointers and raw file descriptors. Users are
+/// responsible for ensuring that memory and resources are only accessed in
+/// valid ways.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man.archlinux.org/man/io_uring_enter.2.en
+#[inline]
+pub unsafe fn io_uring_enter<Fd: AsFd>(
+ fd: Fd,
+ to_submit: u32,
+ min_complete: u32,
+ flags: IoringEnterFlags,
+ arg: *const c_void,
+ size: usize,
+) -> io::Result<u32> {
+ imp::io_uring::syscalls::io_uring_enter(fd.as_fd(), to_submit, min_complete, flags, arg, size)
+}
+
+bitflags::bitflags! {
+ /// `IORING_ENTER_*` flags for use with [`io_uring_enter`].
+ #[derive(Default)]
+ pub struct IoringEnterFlags: u32 {
+ /// `IORING_ENTER_GETEVENTS`
+ const GETEVENTS = sys::IORING_ENTER_GETEVENTS;
+
+ /// `IORING_ENTER_SQ_WAKEUP`
+ const SQ_WAKEUP = sys::IORING_ENTER_SQ_WAKEUP;
+
+ /// `IORING_ENTER_SQ_WAIT`
+ const SQ_WAIT = sys::IORING_ENTER_SQ_WAIT;
+
+ /// `IORING_ENTER_EXT_ARG`
+ const EXT_ARG = sys::IORING_ENTER_EXT_ARG;
+ }
+}
+
+/// `IORING_REGISTER_*` and `IORING_UNREGISTER_*` constants for use with
+/// [`io_uring_register`].
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u8)]
+#[non_exhaustive]
+pub enum IoringRegisterOp {
+ /// `IORING_REGISTER_BUFFERS`
+ RegisterBuffers = sys::IORING_REGISTER_BUFFERS as _,
+
+ /// `IORING_UNREGISTER_BUFFERS`
+ UnregisterBuffers = sys::IORING_UNREGISTER_BUFFERS as _,
+
+ /// `IORING_REGISTER_FILES`
+ RegisterFiles = sys::IORING_REGISTER_FILES as _,
+
+ /// `IORING_UNREGISTER_FILES`
+ UnregisterFiles = sys::IORING_UNREGISTER_FILES as _,
+
+ /// `IORING_REGISTER_EVENTFD`
+ RegisterEventfd = sys::IORING_REGISTER_EVENTFD as _,
+
+ /// `IORING_UNREGISTER_EVENTFD`
+ UnregisterEventfd = sys::IORING_UNREGISTER_EVENTFD as _,
+
+ /// `IORING_REGISTER_FILES_UPDATE`
+ RegisterFilesUpdate = sys::IORING_REGISTER_FILES_UPDATE as _,
+
+ /// `IORING_REGISTER_EVENTFD_ASYNC`
+ RegisterEventfdAsync = sys::IORING_REGISTER_EVENTFD_ASYNC as _,
+
+ /// `IORING_REGISTER_PROBE`
+ RegisterProbe = sys::IORING_REGISTER_PROBE as _,
+
+ /// `IORING_REGISTER_PERSONALITY`
+ RegisterPersonality = sys::IORING_REGISTER_PERSONALITY as _,
+
+ /// `IORING_UNREGISTER_PERSONALITY`
+ UnregisterPersonality = sys::IORING_UNREGISTER_PERSONALITY as _,
+
+ /// `IORING_REGISTER_RESTRICTIONS`
+ RegisterRestrictions = sys::IORING_REGISTER_RESTRICTIONS as _,
+
+ /// `IORING_REGISTER_ENABLE_RINGS`
+ RegisterEnableRings = sys::IORING_REGISTER_ENABLE_RINGS as _,
+
+ /// `IORING_REGISTER_BUFFERS2`
+ RegisterBuffers2 = sys::IORING_REGISTER_BUFFERS2 as _,
+
+ /// `IORING_REGISTER_BUFFERS_UPDATE`
+ RegisterBuffersUpdate = sys::IORING_REGISTER_BUFFERS_UPDATE as _,
+
+ /// `IORING_REGISTER_FILES2`
+ RegisterFiles2 = sys::IORING_REGISTER_FILES2 as _,
+
+ /// `IORING_REGISTER_FILES_SKIP`
+ RegisterFilesSkip = sys::IORING_REGISTER_FILES_SKIP as _,
+
+ /// `IORING_REGISTER_FILES_UPDATE2`
+ RegisterFilesUpdate2 = sys::IORING_REGISTER_FILES_UPDATE2 as _,
+
+ /// `IORING_REGISTER_IOWQ_AFF`
+ RegisterIowqAff = sys::IORING_REGISTER_IOWQ_AFF as _,
+
+ /// `IORING_UNREGISTER_IOWQ_AFF`
+ UnregisterIowqAff = sys::IORING_UNREGISTER_IOWQ_AFF as _,
+
+ /// `IORING_REGISTER_IOWQ_MAX_WORKERS`
+ RegisterIowqMaxWorkers = sys::IORING_REGISTER_IOWQ_MAX_WORKERS as _,
+}
+
+/// `IORING_OP_*` constants for use with [`io_uring_sqe`].
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u8)]
+#[non_exhaustive]
+pub enum IoringOp {
+ /// `IORING_OP_NOP`
+ Nop = sys::IORING_OP_NOP as _,
+
+ /// `IORING_OP_ACCEPT`
+ Accept = sys::IORING_OP_ACCEPT as _,
+
+ /// `IORING_OP_ASYNC_CANCEL`
+ AsyncCancel = sys::IORING_OP_ASYNC_CANCEL as _,
+
+ /// `IORING_OP_CLOSE`
+ Close = sys::IORING_OP_CLOSE as _,
+
+ /// `IORING_OP_CONNECT`
+ Connect = sys::IORING_OP_CONNECT as _,
+
+ /// `IORING_OP_EPOLL_CTL`
+ EpollCtl = sys::IORING_OP_EPOLL_CTL as _,
+
+ /// `IORING_OP_FADVISE`
+ Fadvise = sys::IORING_OP_FADVISE as _,
+
+ /// `IORING_OP_FALLOCATE`
+ Fallocate = sys::IORING_OP_FALLOCATE as _,
+
+ /// `IORING_OP_FILES_UPDATE`
+ FilesUpdate = sys::IORING_OP_FILES_UPDATE as _,
+
+ /// `IORING_OP_FSYNC`
+ Fsync = sys::IORING_OP_FSYNC as _,
+
+ /// `IORING_OP_LINKAT`
+ Linkat = sys::IORING_OP_LINKAT as _,
+
+ /// `IORING_OP_LINK_TIMEOUT`
+ LinkTimeout = sys::IORING_OP_LINK_TIMEOUT as _,
+
+ /// `IORING_OP_MADVISE`
+ Madvise = sys::IORING_OP_MADVISE as _,
+
+ /// `IORING_OP_MKDIRAT`
+ Mkdirat = sys::IORING_OP_MKDIRAT as _,
+
+ /// `IORING_OP_OPENAT`
+ Openat = sys::IORING_OP_OPENAT as _,
+
+ /// `IORING_OP_OPENAT2`
+ Openat2 = sys::IORING_OP_OPENAT2 as _,
+
+ /// `IORING_OP_POLL_ADD`
+ PollAdd = sys::IORING_OP_POLL_ADD as _,
+
+ /// `IORING_OP_POLL_REMOVE`
+ PollRemove = sys::IORING_OP_POLL_REMOVE as _,
+
+ /// `IORING_OP_PROVIDE_BUFFERS`
+ ProvideBuffers = sys::IORING_OP_PROVIDE_BUFFERS as _,
+
+ /// `IORING_OP_READ`
+ Read = sys::IORING_OP_READ as _,
+
+ /// `IORING_OP_READV`
+ Readv = sys::IORING_OP_READV as _,
+
+ /// `IORING_OP_READ_FIXED`
+ ReadFixed = sys::IORING_OP_READ_FIXED as _,
+
+ /// `IORING_OP_RECV`
+ Recv = sys::IORING_OP_RECV as _,
+
+ /// `IORING_OP_RECVMSG`
+ Recvmsg = sys::IORING_OP_RECVMSG as _,
+
+ /// `IORING_OP_REMOVE_BUFFERS`
+ RemoveBuffers = sys::IORING_OP_REMOVE_BUFFERS as _,
+
+ /// `IORING_OP_RENAMEAT`
+ Renameat = sys::IORING_OP_RENAMEAT as _,
+
+ /// `IORING_OP_SEND`
+ Send = sys::IORING_OP_SEND as _,
+
+ /// `IORING_OP_SENDMSG`
+ Sendmsg = sys::IORING_OP_SENDMSG as _,
+
+ /// `IORING_OP_SHUTDOWN`
+ Shutdown = sys::IORING_OP_SHUTDOWN as _,
+
+ /// `IORING_OP_SPLICE`
+ Splice = sys::IORING_OP_SPLICE as _,
+
+ /// `IORING_OP_STATX`
+ Statx = sys::IORING_OP_STATX as _,
+
+ /// `IORING_OP_SYMLINKAT`
+ Symlinkat = sys::IORING_OP_SYMLINKAT as _,
+
+ /// `IORING_OP_SYNC_FILE_RANGE`
+ SyncFileRange = sys::IORING_OP_SYNC_FILE_RANGE as _,
+
+ /// `IORING_OP_TEE`
+ Tee = sys::IORING_OP_TEE as _,
+
+ /// `IORING_OP_TIMEOUT`
+ Timeout = sys::IORING_OP_TIMEOUT as _,
+
+ /// `IORING_OP_TIMEOUT_REMOVE`
+ TimeoutRemove = sys::IORING_OP_TIMEOUT_REMOVE as _,
+
+ /// `IORING_OP_UNLINKAT`
+ Unlinkat = sys::IORING_OP_UNLINKAT as _,
+
+ /// `IORING_OP_WRITE`
+ Write = sys::IORING_OP_WRITE as _,
+
+ /// `IORING_OP_WRITEV`
+ Writev = sys::IORING_OP_WRITEV as _,
+
+ /// `IORING_OP_WRITE_FIXED`
+ WriteFixed = sys::IORING_OP_WRITE_FIXED as _,
+}
+
+impl Default for IoringOp {
+ #[inline]
+ fn default() -> Self {
+ Self::Nop
+ }
+}
+
+/// `IORING_RESTRICTION_*` constants for use with [`io_uring_restriction`].
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u16)]
+#[non_exhaustive]
+pub enum IoringRestrictionOp {
+ /// `IORING_RESTRICTION_REGISTER_OP`
+ RegisterOp = sys::IORING_RESTRICTION_REGISTER_OP as _,
+
+ /// `IORING_RESTRICTION_SQE_FLAGS_ALLOWED`
+ SqeFlagsAllowed = sys::IORING_RESTRICTION_SQE_FLAGS_ALLOWED as _,
+
+ /// `IORING_RESTRICTION_SQE_FLAGS_REQUIRED`
+ SqeFlagsRequired = sys::IORING_RESTRICTION_SQE_FLAGS_REQUIRED as _,
+
+ /// `IORING_RESTRICTION_SQE_OP`
+ SqeOp = sys::IORING_RESTRICTION_SQE_OP as _,
+}
+
+impl Default for IoringRestrictionOp {
+ #[inline]
+ fn default() -> Self {
+ Self::RegisterOp
+ }
+}
+
+bitflags::bitflags! {
+ /// `IORING_SETUP_*` flags for use with [`io_uring_params`].
+ #[derive(Default)]
+ pub struct IoringSetupFlags: u32 {
+ /// `IORING_SETUP_ATTACH_WQ`
+ const ATTACH_WQ = sys::IORING_SETUP_ATTACH_WQ;
+
+ /// `IORING_SETUP_CLAMP`
+ const CLAMP = sys::IORING_SETUP_CLAMP;
+
+ /// `IORING_SETUP_CQSIZE`
+ const CQSIZE = sys::IORING_SETUP_CQSIZE;
+
+ /// `IORING_SETUP_IOPOLL`
+ const IOPOLL = sys::IORING_SETUP_IOPOLL;
+
+ /// `IORING_SETUP_R_DISABLED`
+ const R_DISABLED = sys::IORING_SETUP_R_DISABLED;
+
+ /// `IORING_SETUP_SQPOLL`
+ const SQPOLL = sys::IORING_SETUP_SQPOLL;
+
+ /// `IORING_SETUP_SQ_AFF`
+ const SQ_AFF = sys::IORING_SETUP_SQ_AFF;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IOSQE_*` flags for use with [`io_uring_sqe`].
+ #[derive(Default)]
+ pub struct IoringSqeFlags: u8 {
+ /// `1 << IOSQE_ASYNC_BIT`
+ const ASYNC = 1 << sys::IOSQE_ASYNC_BIT as u8;
+
+ /// `1 << IOSQE_BUFFER_SELECT_BIT`
+ const BUFFER_SELECT = 1 << sys::IOSQE_BUFFER_SELECT_BIT as u8;
+
+ /// `1 << IOSQE_FIXED_FILE_BIT`
+ const FIXED_FILE = 1 << sys::IOSQE_FIXED_FILE_BIT as u8;
+
+ /// 1 << `IOSQE_IO_DRAIN_BIT`
+ const IO_DRAIN = 1 << sys::IOSQE_IO_DRAIN_BIT as u8;
+
+ /// `1 << IOSQE_IO_HARDLINK_BIT`
+ const IO_HARDLINK = 1 << sys::IOSQE_IO_HARDLINK_BIT as u8;
+
+ /// `1 << IOSQE_IO_LINK_BIT`
+ const IO_LINK = 1 << sys::IOSQE_IO_LINK_BIT as u8;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IORING_CQE_F_*` flags for use with [`io_uring_cqe`].
+ #[derive(Default)]
+ pub struct IoringCqeFlags: u32 {
+ /// `IORING_CQE_F_BUFFER`
+ const BUFFER = sys::IORING_CQE_F_BUFFER as _;
+
+ /// `IORING_CQE_F_MORE`
+ const MORE = sys::IORING_CQE_F_MORE as _;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IORING_FSYNC_*` flags for use with [`io_uring_sqe`].
+ #[derive(Default)]
+ pub struct IoringFsyncFlags: u32 {
+ /// `IORING_FSYNC_DATASYNC`
+ const DATASYNC = sys::IORING_FSYNC_DATASYNC;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IORING_TIMEOUT_*` and `IORING_LINK_TIMEOUT_UPDATE` flags for use with
+ /// [`io_uring_sqe`].
+ #[derive(Default)]
+ pub struct IoringTimeoutFlags: u32 {
+ /// `IORING_TIMEOUT_ABS`
+ const ABS = sys::IORING_TIMEOUT_ABS;
+
+ /// `IORING_TIMEOUT_UPDATE`
+ const UPDATE = sys::IORING_TIMEOUT_UPDATE;
+
+ /// `IORING_TIMEOUT_BOOTTIME`
+ const BOOTTIME = sys::IORING_TIMEOUT_BOOTTIME;
+
+ /// `IORING_TIMEOUT_ETIME_SUCCESS`
+ const ETIME_SUCCESS = sys::IORING_TIMEOUT_ETIME_SUCCESS;
+
+ /// `IORING_TIMEOUT_REALTIME`
+ const REALTIME = sys::IORING_TIMEOUT_REALTIME;
+
+ /// `IORING_TIMEOUT_CLOCK_MASK`
+ const CLOCK_MASK = sys::IORING_TIMEOUT_CLOCK_MASK;
+
+ /// `IORING_TIMEOUT_UPDATE_MASK`
+ const UPDATE_MASK = sys::IORING_TIMEOUT_UPDATE_MASK;
+
+ /// `IORING_LINK_TIMEOUT_UPDATE`
+ const LINK_TIMEOUT_UPDATE = sys::IORING_LINK_TIMEOUT_UPDATE;
+ }
+}
+
+bitflags::bitflags! {
+ /// `SPLICE_F_*` flags for use with [`io_uring_sqe`].
+ #[derive(Default)]
+ pub struct SpliceFlags: u32 {
+ /// `SPLICE_F_FD_IN_FIXED`
+ const FD_IN_FIXED = sys::SPLICE_F_FD_IN_FIXED;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IORING_FEAT_*` flags for use with [`io_uring_params`].
+ #[derive(Default)]
+ pub struct IoringFeatureFlags: u32 {
+ /// `IORING_FEAT_CQE_SKIP`
+ const CQE_SKIP = sys::IORING_FEAT_CQE_SKIP;
+
+ /// `IORING_FEAT_CUR_PERSONALITY`
+ const CUR_PERSONALITY = sys::IORING_FEAT_CUR_PERSONALITY;
+
+ /// `IORING_FEAT_EXT_ARG`
+ const EXT_ARG = sys::IORING_FEAT_EXT_ARG;
+
+ /// `IORING_FEAT_FAST_POLL`
+ const FAST_POLL = sys::IORING_FEAT_FAST_POLL;
+
+ /// `IORING_FEAT_NATIVE_WORKERS`
+ const NATIVE_WORKERS = sys::IORING_FEAT_NATIVE_WORKERS;
+
+ /// `IORING_FEAT_NODROP`
+ const NODROP = sys::IORING_FEAT_NODROP;
+
+ /// `IORING_FEAT_POLL_32BITS`
+ const POLL_32BITS = sys::IORING_FEAT_POLL_32BITS;
+
+ /// `IORING_FEAT_RSRC_TAGS`
+ const RSRC_TAGS = sys::IORING_FEAT_RSRC_TAGS;
+
+ /// `IORING_FEAT_RW_CUR_POS`
+ const RW_CUR_POS = sys::IORING_FEAT_RW_CUR_POS;
+
+ /// `IORING_FEAT_SINGLE_MMAP`
+ const SINGLE_MMAP = sys::IORING_FEAT_SINGLE_MMAP;
+
+ /// `IORING_FEAT_SQPOLL_NONFIXED`
+ const SQPOLL_NONFIXED = sys::IORING_FEAT_SQPOLL_NONFIXED;
+
+ /// `IORING_FEAT_SUBMIT_STABLE`
+ const SUBMIT_STABLE = sys::IORING_FEAT_SUBMIT_STABLE;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IO_URING_OP_*` flags for use with [`io_uring_probe_op`].
+ #[derive(Default)]
+ pub struct IoringOpFlags: u16 {
+ /// `IO_URING_OP_SUPPORTED`
+ const SUPPORTED = sys::IO_URING_OP_SUPPORTED as _;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IORING_SQ_*` flags.
+ #[derive(Default)]
+ pub struct IoringSqFlags: u32 {
+ /// `IORING_SQ_NEED_WAKEUP`
+ const NEED_WAKEUP = sys::IORING_SQ_NEED_WAKEUP;
+
+ /// `IORING_SQ_CQ_OVERFLOW`
+ const CQ_OVERFLOW = sys::IORING_SQ_CQ_OVERFLOW;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IORING_CQ_*` flags.
+ #[derive(Default)]
+ pub struct IoringCqFlags: u32 {
+ /// `IORING_CQ_EVENTFD_DISABLED`
+ const EVENTFD_DISABLED = sys::IORING_CQ_EVENTFD_DISABLED;
+ }
+}
+
+bitflags::bitflags! {
+ /// `IORING_POLL_*` flags.
+ #[derive(Default)]
+ pub struct IoringPollFlags: u32 {
+ /// `IORING_POLL_ADD_MULTI`
+ const ADD_MULTI = sys::IORING_POLL_ADD_MULTI;
+
+ /// `IORING_POLL_UPDATE_EVENTS`
+ const UPDATE_EVENTS = sys::IORING_POLL_UPDATE_EVENTS;
+
+ /// `IORING_POLL_UPDATE_USER_DATA`
+ const UPDATE_USER_DATA = sys::IORING_POLL_UPDATE_USER_DATA;
+ }
+}
+
+#[allow(missing_docs)]
+pub const IORING_CQE_BUFFER_SHIFT: u32 = sys::IORING_CQE_BUFFER_SHIFT as _;
+
+// Re-export these as `u64`, which is the `offset` type in `rustix::io::mmap`.
+#[allow(missing_docs)]
+pub const IORING_OFF_SQ_RING: u64 = sys::IORING_OFF_SQ_RING as _;
+#[allow(missing_docs)]
+pub const IORING_OFF_CQ_RING: u64 = sys::IORING_OFF_CQ_RING as _;
+#[allow(missing_docs)]
+pub const IORING_OFF_SQES: u64 = sys::IORING_OFF_SQES as _;
+
+/// `IORING_REGISTER_FILES_SKIP`
+#[inline]
+#[doc(alias = "IORING_REGISTER_FILES_SKIP")]
+#[allow(unsafe_code)]
+pub const fn io_uring_register_files_skip() -> BorrowedFd<'static> {
+ let files_skip = sys::IORING_REGISTER_FILES_SKIP as RawFd;
+
+ // Safety: `IORING_REGISTER_FILES_SKIP` is a reserved value that is never
+ // dynamically allocated, so it'll remain valid for the duration of
+ // `'static`.
+ unsafe { BorrowedFd::<'static>::borrow_raw(files_skip) }
+}
+
+/// A pointer in the io_uring API.
+///
+/// `io_uring`'s native API represents pointers as `u64` values. In order to
+/// preserve strict-provenance, use a `*mut c_void`. On platforms where
+/// pointers are narrower than 64 bits, this requires additional padding.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct io_uring_ptr {
+ #[cfg(all(target_pointer_width = "32", target_endian = "big"))]
+ #[doc(hidden)]
+ pub __pad32: u32,
+ #[cfg(all(target_pointer_width = "16", target_endian = "big"))]
+ #[doc(hidden)]
+ pub __pad16: u16,
+
+ /// The pointer value.
+ pub ptr: *mut c_void,
+
+ #[cfg(all(target_pointer_width = "16", target_endian = "little"))]
+ #[doc(hidden)]
+ pub __pad16: u16,
+ #[cfg(all(target_pointer_width = "32", target_endian = "little"))]
+ #[doc(hidden)]
+ pub __pad32: u32,
+}
+
+impl From<*mut c_void> for io_uring_ptr {
+ #[inline]
+ fn from(ptr: *mut c_void) -> Self {
+ Self {
+ ptr,
+
+ #[cfg(target_pointer_width = "16")]
+ __pad16: Default::default(),
+ #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
+ __pad32: Default::default(),
+ }
+ }
+}
+
+impl Default for io_uring_ptr {
+ #[inline]
+ fn default() -> Self {
+ Self::from(null_mut())
+ }
+}
+
+/// User data in the io_uring API.
+///
+/// `io_uring`'s native API represents `user_data` fields as `u64` values. In
+/// order to preserve strict-provenance, use a union which allows users to
+/// optionally store pointers.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union io_uring_user_data {
+ /// An arbitrary `u64`.
+ pub u64_: u64,
+
+ /// A pointer.
+ pub ptr: io_uring_ptr,
+}
+
+impl io_uring_user_data {
+ /// Return the `u64` value.
+ #[inline]
+ pub fn u64_(self) -> u64 {
+ // Safety: All the fields have the same underlying representation.
+ unsafe { self.u64_ }
+ }
+
+ /// Create a `Self` from a `u64` value.
+ #[inline]
+ pub fn from_u64(u64_: u64) -> Self {
+ Self { u64_ }
+ }
+
+ /// Return the `ptr` pointer value.
+ #[inline]
+ pub fn ptr(self) -> *mut c_void {
+ // Safety: All the fields have the same underlying representation.
+ unsafe { self.ptr }.ptr
+ }
+
+ /// Create a `Self` from a pointer value.
+ #[inline]
+ pub fn from_ptr(ptr: *mut c_void) -> Self {
+ Self {
+ ptr: io_uring_ptr::from(ptr),
+ }
+ }
+}
+
+impl Default for io_uring_user_data {
+ #[inline]
+ fn default() -> Self {
+ let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+ // Safety: All of Linux's io_uring structs may be zero-initialized.
+ unsafe {
+ ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+
+impl core::fmt::Debug for io_uring_user_data {
+ fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ // Safety: Just format as a `u64`, since formatting doesn't preserve
+ // provenance, and we don't have a discriminant.
+ unsafe { self.u64_.fmt(fmt) }
+ }
+}
+
+/// An io_uring Submission Queue Entry.
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Copy, Clone, Default)]
+pub struct io_uring_sqe {
+ pub opcode: IoringOp,
+ pub flags: IoringSqeFlags,
+ pub ioprio: u16,
+ pub fd: RawFd,
+ pub off_or_addr2: off_or_addr2_union,
+ pub addr_or_splice_off_in: addr_or_splice_off_in_union,
+ pub len: u32,
+ pub op_flags: op_flags_union,
+ pub user_data: io_uring_user_data,
+ pub buf: buf_union,
+ pub personality: u16,
+ pub splice_fd_in_or_file_index: splice_fd_in_or_file_index_union,
+ pub __pad2: [u64; 2],
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union off_or_addr2_union {
+ pub off: u64,
+ pub addr2: io_uring_ptr,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union addr_or_splice_off_in_union {
+ pub addr: io_uring_ptr,
+ pub splice_off_in: u64,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union op_flags_union {
+ pub rw_flags: crate::io::ReadWriteFlags,
+ pub fsync_flags: IoringFsyncFlags,
+ pub poll_events: u16,
+ pub poll32_events: u32,
+ pub sync_range_flags: u32,
+ /// `msg_flags` is split into `send_flags` and `recv_flags`.
+ #[doc(alias = "msg_flags")]
+ pub send_flags: crate::net::SendFlags,
+ /// `msg_flags` is split into `send_flags` and `recv_flags`.
+ #[doc(alias = "msg_flags")]
+ pub recv_flags: crate::net::RecvFlags,
+ pub timeout_flags: IoringTimeoutFlags,
+ pub accept_flags: crate::net::AcceptFlags,
+ pub cancel_flags: u32,
+ pub open_flags: crate::fs::AtFlags,
+ pub statx_flags: crate::fs::AtFlags,
+ pub fadvise_advice: crate::fs::Advice,
+ pub splice_flags: SpliceFlags,
+ pub rename_flags: crate::fs::RenameFlags,
+ pub unlink_flags: crate::fs::AtFlags,
+ pub hardlink_flags: crate::fs::AtFlags,
+}
+
+#[allow(missing_docs)]
+#[repr(C, packed)]
+#[derive(Copy, Clone)]
+pub union buf_union {
+ pub buf_index: u16,
+ pub buf_group: u16,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union splice_fd_in_or_file_index_union {
+ pub splice_fd_in: i32,
+ pub file_index: u32,
+}
+
+/// An io_uring Completion Queue Entry.
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_uring_cqe {
+ pub user_data: io_uring_user_data,
+ pub res: i32,
+ pub flags: IoringCqeFlags,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Copy, Clone, Default)]
+pub struct io_uring_restriction {
+ pub opcode: IoringRestrictionOp,
+ pub register_or_sqe_op_or_sqe_flags: register_or_sqe_op_or_sqe_flags_union,
+ pub resv: u8,
+ pub resv2: [u32; 3],
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union register_or_sqe_op_or_sqe_flags_union {
+ pub register_op: IoringRegisterOp,
+ pub sqe_op: IoringOp,
+ pub sqe_flags: IoringSqeFlags,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_uring_params {
+ pub sq_entries: u32,
+ pub cq_entries: u32,
+ pub flags: IoringSetupFlags,
+ pub sq_thread_cpu: u32,
+ pub sq_thread_idle: u32,
+ pub features: IoringFeatureFlags,
+ pub wq_fd: u32,
+ pub resv: [u32; 3],
+ pub sq_off: io_sqring_offsets,
+ pub cq_off: io_cqring_offsets,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_sqring_offsets {
+ pub head: u32,
+ pub tail: u32,
+ pub ring_mask: u32,
+ pub ring_entries: u32,
+ pub flags: u32,
+ pub dropped: u32,
+ pub array: u32,
+ pub resv1: u32,
+ pub resv2: u64,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_cqring_offsets {
+ pub head: u32,
+ pub tail: u32,
+ pub ring_mask: u32,
+ pub ring_entries: u32,
+ pub overflow: u32,
+ pub cqes: u32,
+ pub flags: u32,
+ pub resv1: u32,
+ pub resv2: u64,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Default)]
+pub struct io_uring_probe {
+ pub last_op: IoringOp,
+ pub ops_len: u8,
+ pub resv: u16,
+ pub resv2: [u32; 3],
+ pub ops: sys::__IncompleteArrayField<io_uring_probe_op>,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_uring_probe_op {
+ pub op: IoringOp,
+ pub resv: u8,
+ pub flags: IoringOpFlags,
+ pub resv2: u32,
+}
+
+#[allow(missing_docs)]
+#[repr(C, align(8))]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_uring_files_update {
+ pub offset: u32,
+ pub resv: u32,
+ pub fds: u64,
+}
+
+#[allow(missing_docs)]
+#[repr(C, align(8))]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_uring_rsrc_register {
+ pub nr: u32,
+ pub resv: u32,
+ pub resv2: u64,
+ pub data: u64,
+ pub tags: u64,
+}
+
+#[allow(missing_docs)]
+#[repr(C, align(8))]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_uring_rsrc_update {
+ pub offset: u32,
+ pub resv: u32,
+ pub data: u64,
+}
+
+#[allow(missing_docs)]
+#[repr(C, align(8))]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_uring_rsrc_update2 {
+ pub offset: u32,
+ pub resv: u32,
+ pub data: u64,
+ pub tags: u64,
+ pub nr: u32,
+ pub resv2: u32,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct io_uring_getevents_arg {
+ pub sigmask: u64,
+ pub sigmask_sz: u32,
+ pub pad: u32,
+ pub ts: u64,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct iovec {
+ pub iov_base: *mut c_void,
+ pub iov_len: usize,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Default)]
+pub struct open_how {
+ /// An [`OFlags`] value represented as a `u64`.
+ ///
+ /// [`OFlags`]: crate::fs::OFlags
+ pub flags: u64,
+
+ /// A [`Mode`] value represented as a `u64`.
+ ///
+ /// [`Mode`]: crate::fs::Mode
+ pub mode: u64,
+
+ pub resolve: crate::fs::ResolveFlags,
+}
+
+impl Default for off_or_addr2_union {
+ #[inline]
+ fn default() -> Self {
+ let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+ // Safety: All of Linux's io_uring structs may be zero-initialized.
+ unsafe {
+ ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+
+impl Default for addr_or_splice_off_in_union {
+ #[inline]
+ fn default() -> Self {
+ let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+ // Safety: All of Linux's io_uring structs may be zero-initialized.
+ unsafe {
+ ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+
+impl Default for op_flags_union {
+ #[inline]
+ fn default() -> Self {
+ let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+ // Safety: All of Linux's io_uring structs may be zero-initialized.
+ unsafe {
+ ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+
+impl Default for buf_union {
+ #[inline]
+ fn default() -> Self {
+ let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+ // Safety: All of Linux's io_uring structs may be zero-initialized.
+ unsafe {
+ ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+
+impl Default for splice_fd_in_or_file_index_union {
+ #[inline]
+ fn default() -> Self {
+ let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+ // Safety: All of Linux's io_uring structs may be zero-initialized.
+ unsafe {
+ ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+
+impl Default for register_or_sqe_op_or_sqe_flags_union {
+ #[inline]
+ fn default() -> Self {
+ let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
+ // Safety: All of Linux's io_uring structs may be zero-initialized.
+ unsafe {
+ ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+
+/// Check that our custom structs and unions have the same layout as the
+/// kernel's versions.
+#[test]
+fn io_uring_layouts() {
+ use core::mem::{align_of, size_of};
+ use memoffset::{offset_of, span_of};
+
+ // Check that the size and alignment of a type match the `sys` bindings.
+ macro_rules! check_type {
+ ($struct:ident) => {
+ assert_eq!(
+ (size_of::<$struct>(), align_of::<$struct>()),
+ (size_of::<sys::$struct>(), align_of::<sys::$struct>())
+ );
+ };
+ }
+
+ // The same as `check_type`, but for unions we've renamed to avoid having
+ // types like "bindgen_ty_1" in the API.
+ macro_rules! check_renamed_union {
+ ($to:ident, $from:ident) => {
+ assert_eq!(
+ (size_of::<$to>(), align_of::<$to>()),
+ (size_of::<sys::$from>(), align_of::<sys::$from>())
+ );
+ };
+ }
+
+ // Check that the field of a struct has the same offset as the
+ // corresponding field in the `sys` bindings.
+ macro_rules! check_struct_field {
+ ($struct:ident, $field:ident) => {
+ assert_eq!(
+ offset_of!($struct, $field),
+ offset_of!(sys::$struct, $field)
+ );
+ assert_eq!(span_of!($struct, $field), span_of!(sys::$struct, $field));
+ };
+ }
+
+ // The same as `check_struct_field`, but for unions we've renamed to avoid
+ // having types like "bindgen_ty_1" in the API.
+ macro_rules! check_struct_renamed_union_field {
+ ($struct:ident, $to:ident, $from:ident) => {
+ assert_eq!(offset_of!($struct, $to), offset_of!(sys::$struct, $from));
+ assert_eq!(span_of!($struct, $to), span_of!(sys::$struct, $from));
+ };
+ }
+
+ // For the common case of no renaming, check all fields of a struct.
+ macro_rules! check_struct {
+ ($name:ident, $($field:ident),*) => {
+ // Check the size and alignment.
+ check_type!($name);
+
+ // Check that we have all the fields.
+ let _test = $name {
+ // Safety: All of io_uring's types can be zero-initialized.
+ $($field: unsafe { core::mem::zeroed() }),*
+ };
+
+ // Check that the fields have the right sizes and offsets.
+ $(check_struct_field!($name, $field));*
+ };
+ }
+
+ check_renamed_union!(off_or_addr2_union, io_uring_sqe__bindgen_ty_1);
+ check_renamed_union!(addr_or_splice_off_in_union, io_uring_sqe__bindgen_ty_2);
+ check_renamed_union!(op_flags_union, io_uring_sqe__bindgen_ty_3);
+ check_renamed_union!(buf_union, io_uring_sqe__bindgen_ty_4);
+ check_renamed_union!(splice_fd_in_or_file_index_union, io_uring_sqe__bindgen_ty_5);
+ check_renamed_union!(
+ register_or_sqe_op_or_sqe_flags_union,
+ io_uring_restriction__bindgen_ty_1
+ );
+
+ check_type!(io_uring_sqe);
+ check_struct_field!(io_uring_sqe, opcode);
+ check_struct_field!(io_uring_sqe, flags);
+ check_struct_field!(io_uring_sqe, ioprio);
+ check_struct_field!(io_uring_sqe, fd);
+ check_struct_renamed_union_field!(io_uring_sqe, off_or_addr2, __bindgen_anon_1);
+ check_struct_renamed_union_field!(io_uring_sqe, addr_or_splice_off_in, __bindgen_anon_2);
+ check_struct_field!(io_uring_sqe, len);
+ check_struct_renamed_union_field!(io_uring_sqe, op_flags, __bindgen_anon_3);
+ check_struct_field!(io_uring_sqe, user_data);
+ check_struct_renamed_union_field!(io_uring_sqe, buf, __bindgen_anon_4);
+ check_struct_field!(io_uring_sqe, personality);
+ check_struct_renamed_union_field!(io_uring_sqe, splice_fd_in_or_file_index, __bindgen_anon_5);
+ check_struct_field!(io_uring_sqe, __pad2);
+
+ check_type!(io_uring_restriction);
+ check_struct_field!(io_uring_restriction, opcode);
+ check_struct_renamed_union_field!(
+ io_uring_restriction,
+ register_or_sqe_op_or_sqe_flags,
+ __bindgen_anon_1
+ );
+ check_struct_field!(io_uring_restriction, resv);
+ check_struct_field!(io_uring_restriction, resv2);
+
+ check_struct!(io_uring_cqe, user_data, res, flags);
+ check_struct!(
+ io_uring_params,
+ sq_entries,
+ cq_entries,
+ flags,
+ sq_thread_cpu,
+ sq_thread_idle,
+ features,
+ wq_fd,
+ resv,
+ sq_off,
+ cq_off
+ );
+ check_struct!(
+ io_sqring_offsets,
+ head,
+ tail,
+ ring_mask,
+ ring_entries,
+ flags,
+ dropped,
+ array,
+ resv1,
+ resv2
+ );
+ check_struct!(
+ io_cqring_offsets,
+ head,
+ tail,
+ ring_mask,
+ ring_entries,
+ overflow,
+ cqes,
+ flags,
+ resv1,
+ resv2
+ );
+ check_struct!(io_uring_probe, last_op, ops_len, resv, resv2, ops);
+ check_struct!(io_uring_probe_op, op, resv, flags, resv2);
+ check_struct!(io_uring_files_update, offset, resv, fds);
+ check_struct!(io_uring_rsrc_register, nr, resv, resv2, data, tags);
+ check_struct!(io_uring_rsrc_update, offset, resv, data);
+ check_struct!(io_uring_rsrc_update2, offset, resv, data, tags, nr, resv2);
+ check_struct!(io_uring_getevents_arg, sigmask, sigmask_sz, pad, ts);
+ check_struct!(iovec, iov_base, iov_len);
+ check_struct!(open_how, flags, mode, resolve);
+}
diff --git a/vendor/rustix/src/lib.rs b/vendor/rustix/src/lib.rs
new file mode 100644
index 000000000..ca7c6cd4e
--- /dev/null
+++ b/vendor/rustix/src/lib.rs
@@ -0,0 +1,230 @@
+//! `rustix` provides efficient memory-safe and [I/O-safe] wrappers to
+//! POSIX-like, Unix-like, Linux, and Winsock2 syscall-like APIs, with
+//! configurable backends.
+//!
+//! With rustix, you can write code like this:
+//!
+//! ```rust
+//! # #[cfg(feature = "net")]
+//! # fn read(sock: std::net::TcpStream, buf: &mut [u8]) -> std::io::Result<()> {
+//! # use rustix::net::RecvFlags;
+//! let nread: usize = rustix::net::recv(&sock, buf, RecvFlags::PEEK)?;
+//! # let _ = nread;
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! instead of like this:
+//!
+//! ```rust
+//! # #[cfg(feature = "net")]
+//! # fn read(sock: std::net::TcpStream, buf: &mut [u8]) -> std::io::Result<()> {
+//! # use std::convert::TryInto;
+//! # #[cfg(unix)]
+//! # use std::os::unix::io::AsRawFd;
+//! # #[cfg(target_os = "wasi")]
+//! # use std::os::wasi::io::AsRawFd;
+//! # #[cfg(windows)]
+//! # use windows_sys::Win32::Networking::WinSock as libc;
+//! # #[cfg(windows)]
+//! # use std::os::windows::io::AsRawSocket;
+//! # const MSG_PEEK: i32 = libc::MSG_PEEK;
+//! let nread: usize = unsafe {
+//! #[cfg(any(unix, target_os = "wasi"))]
+//! let raw = sock.as_raw_fd();
+//! #[cfg(windows)]
+//! let raw = sock.as_raw_socket();
+//! match libc::recv(
+//! raw as _,
+//! buf.as_mut_ptr().cast(),
+//! buf.len().try_into().unwrap_or(i32::MAX as _),
+//! MSG_PEEK,
+//! ) {
+//! -1 => return Err(std::io::Error::last_os_error()),
+//! nread => nread as usize,
+//! }
+//! };
+//! # let _ = nread;
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! rustix's APIs perform the following tasks:
+//! - Error values are translated to [`Result`]s.
+//! - Buffers are passed as Rust slices.
+//! - Out-parameters are presented as return values.
+//! - Path arguments use [`Arg`], so they accept any string type.
+//! - File descriptors are passed and returned via [`AsFd`] and [`OwnedFd`]
+//! instead of bare integers, ensuring I/O safety.
+//! - Constants use `enum`s and [`bitflags`] types.
+//! - Multiplexed functions (eg. `fcntl`, `ioctl`, etc.) are de-multiplexed.
+//! - Variadic functions (eg. `openat`, etc.) are presented as non-variadic.
+//! - Functions and types which need `l` prefixes or `64` suffixes to enable
+//! large-file support are used automatically, and file sizes and offsets
+//! are presented as `u64` and `i64`.
+//! - Behaviors that depend on the sizes of C types like `long` are hidden.
+//! - In some places, more human-friendly and less historical-accident names
+//! are used (and documentation aliases are used so that the original names
+//! can still be searched for).
+//! - Provide y2038 compatibility, on platforms which support this.
+//! - Correct selected platform bugs, such as behavioral differences when
+//! running under seccomp.
+//!
+//! Things they don't do include:
+//! - Detecting whether functions are supported at runtime.
+//! - Hiding significant differences between platforms.
+//! - Restricting ambient authorities.
+//! - Imposing sandboxing features such as filesystem path or network address
+//! sandboxing.
+//!
+//! See [`cap-std`], [`system-interface`], and [`io-streams`] for libraries
+//! which do hide significant differences between platforms, and [`cap-std`]
+//! which does perform sandboxing and restricts ambient authorities.
+//!
+//! [`cap-std`]: https://crates.io/crates/cap-std
+//! [`system-interface`]: https://crates.io/crates/system-interface
+//! [`io-streams`]: https://crates.io/crates/io-streams
+//! [`getrandom`]: https://crates.io/crates/getrandom
+//! [`bitflags`]: https://crates.io/crates/bitflags
+//! [`AsFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsFd.html
+//! [`OwnedFd`]: https://docs.rs/io-lifetimes/latest/io_lifetimes/struct.OwnedFd.html
+//! [io-lifetimes crate]: https://crates.io/crates/io-lifetimes
+//! [I/O-safe]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md
+//! [`Result`]: https://docs.rs/rustix/latest/rustix/io/type.Result.html
+//! [`Arg`]: https://docs.rs/rustix/latest/rustix/path/trait.Arg.html
+
+#![deny(missing_docs)]
+#![allow(stable_features)]
+#![cfg_attr(linux_raw, deny(unsafe_code))]
+#![cfg_attr(rustc_attrs, feature(rustc_attrs))]
+#![cfg_attr(doc_cfg, feature(doc_cfg))]
+#![cfg_attr(all(target_os = "wasi", feature = "std"), feature(wasi_ext))]
+#![cfg_attr(
+ all(linux_raw, naked_functions, target_arch = "x86"),
+ feature(naked_functions)
+)]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+#![cfg_attr(core_ffi_c, feature(core_ffi_c))]
+#![cfg_attr(core_c_str, feature(core_c_str))]
+#![cfg_attr(alloc_c_string, feature(alloc_ffi))]
+#![cfg_attr(alloc_c_string, feature(alloc_c_string))]
+#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(feature = "rustc-dep-of-std", feature(core_intrinsics))]
+#![cfg_attr(feature = "rustc-dep-of-std", feature(ip))]
+#![cfg_attr(
+ all(not(feature = "rustc-dep-of-std"), core_intrinsics),
+ feature(core_intrinsics)
+)]
+#![cfg_attr(asm_experimental_arch, feature(asm_experimental_arch))]
+#![cfg_attr(not(feature = "all-apis"), allow(dead_code))]
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+extern crate alloc;
+
+// Internal utilities.
+#[cfg(not(windows))]
+#[macro_use]
+pub(crate) mod cstr;
+#[macro_use]
+pub(crate) mod const_assert;
+pub(crate) mod utils;
+
+// Pick the backend implementation to use.
+#[cfg_attr(libc, path = "imp/libc/mod.rs")]
+#[cfg_attr(linux_raw, path = "imp/linux_raw/mod.rs")]
+#[cfg_attr(wasi, path = "imp/wasi/mod.rs")]
+mod imp;
+
+/// Export the `*Fd` types and traits that are used in rustix's public API.
+///
+/// Users can use this to avoid needing to import anything else to use the same
+/// versions of these types and traits.
+///
+/// Rustix APIs that use `OwnedFd` use [`rustix::io::OwnedFd`] instead, which
+/// allows rustix to implement `close` for them.
+///
+/// [`rustix::io::OwnedFd`]: crate::io::OwnedFd
+pub mod fd {
+ use super::imp;
+ pub use imp::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+ #[cfg(windows)]
+ pub use imp::fd::{AsSocket, FromSocket, IntoSocket};
+ #[cfg(feature = "std")]
+ pub use imp::fd::{FromFd, IntoFd};
+}
+
+// The public API modules.
+#[cfg(not(windows))]
+pub mod ffi;
+#[cfg(not(windows))]
+#[cfg(feature = "fs")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))]
+pub mod fs;
+pub mod io;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(feature = "io_uring")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "io_uring")))]
+pub mod io_uring;
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[cfg(feature = "mm")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "mm")))]
+pub mod mm;
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[cfg(feature = "net")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "net")))]
+pub mod net;
+#[cfg(not(windows))]
+#[cfg(feature = "param")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "param")))]
+pub mod param;
+#[cfg(not(windows))]
+#[cfg(any(feature = "fs", feature = "net"))]
+#[cfg_attr(doc_cfg, doc(cfg(any(feature = "fs", feature = "net"))))]
+pub mod path;
+#[cfg(not(windows))]
+#[cfg(feature = "process")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "process")))]
+pub mod process;
+#[cfg(not(windows))]
+#[cfg(feature = "rand")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))]
+pub mod rand;
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[cfg(feature = "termios")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "termios")))]
+pub mod termios;
+#[cfg(not(windows))]
+#[cfg(feature = "thread")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "thread")))]
+pub mod thread;
+#[cfg(not(windows))]
+#[cfg(feature = "time")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "time")))]
+pub mod time;
+
+// "runtime" is also a public API module, but it's only for libc-like users.
+#[cfg(not(windows))]
+#[cfg(feature = "runtime")]
+#[doc(hidden)]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "runtime")))]
+pub mod runtime;
+
+// We have some internal interdependencies in the API features, so for now,
+// for API features that aren't enabled, declare them as `pub(crate)` so
+// that they're not public, but still available for internal use.
+
+#[cfg(not(windows))]
+#[cfg(not(feature = "fs"))]
+pub(crate) mod fs;
+#[cfg(not(windows))]
+#[cfg(all(
+ not(feature = "param"),
+ any(feature = "runtime", feature = "time", target_arch = "x86"),
+))]
+pub(crate) mod param;
+#[cfg(not(windows))]
+#[cfg(not(any(feature = "fs", feature = "net")))]
+pub(crate) mod path;
+#[cfg(not(windows))]
+#[cfg(not(feature = "process"))]
+pub(crate) mod process;
diff --git a/vendor/rustix/src/mm/madvise.rs b/vendor/rustix/src/mm/madvise.rs
new file mode 100644
index 000000000..317c3b515
--- /dev/null
+++ b/vendor/rustix/src/mm/madvise.rs
@@ -0,0 +1,35 @@
+//! The `madvise` function.
+//!
+//! # Safety
+//!
+//! `madvise` operates on a raw pointer. Some forms of `madvise` may
+//! mutate the memory or have other side effects.
+#![allow(unsafe_code)]
+
+use crate::{imp, io};
+use core::ffi::c_void;
+
+pub use imp::mm::types::Advice;
+
+/// `posix_madvise(addr, len, advice)`—Declares an expected access pattern
+/// for a memory-mapped file.
+///
+/// # Safety
+///
+/// `addr` must be a valid pointer to memory that is appropriate to
+/// call `posix_madvise` on. Some forms of `advice` may mutate the memory
+/// or evoke a variety of side-effects on the mapping and/or the file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux `madvise`]
+/// - [Linux `posix_madvise`]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_madvise.html
+/// [Linux `madvise`]: https://man7.org/linux/man-pages/man2/madvise.2.html
+/// [Linux `posix_madvise`]: https://man7.org/linux/man-pages/man3/posix_madvise.3.html
+#[inline]
+#[doc(alias = "posix_madvise")]
+pub unsafe fn madvise(addr: *mut c_void, len: usize, advice: Advice) -> io::Result<()> {
+ imp::mm::syscalls::madvise(addr, len, advice)
+}
diff --git a/vendor/rustix/src/mm/mmap.rs b/vendor/rustix/src/mm/mmap.rs
new file mode 100644
index 000000000..7be02464e
--- /dev/null
+++ b/vendor/rustix/src/mm/mmap.rs
@@ -0,0 +1,231 @@
+//! The `mmap` API.
+//!
+//! # Safety
+//!
+//! `mmap` and related functions manipulate raw pointers and have special
+//! semantics and are wildly unsafe.
+#![allow(unsafe_code)]
+
+use crate::{imp, io};
+use core::ffi::c_void;
+use imp::fd::AsFd;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use imp::mm::types::MlockFlags;
+#[cfg(any(linux_raw, all(libc, target_os = "linux")))]
+pub use imp::mm::types::MremapFlags;
+pub use imp::mm::types::{MapFlags, MprotectFlags, ProtFlags};
+
+/// `mmap(ptr, len, prot, flags, fd, offset)`—Create a file-backed memory
+/// mapping.
+///
+/// For anonymous mappings (`MAP_ANON`/`MAP_ANONYMOUS`), see
+/// [`mmap_anonymous`].
+///
+/// # Safety
+///
+/// Raw pointers and lots of special semantics.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mmap.2.html
+#[inline]
+pub unsafe fn mmap<Fd: AsFd>(
+ ptr: *mut c_void,
+ len: usize,
+ prot: ProtFlags,
+ flags: MapFlags,
+ fd: Fd,
+ offset: u64,
+) -> io::Result<*mut c_void> {
+ imp::mm::syscalls::mmap(ptr, len, prot, flags, fd.as_fd(), offset)
+}
+
+/// `mmap(ptr, len, prot, MAP_ANONYMOUS | flags, -1, 0)`—Create an anonymous
+/// memory mapping.
+///
+/// For file-backed mappings, see [`mmap`].
+///
+/// # Safety
+///
+/// Raw pointers and lots of special semantics.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mmap.2.html
+#[inline]
+#[doc(alias = "mmap")]
+pub unsafe fn mmap_anonymous(
+ ptr: *mut c_void,
+ len: usize,
+ prot: ProtFlags,
+ flags: MapFlags,
+) -> io::Result<*mut c_void> {
+ imp::mm::syscalls::mmap_anonymous(ptr, len, prot, flags)
+}
+
+/// `munmap(ptr, len)`
+///
+/// # Safety
+///
+/// Raw pointers and lots of special semantics.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munmap.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/munmap.2.html
+#[inline]
+pub unsafe fn munmap(ptr: *mut c_void, len: usize) -> io::Result<()> {
+ imp::mm::syscalls::munmap(ptr, len)
+}
+
+/// `mremap(old_address, old_size, new_size, flags)`—Resize, modify,
+/// and/or move a memory mapping.
+///
+/// For moving a mapping to a fixed address (`MREMAP_FIXED`), see
+/// [`mremap_fixed`].
+///
+/// # Safety
+///
+/// Raw pointers and lots of special semantics.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/mremap.2.html
+#[cfg(any(linux_raw, all(libc, target_os = "linux")))]
+#[inline]
+pub unsafe fn mremap(
+ old_address: *mut c_void,
+ old_size: usize,
+ new_size: usize,
+ flags: MremapFlags,
+) -> io::Result<*mut c_void> {
+ imp::mm::syscalls::mremap(old_address, old_size, new_size, flags)
+}
+
+/// `mremap(old_address, old_size, new_size, MREMAP_FIXED | flags)`—Resize,
+/// modify, and/or move a memory mapping to a specific address.
+///
+/// For `mremap` without moving to a specific address, see [`mremap`].
+/// [`mremap_fixed`].
+///
+/// # Safety
+///
+/// Raw pointers and lots of special semantics.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/mremap.2.html
+#[cfg(any(linux_raw, all(libc, target_os = "linux")))]
+#[inline]
+#[doc(alias = "mremap")]
+pub unsafe fn mremap_fixed(
+ old_address: *mut c_void,
+ old_size: usize,
+ new_size: usize,
+ flags: MremapFlags,
+ new_address: *mut c_void,
+) -> io::Result<*mut c_void> {
+ imp::mm::syscalls::mremap_fixed(old_address, old_size, new_size, flags, new_address)
+}
+
+/// `mprotect(ptr, len, flags)`
+///
+/// # Safety
+///
+/// Raw pointers and lots of special semantics.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mprotect.2.html
+#[inline]
+pub unsafe fn mprotect(ptr: *mut c_void, len: usize, flags: MprotectFlags) -> io::Result<()> {
+ imp::mm::syscalls::mprotect(ptr, len, flags)
+}
+
+/// `mlock(ptr, len)`—Lock memory into RAM.
+///
+/// # Safety
+///
+/// This function operates on raw pointers, but it should only be used on
+/// memory which the caller owns. Technically, locking memory shouldn't violate
+/// any invariants, but since unlocking it can violate invariants, this
+/// function is also unsafe for symmetry.
+///
+/// Some implementations implicitly round the memory region out to the nearest
+/// page boundaries, so this function may lock more memory than explicitly
+/// requested if the memory isn't page-aligned.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlock.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/mlock.2.html
+#[inline]
+pub unsafe fn mlock(ptr: *mut c_void, len: usize) -> io::Result<()> {
+ imp::mm::syscalls::mlock(ptr, len)
+}
+
+/// `mlock2(ptr, len, flags)`—Lock memory into RAM, with
+/// flags.
+///
+/// `mlock_with` is the same as [`mlock`] but adds an additional flags operand.
+///
+/// # Safety
+///
+/// This function operates on raw pointers, but it should only be used on
+/// memory which the caller owns. Technically, locking memory shouldn't violate
+/// any invariants, but since unlocking it can violate invariants, this
+/// function is also unsafe for symmetry.
+///
+/// Some implementations implicitly round the memory region out to the nearest
+/// page boundaries, so this function may lock more memory than explicitly
+/// requested if the memory isn't page-aligned.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/mlock2.2.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[doc(alias = "mlock2")]
+pub unsafe fn mlock_with(ptr: *mut c_void, len: usize, flags: MlockFlags) -> io::Result<()> {
+ imp::mm::syscalls::mlock_with(ptr, len, flags)
+}
+
+/// `munlock(ptr, len)`—Unlock memory.
+///
+/// # Safety
+///
+/// This function operates on raw pointers, but it should only be used on
+/// memory which the caller owns, to avoid compromising the `mlock` invariants
+/// of other unrelated code in the process.
+///
+/// Some implementations implicitly round the memory region out to the nearest
+/// page boundaries, so this function may unlock more memory than explicitly
+/// requested if the memory isn't page-aligned.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munlock.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/munlock.2.html
+#[inline]
+pub unsafe fn munlock(ptr: *mut c_void, len: usize) -> io::Result<()> {
+ imp::mm::syscalls::munlock(ptr, len)
+}
diff --git a/vendor/rustix/src/mm/mod.rs b/vendor/rustix/src/mm/mod.rs
new file mode 100644
index 000000000..9fabea87f
--- /dev/null
+++ b/vendor/rustix/src/mm/mod.rs
@@ -0,0 +1,21 @@
+//! Memory map operations.
+
+#[cfg(not(target_os = "redox"))]
+mod madvise;
+mod mmap;
+mod msync;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod userfaultfd;
+
+#[cfg(not(target_os = "redox"))]
+pub use madvise::{madvise, Advice};
+pub use mmap::{
+ mlock, mmap, mmap_anonymous, mprotect, munlock, munmap, MapFlags, MprotectFlags, ProtFlags,
+};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use mmap::{mlock_with, MlockFlags};
+#[cfg(any(linux_raw, all(libc, target_os = "linux")))]
+pub use mmap::{mremap, mremap_fixed, MremapFlags};
+pub use msync::{msync, MsyncFlags};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use userfaultfd::{userfaultfd, UserfaultfdFlags};
diff --git a/vendor/rustix/src/mm/msync.rs b/vendor/rustix/src/mm/msync.rs
new file mode 100644
index 000000000..7117a5067
--- /dev/null
+++ b/vendor/rustix/src/mm/msync.rs
@@ -0,0 +1,32 @@
+//! The `msync` function.
+//!
+//! # Safety
+//!
+//! `msync` operates on a raw pointer. Some forms of `msync` may mutate the
+//! memory or have other side effects.
+#![allow(unsafe_code)]
+
+use crate::{imp, io};
+use core::ffi::c_void;
+
+pub use imp::mm::types::MsyncFlags;
+
+/// `msync(addr, len, flags)`—Synchronizes a memory-mapping with its backing
+/// storage.
+///
+/// # Safety
+///
+/// `addr` must be a valid pointer to memory that is appropriate to
+/// call `msync` on. Some forms of `msync` may mutate the memory
+/// or evoke a variety of side-effects on the mapping and/or the file.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux `msync`]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/msync.html
+/// [Linux `msync`]: https://man7.org/linux/man-pages/man2/msync.2.html
+#[inline]
+pub unsafe fn msync(addr: *mut c_void, len: usize, flags: MsyncFlags) -> io::Result<()> {
+ imp::mm::syscalls::msync(addr, len, flags)
+}
diff --git a/vendor/rustix/src/mm/userfaultfd.rs b/vendor/rustix/src/mm/userfaultfd.rs
new file mode 100644
index 000000000..65b4a0dd8
--- /dev/null
+++ b/vendor/rustix/src/mm/userfaultfd.rs
@@ -0,0 +1,30 @@
+//! The Linux `userfaultfd` API.
+//!
+//! # Safety
+//!
+//! Calling `userfaultfd` is safe, but the returned file descriptor lets users
+//! observe and manipulate process memory in magical ways.
+#![allow(unsafe_code)]
+
+use crate::imp;
+use crate::io::{self, OwnedFd};
+
+pub use imp::mm::types::UserfaultfdFlags;
+
+/// `userfaultfd(flags)`
+///
+/// # Safety
+///
+/// The call itself is safe, but the returned file descriptor lets users
+/// observe and manipulate process memory in magical ways.
+///
+/// # References
+/// - [Linux]
+/// - [Linux userfaultfd]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/userfaultfd.2.html
+/// [Linux userfaultfd]: https://www.kernel.org/doc/Documentation/vm/userfaultfd.txt
+#[inline]
+pub unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> {
+ imp::mm::syscalls::userfaultfd(flags)
+}
diff --git a/vendor/rustix/src/net/addr.rs b/vendor/rustix/src/net/addr.rs
new file mode 100644
index 000000000..59f4a55d7
--- /dev/null
+++ b/vendor/rustix/src/net/addr.rs
@@ -0,0 +1,759 @@
+//! The following is derived from Rust's
+//! library/std/src/net/addr.rs at revision
+//! dca3f1b786efd27be3b325ed1e01e247aa589c3b.
+//!
+//! This defines `SocketAddr`, `SocketAddrV4`, and `SocketAddrV6`. These are
+//! conceptually platform-independent, however in practice OS's have differing
+//! representations.
+
+#![allow(unsafe_code)]
+
+use crate::imp::c;
+use crate::imp::net::ext::{
+ in6_addr_s6_addr, in_addr_s_addr, sockaddr_in6_new, sockaddr_in6_sin6_scope_id,
+ sockaddr_in6_sin6_scope_id_mut,
+};
+use crate::net::ip::{IpAddr, Ipv4Addr, Ipv6Addr};
+use core::cmp::Ordering;
+use core::hash;
+use core::mem;
+
+/// An internet socket address, either IPv4 or IPv6.
+///
+/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
+/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
+/// [`SocketAddrV6`]'s respective documentation for more details.
+///
+/// The size of a `SocketAddr` instance may vary depending on the target operating
+/// system.
+///
+/// [IP address]: IpAddr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+///
+/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.port(), 8080);
+/// assert_eq!(socket.is_ipv4(), true);
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub enum SocketAddr {
+ /// An IPv4 socket address.
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ V4(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] SocketAddrV4),
+ /// An IPv6 socket address.
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ V6(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] SocketAddrV6),
+}
+
+/// An IPv4 socket address.
+///
+/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as
+/// stated in [IETF RFC 793].
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// The size of a `SocketAddrV4` struct may vary depending on the target operating
+/// system. Do not assume that this type has the same memory layout as the underlying
+/// system representation.
+///
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [`IPv4` address]: Ipv4Addr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv4Addr, SocketAddrV4};
+///
+/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
+#[derive(Copy)]
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub struct SocketAddrV4 {
+ // Do not assume that this struct is implemented as the underlying system representation.
+ // The memory layout is not part of the stable interface that std exposes.
+ pub(crate) inner: c::sockaddr_in,
+}
+
+/// An IPv6 socket address.
+///
+/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well
+/// as fields containing the traffic class, the flow label, and a scope identifier
+/// (see [IETF RFC 2553, Section 3.3] for more details).
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// The size of a `SocketAddrV6` struct may vary depending on the target operating
+/// system. Do not assume that this type has the same memory layout as the underlying
+/// system representation.
+///
+/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+/// [`IPv6` address]: Ipv6Addr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv6Addr, SocketAddrV6};
+///
+/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+///
+/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
+#[derive(Copy)]
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub struct SocketAddrV6 {
+ // Do not assume that this struct is implemented as the underlying system representation.
+ // The memory layout is not part of the stable interface that std exposes.
+ pub(crate) inner: c::sockaddr_in6,
+}
+
+impl SocketAddr {
+ /// Creates a new socket address from an [IP address] and a port number.
+ ///
+ /// [IP address]: IpAddr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))]
+ #[must_use]
+ pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
+ match ip {
+ IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
+ IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
+ }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+ /// ```
+ #[cfg(const_raw_ptr_deref)]
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn ip(&self) -> IpAddr {
+ match *self {
+ SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
+ SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
+ }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+ /// ```
+ #[cfg(not(const_raw_ptr_deref))]
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub fn ip(&self) -> IpAddr {
+ match *self {
+ SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
+ SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
+ }
+ }
+
+ /// Changes the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
+ /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))]
+ pub fn set_ip(&mut self, new_ip: IpAddr) {
+ // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
+ match (self, new_ip) {
+ (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip),
+ (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip),
+ (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()),
+ }
+ }
+
+ /// Returns the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn port(&self) -> u16 {
+ match *self {
+ SocketAddr::V4(ref a) => a.port(),
+ SocketAddr::V6(ref a) => a.port(),
+ }
+ }
+
+ /// Changes the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// socket.set_port(1025);
+ /// assert_eq!(socket.port(), 1025);
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))]
+ pub fn set_port(&mut self, new_port: u16) {
+ match *self {
+ SocketAddr::V4(ref mut a) => a.set_port(new_port),
+ SocketAddr::V6(ref mut a) => a.set_port(new_port),
+ }
+ }
+
+ /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+ /// [`IPv4` address], and [`false`] otherwise.
+ ///
+ /// [IP address]: IpAddr
+ /// [`IPv4` address]: IpAddr::V4
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.is_ipv4(), true);
+ /// assert_eq!(socket.is_ipv6(), false);
+ /// ```
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_checker", since = "1.16.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn is_ipv4(&self) -> bool {
+ matches!(*self, SocketAddr::V4(_))
+ }
+
+ /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+ /// [`IPv6` address], and [`false`] otherwise.
+ ///
+ /// [IP address]: IpAddr
+ /// [`IPv6` address]: IpAddr::V6
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080);
+ /// assert_eq!(socket.is_ipv4(), false);
+ /// assert_eq!(socket.is_ipv6(), true);
+ /// ```
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_checker", since = "1.16.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn is_ipv6(&self) -> bool {
+ matches!(*self, SocketAddr::V6(_))
+ }
+}
+
+impl SocketAddrV4 {
+ /// Creates a new socket address from an [`IPv4` address] and a port number.
+ ///
+ /// [`IPv4` address]: Ipv4Addr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use]
+ pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
+ SocketAddrV4 {
+ inner: c::sockaddr_in {
+ sin_family: c::AF_INET as c::sa_family_t,
+ sin_port: port.to_be(),
+ sin_addr: ip.inner,
+ ..unsafe { mem::zeroed() }
+ },
+ }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+ /// ```
+ #[cfg(const_raw_ptr_deref)]
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn ip(&self) -> &Ipv4Addr {
+ // SAFETY: `Ipv4Addr` is `#[repr(C)] struct { _: in_addr; }`.
+ // It is safe to cast from `&in_addr` to `&Ipv4Addr`.
+ unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+ /// ```
+ #[cfg(not(const_raw_ptr_deref))]
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub fn ip(&self) -> &Ipv4Addr {
+ // SAFETY: `Ipv4Addr` is `#[repr(C)] struct { _: in_addr; }`.
+ // It is safe to cast from `&in_addr` to `&Ipv4Addr`.
+ unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) }
+ }
+
+ /// Changes the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1));
+ /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1));
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))]
+ pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
+ self.inner.sin_addr = new_ip.inner
+ }
+
+ /// Returns the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn port(&self) -> u16 {
+ u16::from_be(self.inner.sin_port)
+ }
+
+ /// Changes the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// socket.set_port(4242);
+ /// assert_eq!(socket.port(), 4242);
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))]
+ pub fn set_port(&mut self, new_port: u16) {
+ self.inner.sin_port = new_port.to_be();
+ }
+}
+
+impl SocketAddrV6 {
+ /// Creates a new socket address from an [`IPv6` address], a 16-bit port number,
+ /// and the `flowinfo` and `scope_id` fields.
+ ///
+ /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
+ /// parameters, see [IETF RFC 2553, Section 3.3].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+ /// [`IPv6` address]: Ipv6Addr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use]
+ pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
+ SocketAddrV6 {
+ inner: sockaddr_in6_new(
+ c::AF_INET6 as c::sa_family_t,
+ port.to_be(),
+ flowinfo,
+ ip.inner,
+ scope_id,
+ ),
+ }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+ /// ```
+ #[cfg(const_raw_ptr_deref)]
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn ip(&self) -> &Ipv6Addr {
+ unsafe { &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+ /// ```
+ #[cfg(not(const_raw_ptr_deref))]
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub fn ip(&self) -> &Ipv6Addr {
+ unsafe { &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) }
+ }
+
+ /// Changes the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
+ /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))]
+ pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
+ self.inner.sin6_addr = new_ip.inner
+ }
+
+ /// Returns the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn port(&self) -> u16 {
+ u16::from_be(self.inner.sin6_port)
+ }
+
+ /// Changes the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// socket.set_port(4242);
+ /// assert_eq!(socket.port(), 4242);
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))]
+ pub fn set_port(&mut self, new_port: u16) {
+ self.inner.sin6_port = new_port.to_be();
+ }
+
+ /// Returns the flow information associated with this address.
+ ///
+ /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`,
+ /// as specified in [IETF RFC 2553, Section 3.3].
+ /// It combines information about the flow label and the traffic class as specified
+ /// in [IETF RFC 2460], respectively [Section 6] and [Section 7].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+ /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460
+ /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6
+ /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
+ /// assert_eq!(socket.flowinfo(), 10);
+ /// ```
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn flowinfo(&self) -> u32 {
+ self.inner.sin6_flowinfo
+ }
+
+ /// Changes the flow information associated with this socket address.
+ ///
+ /// See [`SocketAddrV6::flowinfo`]'s documentation for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
+ /// socket.set_flowinfo(56);
+ /// assert_eq!(socket.flowinfo(), 56);
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))]
+ pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
+ self.inner.sin6_flowinfo = new_flowinfo;
+ }
+
+ /// Returns the scope ID associated with this address.
+ ///
+ /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`,
+ /// as specified in [IETF RFC 2553, Section 3.3].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
+ /// assert_eq!(socket.scope_id(), 78);
+ /// ```
+ #[must_use]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_socketaddr", issue = "82485")
+ )]
+ pub const fn scope_id(&self) -> u32 {
+ sockaddr_in6_sin6_scope_id(self.inner)
+ }
+
+ /// Changes the scope ID associated with this socket address.
+ ///
+ /// See [`SocketAddrV6::scope_id`]'s documentation for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
+ /// socket.set_scope_id(42);
+ /// assert_eq!(socket.scope_id(), 42);
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))]
+ pub fn set_scope_id(&mut self, new_scope_id: u32) {
+ *sockaddr_in6_sin6_scope_id_mut(&mut self.inner) = new_scope_id;
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))]
+impl From<SocketAddrV4> for SocketAddr {
+ /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
+ fn from(sock4: SocketAddrV4) -> SocketAddr {
+ SocketAddr::V4(sock4)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))]
+impl From<SocketAddrV6> for SocketAddr {
+ /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
+ fn from(sock6: SocketAddrV6) -> SocketAddr {
+ SocketAddr::V6(sock6)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "addr_from_into_ip", since = "1.17.0"))]
+impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
+ /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
+ ///
+ /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`]
+ /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`].
+ ///
+ /// `u16` is treated as port of the newly created [`SocketAddr`].
+ fn from(pieces: (I, u16)) -> SocketAddr {
+ SocketAddr::new(pieces.0.into(), pieces.1)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Clone for SocketAddrV4 {
+ fn clone(&self) -> SocketAddrV4 {
+ *self
+ }
+}
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Clone for SocketAddrV6 {
+ fn clone(&self) -> SocketAddrV6 {
+ *self
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl PartialEq for SocketAddrV4 {
+ fn eq(&self, other: &SocketAddrV4) -> bool {
+ self.inner.sin_port == other.inner.sin_port
+ && in_addr_s_addr(self.inner.sin_addr) == in_addr_s_addr(other.inner.sin_addr)
+ }
+}
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl PartialEq for SocketAddrV6 {
+ fn eq(&self, other: &SocketAddrV6) -> bool {
+ self.inner.sin6_port == other.inner.sin6_port
+ && in6_addr_s6_addr(self.inner.sin6_addr) == in6_addr_s6_addr(self.inner.sin6_addr)
+ && self.inner.sin6_flowinfo == other.inner.sin6_flowinfo
+ && sockaddr_in6_sin6_scope_id(self.inner) == sockaddr_in6_sin6_scope_id(other.inner)
+ }
+}
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Eq for SocketAddrV4 {}
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Eq for SocketAddrV6 {}
+
+#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))]
+impl PartialOrd for SocketAddrV4 {
+ fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))]
+impl PartialOrd for SocketAddrV6 {
+ fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))]
+impl Ord for SocketAddrV4 {
+ fn cmp(&self, other: &SocketAddrV4) -> Ordering {
+ self.ip()
+ .cmp(other.ip())
+ .then(self.port().cmp(&other.port()))
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))]
+impl Ord for SocketAddrV6 {
+ fn cmp(&self, other: &SocketAddrV6) -> Ordering {
+ self.ip()
+ .cmp(other.ip())
+ .then(self.port().cmp(&other.port()))
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl hash::Hash for SocketAddrV4 {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ (self.inner.sin_port, in_addr_s_addr(self.inner.sin_addr)).hash(s)
+ }
+}
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl hash::Hash for SocketAddrV6 {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ (
+ self.inner.sin6_port,
+ &in6_addr_s6_addr(self.inner.sin6_addr),
+ self.inner.sin6_flowinfo,
+ sockaddr_in6_sin6_scope_id(self.inner),
+ )
+ .hash(s)
+ }
+}
diff --git a/vendor/rustix/src/net/ip.rs b/vendor/rustix/src/net/ip.rs
new file mode 100644
index 000000000..7c587cc7a
--- /dev/null
+++ b/vendor/rustix/src/net/ip.rs
@@ -0,0 +1,2059 @@
+//! The following is derived from Rust's
+//! library/std/src/net/ip.rs at revision
+//! dca3f1b786efd27be3b325ed1e01e247aa589c3b.
+//!
+//! This defines `IpAddr`, `Ipv4Addr`, and `Ipv6Addr`. Ideally, these should be
+//! defined in `core`. See [RFC 2832].
+//!
+//! [RFC 2832]: https://github.com/rust-lang/rfcs/pull/2832
+
+#![allow(unsafe_code)]
+
+use crate::imp::c;
+use crate::imp::net::ext::{in6_addr_new, in6_addr_s6_addr, in_addr_new, in_addr_s_addr};
+use core::cmp::Ordering;
+use core::hash;
+use core::mem::transmute;
+
+/// An IP address, either IPv4 or IPv6.
+///
+/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
+/// respective documentation for more details.
+///
+/// The size of an `IpAddr` instance may vary depending on the target operating
+/// system.
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+///
+/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
+/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+///
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
+/// assert_eq!("::1".parse(), Ok(localhost_v6));
+///
+/// assert_eq!(localhost_v4.is_ipv6(), false);
+/// assert_eq!(localhost_v4.is_ipv4(), true);
+/// ```
+#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
+pub enum IpAddr {
+ /// An IPv4 address.
+ #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))]
+ V4(#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] Ipv4Addr),
+ /// An IPv6 address.
+ #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))]
+ V6(#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] Ipv6Addr),
+}
+
+/// An IPv4 address.
+///
+/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
+/// They are usually represented as four octets.
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// The size of an `Ipv4Addr` struct may vary depending on the target operating
+/// system.
+///
+/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
+///
+/// # Textual representation
+///
+/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
+/// notation, divided by `.` (this is called "dot-decimal notation").
+/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which
+/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943].
+///
+/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1
+/// [`FromStr`]: core::str::FromStr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv4Addr;
+///
+/// let localhost = Ipv4Addr::new(127, 0, 0, 1);
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// assert!("012.004.002.000".parse::<Ipv4Addr>().is_err()); // all octets are in octal
+/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
+/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
+/// ```
+#[derive(Copy)]
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub struct Ipv4Addr {
+ pub(crate) inner: c::in_addr,
+}
+
+/// An IPv6 address.
+///
+/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
+/// They are usually represented as eight 16-bit segments.
+///
+/// The size of an `Ipv6Addr` struct may vary depending on the target operating
+/// system.
+///
+/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+///
+/// # Embedding IPv4 Addresses
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined:
+/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated.
+///
+/// Both types of addresses are not assigned any special meaning by this implementation,
+/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`,
+/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is.
+/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address.
+///
+/// ### IPv4-Compatible IPv6 Addresses
+///
+/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated.
+/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows:
+///
+/// ```text
+/// | 80 bits | 16 | 32 bits |
+/// +--------------------------------------+--------------------------+
+/// |0000..............................0000|0000| IPv4 address |
+/// +--------------------------------------+----+---------------------+
+/// ```
+/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`.
+///
+/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`].
+/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address.
+///
+/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1
+///
+/// ### IPv4-Mapped IPv6 Addresses
+///
+/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2].
+/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows:
+///
+/// ```text
+/// | 80 bits | 16 | 32 bits |
+/// +--------------------------------------+--------------------------+
+/// |0000..............................0000|FFFF| IPv4 address |
+/// +--------------------------------------+----+---------------------+
+/// ```
+/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`.
+///
+/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`].
+/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address.
+///
+/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2
+///
+/// # Textual representation
+///
+/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
+/// an IPv6 address in text, but in general, each segments is written in hexadecimal
+/// notation, and segments are separated by `:`. For more information, see
+/// [IETF RFC 5952].
+///
+/// [`FromStr`]: core::str::FromStr
+/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv6Addr;
+///
+/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+/// assert_eq!("::1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// ```
+#[derive(Copy)]
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+pub struct Ipv6Addr {
+ pub(crate) inner: c::in6_addr,
+}
+
+/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
+///
+/// # Stability Guarantees
+///
+/// Not all possible values for a multicast scope have been assigned.
+/// Future RFCs may introduce new scopes, which will be added as variants to this enum;
+/// because of this the enum is marked as `#[non_exhaustive]`.
+///
+/// # Examples
+/// ```
+/// #![feature(ip)]
+///
+/// use std::net::Ipv6Addr;
+/// use std::net::Ipv6MulticastScope::*;
+///
+/// // An IPv6 multicast address with global scope (`ff0e::`).
+/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0);
+///
+/// // Will print "Global scope".
+/// match address.multicast_scope() {
+/// Some(InterfaceLocal) => println!("Interface-Local scope"),
+/// Some(LinkLocal) => println!("Link-Local scope"),
+/// Some(RealmLocal) => println!("Realm-Local scope"),
+/// Some(AdminLocal) => println!("Admin-Local scope"),
+/// Some(SiteLocal) => println!("Site-Local scope"),
+/// Some(OrganizationLocal) => println!("Organization-Local scope"),
+/// Some(Global) => println!("Global scope"),
+/// Some(_) => println!("Unknown scope"),
+/// None => println!("Not a multicast address!")
+/// }
+///
+/// ```
+///
+/// [IPv6 multicast address]: Ipv6Addr
+/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2
+#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
+#[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+#[non_exhaustive]
+pub enum Ipv6MulticastScope {
+ /// Interface-Local scope.
+ InterfaceLocal,
+ /// Link-Local scope.
+ LinkLocal,
+ /// Realm-Local scope.
+ RealmLocal,
+ /// Admin-Local scope.
+ AdminLocal,
+ /// Site-Local scope.
+ SiteLocal,
+ /// Organization-Local scope.
+ OrganizationLocal,
+ /// Global scope.
+ Global,
+}
+
+impl IpAddr {
+ /// Returns [`true`] for the special 'unspecified' address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
+ /// [`Ipv6Addr::is_unspecified()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
+ /// ```
+ #[cfg_attr(staged_api, rustc_const_stable(feature = "const_ip", since = "1.50.0"))]
+ #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_unspecified(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_unspecified(),
+ IpAddr::V6(ip) => ip.is_unspecified(),
+ }
+ }
+
+ /// Returns [`true`] if this is a loopback address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_loopback()`] and
+ /// [`Ipv6Addr::is_loopback()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
+ /// ```
+ #[cfg_attr(staged_api, rustc_const_stable(feature = "const_ip", since = "1.50.0"))]
+ #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_loopback(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_loopback(),
+ IpAddr::V6(ip) => ip.is_loopback(),
+ }
+ }
+
+ /// Returns [`true`] if the address appears to be globally routable.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_global()`] and
+ /// [`Ipv6Addr::is_global()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ip", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_global(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_global(),
+ IpAddr::V6(ip) => ip.is_global(),
+ }
+ }
+
+ /// Returns [`true`] if this is a multicast address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_multicast()`] and
+ /// [`Ipv6Addr::is_multicast()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
+ /// ```
+ #[cfg_attr(staged_api, rustc_const_stable(feature = "const_ip", since = "1.50.0"))]
+ #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_multicast(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_multicast(),
+ IpAddr::V6(ip) => ip.is_multicast(),
+ }
+ }
+
+ /// Returns [`true`] if this address is in a range designated for documentation.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_documentation()`] and
+ /// [`Ipv6Addr::is_documentation()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
+ /// assert_eq!(
+ /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(),
+ /// true
+ /// );
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ip", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_documentation(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_documentation(),
+ IpAddr::V6(ip) => ip.is_documentation(),
+ }
+ }
+
+ /// Returns [`true`] if this address is in a range designated for benchmarking.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and
+ /// [`Ipv6Addr::is_benchmarking()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true);
+ /// ```
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_benchmarking(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_benchmarking(),
+ IpAddr::V6(ip) => ip.is_benchmarking(),
+ }
+ }
+
+ /// Returns [`true`] if this address is an [`IPv4` address], and [`false`]
+ /// otherwise.
+ ///
+ /// [`IPv4` address]: IpAddr::V4
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
+ /// ```
+ #[cfg_attr(staged_api, rustc_const_stable(feature = "const_ip", since = "1.50.0"))]
+ #[cfg_attr(staged_api, stable(feature = "ipaddr_checker", since = "1.16.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_ipv4(&self) -> bool {
+ matches!(self, IpAddr::V4(_))
+ }
+
+ /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
+ /// otherwise.
+ ///
+ /// [`IPv6` address]: IpAddr::V6
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
+ /// ```
+ #[cfg_attr(staged_api, rustc_const_stable(feature = "const_ip", since = "1.50.0"))]
+ #[cfg_attr(staged_api, stable(feature = "ipaddr_checker", since = "1.16.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_ipv6(&self) -> bool {
+ matches!(self, IpAddr::V6(_))
+ }
+
+ /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it
+ /// return `self` as-is.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true);
+ /// ```
+ #[inline]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ip", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ pub const fn to_canonical(&self) -> IpAddr {
+ match self {
+ &v4 @ IpAddr::V4(_) => v4,
+ IpAddr::V6(v6) => v6.to_canonical(),
+ }
+ }
+}
+
+impl Ipv4Addr {
+ /// Creates a new IPv4 address from four eight-bit octets.
+ ///
+ /// The result will represent the IP address `a`.`b`.`c`.`d`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.32.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
+ // `s_addr` is stored as BE on all machine and the array is in BE order.
+ // So the native endian conversion method is used so that it's never swapped.
+ Ipv4Addr {
+ inner: in_addr_new(u32::from_ne_bytes([a, b, c, d])),
+ }
+ }
+
+ /// An IPv4 address with the address pointing to localhost: `127.0.0.1`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::LOCALHOST;
+ /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))]
+ pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
+
+ /// An IPv4 address representing an unspecified address: `0.0.0.0`
+ ///
+ /// This corresponds to the constant `INADDR_ANY` in other languages.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::UNSPECIFIED;
+ /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
+ /// ```
+ #[doc(alias = "INADDR_ANY")]
+ #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))]
+ pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
+
+ /// An IPv4 address representing the broadcast address: `255.255.255.255`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::BROADCAST;
+ /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))]
+ pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
+
+ /// Returns the four eight-bit integers that make up this address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+ /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn octets(&self) -> [u8; 4] {
+ // This returns the order we want because s_addr is stored in big-endian.
+ in_addr_s_addr(self.inner).to_ne_bytes()
+ }
+
+ /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
+ ///
+ /// This property is defined in _UNIX Network Programming, Second Edition_,
+ /// W. Richard Stevens, p. 891; see also [ip7].
+ ///
+ /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
+ /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.32.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_unspecified(&self) -> bool {
+ in_addr_s_addr(self.inner) == 0
+ }
+
+ /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`).
+ ///
+ /// This property is defined by [IETF RFC 1122].
+ ///
+ /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
+ /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_loopback(&self) -> bool {
+ self.octets()[0] == 127
+ }
+
+ /// Returns [`true`] if this is a private address.
+ ///
+ /// The private address ranges are defined in [IETF RFC 1918] and include:
+ ///
+ /// - `10.0.0.0/8`
+ /// - `172.16.0.0/12`
+ /// - `192.168.0.0/16`
+ ///
+ /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
+ /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_private(&self) -> bool {
+ match self.octets() {
+ [10, ..] => true,
+ [172, b, ..] if b >= 16 && b <= 31 => true,
+ [192, 168, ..] => true,
+ _ => false,
+ }
+ }
+
+ /// Returns [`true`] if the address is link-local (`169.254.0.0/16`).
+ ///
+ /// This property is defined by [IETF RFC 3927].
+ ///
+ /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
+ /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
+ /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_link_local(&self) -> bool {
+ matches!(self.octets(), [169, 254, ..])
+ }
+
+ /// Returns [`true`] if the address appears to be globally routable.
+ /// See [iana-ipv4-special-registry][ipv4-sr].
+ ///
+ /// The following return [`false`]:
+ ///
+ /// - private addresses (see [`Ipv4Addr::is_private()`])
+ /// - the loopback address (see [`Ipv4Addr::is_loopback()`])
+ /// - the link-local address (see [`Ipv4Addr::is_link_local()`])
+ /// - the broadcast address (see [`Ipv4Addr::is_broadcast()`])
+ /// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`])
+ /// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole
+ /// `0.0.0.0/8` block
+ /// - addresses reserved for future protocols, except
+ /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
+ /// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`]
+ /// - addresses reserved for networking devices benchmarking (see
+ /// [`Ipv4Addr::is_benchmarking()`])
+ ///
+ /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv4Addr;
+ ///
+ /// // private addresses are not global
+ /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
+ ///
+ /// // the 0.0.0.0/8 block is not global
+ /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
+ /// // in particular, the unspecified address is not global
+ /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
+ ///
+ /// // the loopback address is not global
+ /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
+ ///
+ /// // link local addresses are not global
+ /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
+ ///
+ /// // the broadcast address is not global
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
+ ///
+ /// // the address space designated for documentation is not global
+ /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
+ ///
+ /// // shared addresses are not global
+ /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
+ ///
+ /// // addresses reserved for protocol assignment are not global
+ /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
+ ///
+ /// // addresses reserved for future use are not global
+ /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
+ ///
+ /// // addresses reserved for network devices benchmarking are not global
+ /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
+ ///
+ /// // All the other addresses are global
+ /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
+ /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv4", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_global(&self) -> bool {
+ // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
+ // globally routable addresses in the 192.0.0.0/24 range.
+ if u32::from_be_bytes(self.octets()) == 0xc0000009
+ || u32::from_be_bytes(self.octets()) == 0xc000000a
+ {
+ return true;
+ }
+ !self.is_private()
+ && !self.is_loopback()
+ && !self.is_link_local()
+ && !self.is_broadcast()
+ && !self.is_documentation()
+ && !self.is_shared()
+ // addresses reserved for future protocols (`192.0.0.0/24`)
+ && !(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
+ && !self.is_reserved()
+ && !self.is_benchmarking()
+ // Make sure the address is not in 0.0.0.0/8
+ && self.octets()[0] != 0
+ }
+
+ /// Returns [`true`] if this address is part of the Shared Address Space defined in
+ /// [IETF RFC 6598] (`100.64.0.0/10`).
+ ///
+ /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
+ /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
+ /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv4", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_shared(&self) -> bool {
+ self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
+ }
+
+ /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
+ /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
+ /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
+ ///
+ /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
+ /// [errata 423]: https://www.rfc-editor.org/errata/eid423
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
+ /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
+ /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
+ /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv4", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_benchmarking(&self) -> bool {
+ self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
+ }
+
+ /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
+ /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
+ /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
+ /// it is obviously not reserved for future use.
+ ///
+ /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+ ///
+ /// # Warning
+ ///
+ /// As IANA assigns new addresses, this method will be
+ /// updated. This may result in non-reserved addresses being
+ /// treated as reserved in code that relies on an outdated version
+ /// of this method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
+ ///
+ /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
+ /// // The broadcast address is not considered as reserved for future use by this implementation
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv4", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_reserved(&self) -> bool {
+ self.octets()[0] & 240 == 240 && !self.is_broadcast()
+ }
+
+ /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`).
+ ///
+ /// Multicast addresses have a most significant octet between `224` and `239`,
+ /// and is defined by [IETF RFC 5771].
+ ///
+ /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
+ /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
+ /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_multicast(&self) -> bool {
+ self.octets()[0] >= 224 && self.octets()[0] <= 239
+ }
+
+ /// Returns [`true`] if this is a broadcast address (`255.255.255.255`).
+ ///
+ /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919].
+ ///
+ /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
+ /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_broadcast(&self) -> bool {
+ u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
+ }
+
+ /// Returns [`true`] if this address is in a range designated for documentation.
+ ///
+ /// This is defined in [IETF RFC 5737]:
+ ///
+ /// - `192.0.2.0/24` (TEST-NET-1)
+ /// - `198.51.100.0/24` (TEST-NET-2)
+ /// - `203.0.113.0/24` (TEST-NET-3)
+ ///
+ /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
+ /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
+ /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
+ /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_documentation(&self) -> bool {
+ match self.octets() {
+ [192, 0, 2, _] => true,
+ [198, 51, 100, _] => true,
+ [203, 0, 113, _] => true,
+ _ => false,
+ }
+ }
+
+ /// Converts this address to an [IPv4-compatible] [`IPv6` address].
+ ///
+ /// `a.b.c.d` becomes `::a.b.c.d`
+ ///
+ /// Note that IPv4-compatible addresses have been officially deprecated.
+ /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead.
+ ///
+ /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
+ /// [`IPv6` address]: Ipv6Addr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(
+ /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
+ /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff)
+ /// );
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr {
+ inner: in6_addr_new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d]),
+ }
+ }
+
+ /// Converts this address to an [IPv4-mapped] [`IPv6` address].
+ ///
+ /// `a.b.c.d` becomes `::ffff:a.b.c.d`
+ ///
+ /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
+ /// [`IPv6` address]: Ipv6Addr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
+ /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff));
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv4", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr {
+ inner: in6_addr_new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d]),
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))]
+impl From<Ipv4Addr> for IpAddr {
+ /// Copies this address to a new `IpAddr::V4`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr};
+ ///
+ /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+ ///
+ /// assert_eq!(
+ /// IpAddr::V4(addr),
+ /// IpAddr::from(addr)
+ /// )
+ /// ```
+ #[inline]
+ fn from(ipv4: Ipv4Addr) -> IpAddr {
+ IpAddr::V4(ipv4)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))]
+impl From<Ipv6Addr> for IpAddr {
+ /// Copies this address to a new `IpAddr::V6`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr};
+ ///
+ /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
+ ///
+ /// assert_eq!(
+ /// IpAddr::V6(addr),
+ /// IpAddr::from(addr)
+ /// );
+ /// ```
+ #[inline]
+ fn from(ipv6: Ipv6Addr) -> IpAddr {
+ IpAddr::V6(ipv6)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Clone for Ipv4Addr {
+ #[inline]
+ fn clone(&self) -> Ipv4Addr {
+ *self
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl PartialEq for Ipv4Addr {
+ #[inline]
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ in_addr_s_addr(self.inner) == in_addr_s_addr(other.inner)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))]
+impl PartialEq<Ipv4Addr> for IpAddr {
+ #[inline]
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ match self {
+ IpAddr::V4(v4) => v4 == other,
+ IpAddr::V6(_) => false,
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))]
+impl PartialEq<IpAddr> for Ipv4Addr {
+ #[inline]
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other {
+ IpAddr::V4(v4) => self == v4,
+ IpAddr::V6(_) => false,
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Eq for Ipv4Addr {}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl hash::Hash for Ipv4Addr {
+ #[inline]
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ // NOTE:
+ // * hash in big endian order
+ // * in netbsd, `in_addr` has `repr(packed)`, we need to
+ // copy `s_addr` to avoid unsafe borrowing
+ { in_addr_s_addr(self.inner) }.hash(s)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl PartialOrd for Ipv4Addr {
+ #[inline]
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))]
+impl PartialOrd<Ipv4Addr> for IpAddr {
+ #[inline]
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(v4) => v4.partial_cmp(other),
+ IpAddr::V6(_) => Some(Ordering::Greater),
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))]
+impl PartialOrd<IpAddr> for Ipv4Addr {
+ #[inline]
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(v4) => self.partial_cmp(v4),
+ IpAddr::V6(_) => Some(Ordering::Less),
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Ord for Ipv4Addr {
+ #[inline]
+ fn cmp(&self, other: &Ipv4Addr) -> Ordering {
+ // Compare as native endian
+ u32::from_be(in_addr_s_addr(self.inner)).cmp(&u32::from_be(in_addr_s_addr(other.inner)))
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_u32", since = "1.1.0"))]
+impl From<Ipv4Addr> for u32 {
+ /// Converts an `Ipv4Addr` into a host byte order `u32`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe);
+ /// assert_eq!(0xcafebabe, u32::from(addr));
+ /// ```
+ #[inline]
+ fn from(ip: Ipv4Addr) -> u32 {
+ let ip = ip.octets();
+ u32::from_be_bytes(ip)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_u32", since = "1.1.0"))]
+impl From<u32> for Ipv4Addr {
+ /// Converts a host byte order `u32` into an `Ipv4Addr`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::from(0xcafebabe);
+ /// assert_eq!(Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe), addr);
+ /// ```
+ #[inline]
+ fn from(ip: u32) -> Ipv4Addr {
+ Ipv4Addr::from(ip.to_be_bytes())
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "from_slice_v4", since = "1.9.0"))]
+impl From<[u8; 4]> for Ipv4Addr {
+ /// Creates an `Ipv4Addr` from a four element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
+ /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
+ /// ```
+ #[inline]
+ fn from(octets: [u8; 4]) -> Ipv4Addr {
+ Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))]
+impl From<[u8; 4]> for IpAddr {
+ /// Creates an `IpAddr::V4` from a four element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr};
+ ///
+ /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
+ /// ```
+ #[inline]
+ fn from(octets: [u8; 4]) -> IpAddr {
+ IpAddr::V4(Ipv4Addr::from(octets))
+ }
+}
+
+impl Ipv6Addr {
+ /// Creates a new IPv6 address from eight 16-bit segments.
+ ///
+ /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv6", since = "1.32.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
+ let addr16 = [
+ a.to_be(),
+ b.to_be(),
+ c.to_be(),
+ d.to_be(),
+ e.to_be(),
+ f.to_be(),
+ g.to_be(),
+ h.to_be(),
+ ];
+ Ipv6Addr {
+ // All elements in `addr16` are big endian.
+ // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
+ // rustc_allow_const_fn_unstable: the transmute could be written as stable const
+ // code, but that leads to worse code generation (#75085)
+ inner: in6_addr_new(unsafe { transmute::<_, [u8; 16]>(addr16) }),
+ }
+ }
+
+ /// An IPv6 address representing localhost: `::1`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::LOCALHOST;
+ /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))]
+ pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+
+ /// An IPv6 address representing the unspecified address: `::`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::UNSPECIFIED;
+ /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+ /// ```
+ #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))]
+ pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+
+ /// Returns the eight 16-bit segments that make up this address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
+ /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv6", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn segments(&self) -> [u16; 8] {
+ // All elements in `s6_addr` must be big endian.
+ // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
+ // rustc_allow_const_fn_unstable: the transmute could be written as stable const code, but
+ // that leads to worse code generation (#75085)
+ let [a, b, c, d, e, f, g, h] =
+ unsafe { transmute::<_, [u16; 8]>(in6_addr_s6_addr(self.inner)) };
+ // We want native endian u16
+ [
+ u16::from_be(a),
+ u16::from_be(b),
+ u16::from_be(c),
+ u16::from_be(d),
+ u16::from_be(e),
+ u16::from_be(f),
+ u16::from_be(g),
+ u16::from_be(h),
+ ]
+ }
+
+ /// Returns [`true`] for the special 'unspecified' address (`::`).
+ ///
+ /// This property is defined in [IETF RFC 4291].
+ ///
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv6", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_unspecified(&self) -> bool {
+ u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
+ }
+
+ /// Returns [`true`] if this is the [loopback address] (`::1`),
+ /// as defined in [IETF RFC 4291 section 2.5.3].
+ ///
+ /// Contrary to IPv4, in IPv6 there is only one loopback address.
+ ///
+ /// [loopback address]: Ipv6Addr::LOCALHOST
+ /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv6", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_loopback(&self) -> bool {
+ u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
+ }
+
+ /// Returns [`true`] if the address appears to be globally routable.
+ ///
+ /// The following return [`false`]:
+ ///
+ /// - the loopback address
+ /// - link-local and unique local unicast addresses
+ /// - interface-, link-, realm-, admin- and site-local multicast addresses
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_global(&self) -> bool {
+ match self.multicast_scope() {
+ Some(Ipv6MulticastScope::Global) => true,
+ None => self.is_unicast_global(),
+ _ => false,
+ }
+ }
+
+ /// Returns [`true`] if this is a unique local address (`fc00::/7`).
+ ///
+ /// This property is defined in [IETF RFC 4193].
+ ///
+ /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
+ /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_unique_local(&self) -> bool {
+ (self.segments()[0] & 0xfe00) == 0xfc00
+ }
+
+ /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291].
+ /// Any address that is not a [multicast address] (`ff00::/8`) is unicast.
+ ///
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [multicast address]: Ipv6Addr::is_multicast
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// // The unspecified and loopback addresses are unicast.
+ /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true);
+ /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true);
+ ///
+ /// // Any address that is not a multicast address (`ff00::/8`) is unicast.
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_unicast(&self) -> bool {
+ !self.is_multicast()
+ }
+
+ /// Returns `true` if the address is a unicast address with link-local scope,
+ /// as defined in [RFC 4291].
+ ///
+ /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4].
+ /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6],
+ /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format:
+ ///
+ /// ```text
+ /// | 10 bits | 54 bits | 64 bits |
+ /// +----------+-------------------------+----------------------------+
+ /// |1111111010| 0 | interface ID |
+ /// +----------+-------------------------+----------------------------+
+ /// ```
+ /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`,
+ /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated,
+ /// and those addresses will have link-local scope.
+ ///
+ /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope",
+ /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it.
+ ///
+ /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
+ /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
+ /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
+ /// [loopback address]: Ipv6Addr::LOCALHOST
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// // The loopback address (`::1`) does not actually have link-local scope.
+ /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false);
+ ///
+ /// // Only addresses in `fe80::/10` have link-local scope.
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false);
+ /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+ ///
+ /// // Addresses outside the stricter `fe80::/64` also have link-local scope.
+ /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true);
+ /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_unicast_link_local(&self) -> bool {
+ (self.segments()[0] & 0xffc0) == 0xfe80
+ }
+
+ /// Returns [`true`] if this is an address reserved for documentation
+ /// (`2001:db8::/32`).
+ ///
+ /// This property is defined in [IETF RFC 3849].
+ ///
+ /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_documentation(&self) -> bool {
+ (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
+ }
+
+ /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`).
+ ///
+ /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`.
+ /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`.
+ ///
+ /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180
+ /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false);
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true);
+ /// ```
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_benchmarking(&self) -> bool {
+ (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0)
+ }
+
+ /// Returns [`true`] if the address is a globally routable unicast address.
+ ///
+ /// The following return false:
+ ///
+ /// - the loopback address
+ /// - the link-local addresses
+ /// - unique local addresses
+ /// - the unspecified address
+ /// - the address range reserved for documentation
+ ///
+ /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
+ ///
+ /// ```no_rust
+ /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
+ /// be supported in new implementations (i.e., new implementations must treat this prefix as
+ /// Global Unicast).
+ /// ```
+ ///
+ /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_unicast_global(&self) -> bool {
+ self.is_unicast()
+ && !self.is_loopback()
+ && !self.is_unicast_link_local()
+ && !self.is_unique_local()
+ && !self.is_unspecified()
+ && !self.is_documentation()
+ }
+
+ /// Returns the address's multicast scope if the address is multicast.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
+ ///
+ /// assert_eq!(
+ /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
+ /// Some(Ipv6MulticastScope::Global)
+ /// );
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use]
+ #[inline]
+ pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
+ if self.is_multicast() {
+ match self.segments()[0] & 0x000f {
+ 1 => Some(Ipv6MulticastScope::InterfaceLocal),
+ 2 => Some(Ipv6MulticastScope::LinkLocal),
+ 3 => Some(Ipv6MulticastScope::RealmLocal),
+ 4 => Some(Ipv6MulticastScope::AdminLocal),
+ 5 => Some(Ipv6MulticastScope::SiteLocal),
+ 8 => Some(Ipv6MulticastScope::OrganizationLocal),
+ 14 => Some(Ipv6MulticastScope::Global),
+ _ => None,
+ }
+ } else {
+ None
+ }
+ }
+
+ /// Returns [`true`] if this is a multicast address (`ff00::/8`).
+ ///
+ /// This property is defined by [IETF RFC 4291].
+ ///
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv6", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))]
+ #[must_use]
+ #[inline]
+ pub const fn is_multicast(&self) -> bool {
+ (self.segments()[0] & 0xff00) == 0xff00
+ }
+
+ /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address,
+ /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
+ ///
+ /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
+ /// All addresses *not* starting with `::ffff` will return `None`.
+ ///
+ /// [`IPv4` address]: Ipv4Addr
+ /// [IPv4-mapped]: Ipv6Addr
+ /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::{Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
+ /// Some(Ipv4Addr::new(192, 10, 2, 255)));
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
+ match self.octets() {
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
+ Some(Ipv4Addr::new(a, b, c, d))
+ }
+ _ => None,
+ }
+ }
+
+ /// Converts this address to an [`IPv4` address] if it is either
+ /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1],
+ /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2],
+ /// otherwise returns [`None`].
+ ///
+ /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`
+ /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`.
+ ///
+ /// [`IPv4` address]: Ipv4Addr
+ /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
+ /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
+ /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1
+ /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
+ /// Some(Ipv4Addr::new(192, 10, 2, 255)));
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
+ /// Some(Ipv4Addr::new(0, 0, 0, 1)));
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv6", since = "1.50.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
+ if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
+ let [a, b] = ab.to_be_bytes();
+ let [c, d] = cd.to_be_bytes();
+ Some(Ipv4Addr::new(a, b, c, d))
+ } else {
+ None
+ }
+ }
+
+ /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it
+ /// returns self wrapped in an `IpAddr::V6`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_unstable(feature = "const_ipv6", issue = "76205")
+ )]
+ #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn to_canonical(&self) -> IpAddr {
+ if let Some(mapped) = self.to_ipv4_mapped() {
+ return IpAddr::V4(mapped);
+ }
+ IpAddr::V6(*self)
+ }
+
+ /// Returns the sixteen eight-bit integers the IPv6 address consists of.
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
+ /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+ /// ```
+ #[cfg_attr(
+ staged_api,
+ rustc_const_stable(feature = "const_ipv6", since = "1.32.0")
+ )]
+ #[cfg_attr(staged_api, stable(feature = "ipv6_to_octets", since = "1.12.0"))]
+ #[must_use]
+ #[inline]
+ pub const fn octets(&self) -> [u8; 16] {
+ in6_addr_s6_addr(self.inner)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Clone for Ipv6Addr {
+ #[inline]
+ fn clone(&self) -> Ipv6Addr {
+ *self
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl PartialEq for Ipv6Addr {
+ #[inline]
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ in6_addr_s6_addr(self.inner) == in6_addr_s6_addr(other.inner)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))]
+impl PartialEq<IpAddr> for Ipv6Addr {
+ #[inline]
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other {
+ IpAddr::V4(_) => false,
+ IpAddr::V6(v6) => self == v6,
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))]
+impl PartialEq<Ipv6Addr> for IpAddr {
+ #[inline]
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ match self {
+ IpAddr::V4(_) => false,
+ IpAddr::V6(v6) => v6 == other,
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Eq for Ipv6Addr {}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl hash::Hash for Ipv6Addr {
+ #[inline]
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ in6_addr_s6_addr(self.inner).hash(s)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl PartialOrd for Ipv6Addr {
+ #[inline]
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))]
+impl PartialOrd<Ipv6Addr> for IpAddr {
+ #[inline]
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(_) => Some(Ordering::Less),
+ IpAddr::V6(v6) => v6.partial_cmp(other),
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))]
+impl PartialOrd<IpAddr> for Ipv6Addr {
+ #[inline]
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(_) => Some(Ordering::Greater),
+ IpAddr::V6(v6) => self.partial_cmp(v6),
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
+impl Ord for Ipv6Addr {
+ #[inline]
+ fn cmp(&self, other: &Ipv6Addr) -> Ordering {
+ self.segments().cmp(&other.segments())
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "i128", since = "1.26.0"))]
+impl From<Ipv6Addr> for u128 {
+ /// Convert an `Ipv6Addr` into a host byte order `u128`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::new(
+ /// 0x1020, 0x3040, 0x5060, 0x7080,
+ /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
+ /// );
+ /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
+ /// ```
+ #[inline]
+ fn from(ip: Ipv6Addr) -> u128 {
+ let ip = ip.octets();
+ u128::from_be_bytes(ip)
+ }
+}
+#[cfg_attr(staged_api, stable(feature = "i128", since = "1.26.0"))]
+impl From<u128> for Ipv6Addr {
+ /// Convert a host byte order `u128` into an `Ipv6Addr`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
+ /// assert_eq!(
+ /// Ipv6Addr::new(
+ /// 0x1020, 0x3040, 0x5060, 0x7080,
+ /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
+ /// ),
+ /// addr);
+ /// ```
+ #[inline]
+ fn from(ip: u128) -> Ipv6Addr {
+ Ipv6Addr::from(ip.to_be_bytes())
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ipv6_from_octets", since = "1.9.0"))]
+impl From<[u8; 16]> for Ipv6Addr {
+ /// Creates an `Ipv6Addr` from a sixteen element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::from([
+ /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
+ /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
+ /// ]);
+ /// assert_eq!(
+ /// Ipv6Addr::new(
+ /// 0x1918, 0x1716,
+ /// 0x1514, 0x1312,
+ /// 0x1110, 0x0f0e,
+ /// 0x0d0c, 0x0b0a
+ /// ),
+ /// addr
+ /// );
+ /// ```
+ #[inline]
+ fn from(octets: [u8; 16]) -> Ipv6Addr {
+ Ipv6Addr {
+ inner: in6_addr_new(octets),
+ }
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ipv6_from_segments", since = "1.16.0"))]
+impl From<[u16; 8]> for Ipv6Addr {
+ /// Creates an `Ipv6Addr` from an eight element 16-bit array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::from([
+ /// 525u16, 524u16, 523u16, 522u16,
+ /// 521u16, 520u16, 519u16, 518u16,
+ /// ]);
+ /// assert_eq!(
+ /// Ipv6Addr::new(
+ /// 0x20d, 0x20c,
+ /// 0x20b, 0x20a,
+ /// 0x209, 0x208,
+ /// 0x207, 0x206
+ /// ),
+ /// addr
+ /// );
+ /// ```
+ #[inline]
+ fn from(segments: [u16; 8]) -> Ipv6Addr {
+ let [a, b, c, d, e, f, g, h] = segments;
+ Ipv6Addr::new(a, b, c, d, e, f, g, h)
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))]
+impl From<[u8; 16]> for IpAddr {
+ /// Creates an `IpAddr::V6` from a sixteen element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr};
+ ///
+ /// let addr = IpAddr::from([
+ /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
+ /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
+ /// ]);
+ /// assert_eq!(
+ /// IpAddr::V6(Ipv6Addr::new(
+ /// 0x1918, 0x1716,
+ /// 0x1514, 0x1312,
+ /// 0x1110, 0x0f0e,
+ /// 0x0d0c, 0x0b0a
+ /// )),
+ /// addr
+ /// );
+ /// ```
+ #[inline]
+ fn from(octets: [u8; 16]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(octets))
+ }
+}
+
+#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))]
+impl From<[u16; 8]> for IpAddr {
+ /// Creates an `IpAddr::V6` from an eight element 16-bit array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr};
+ ///
+ /// let addr = IpAddr::from([
+ /// 525u16, 524u16, 523u16, 522u16,
+ /// 521u16, 520u16, 519u16, 518u16,
+ /// ]);
+ /// assert_eq!(
+ /// IpAddr::V6(Ipv6Addr::new(
+ /// 0x20d, 0x20c,
+ /// 0x20b, 0x20a,
+ /// 0x209, 0x208,
+ /// 0x207, 0x206
+ /// )),
+ /// addr
+ /// );
+ /// ```
+ #[inline]
+ fn from(segments: [u16; 8]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(segments))
+ }
+}
diff --git a/vendor/rustix/src/net/mod.rs b/vendor/rustix/src/net/mod.rs
new file mode 100644
index 000000000..24fe06dc3
--- /dev/null
+++ b/vendor/rustix/src/net/mod.rs
@@ -0,0 +1,48 @@
+//! Network-related operations.
+//!
+//! On Windows, one must call [`wsa_startup`] in the process before calling any
+//! of these APIs. [`wsa_cleanup`] may be used in the process if these APIs are
+//! no longer needed.
+//!
+//! [`wsa_startup`]: https://docs.rs/rustix/latest/x86_64-pc-windows-msvc/rustix/net/fn.wsa_startup.html
+//! [`wsa_cleanup`]: https://docs.rs/rustix/latest/x86_64-pc-windows-msvc/rustix/net/fn.wsa_cleanup.html
+
+#[cfg(not(feature = "std"))]
+mod addr;
+#[cfg(not(feature = "std"))]
+mod ip;
+mod send_recv;
+mod socket;
+mod socket_addr_any;
+#[cfg(not(any(windows, target_os = "wasi")))]
+mod socketpair;
+#[cfg(windows)]
+mod wsa;
+
+pub mod sockopt;
+
+pub use send_recv::{
+ recv, recvfrom, send, sendto, sendto_any, sendto_v4, sendto_v6, RecvFlags, SendFlags,
+};
+pub use socket::{
+ accept, accept_with, acceptfrom, acceptfrom_with, bind, bind_any, bind_v4, bind_v6, connect,
+ connect_any, connect_v4, connect_v6, getpeername, getsockname, listen, shutdown, socket,
+ socket_with, AcceptFlags, AddressFamily, Protocol, Shutdown, SocketFlags, SocketType,
+};
+pub use socket_addr_any::{SocketAddrAny, SocketAddrStorage};
+#[cfg(not(any(windows, target_os = "wasi")))]
+pub use socketpair::socketpair;
+#[cfg(feature = "std")]
+pub use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+#[cfg(windows)]
+pub use wsa::{wsa_cleanup, wsa_startup};
+#[cfg(not(feature = "std"))]
+pub use {
+ addr::{SocketAddr, SocketAddrV4, SocketAddrV6},
+ ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope},
+};
+#[cfg(unix)]
+pub use {
+ send_recv::sendto_unix,
+ socket::{bind_unix, connect_unix, SocketAddrUnix},
+};
diff --git a/vendor/rustix/src/net/send_recv.rs b/vendor/rustix/src/net/send_recv.rs
new file mode 100644
index 000000000..83ccc79d4
--- /dev/null
+++ b/vendor/rustix/src/net/send_recv.rs
@@ -0,0 +1,210 @@
+//! `recv` and `send`, and variants.
+
+#[cfg(unix)]
+use crate::net::SocketAddrUnix;
+use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
+use crate::{imp, io};
+use imp::fd::{AsFd, BorrowedFd};
+
+pub use imp::net::send_recv::{RecvFlags, SendFlags};
+
+/// `recv(fd, buf, flags)`—Reads data from a socket.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/recv.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recv.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recv
+#[inline]
+pub fn recv<Fd: AsFd>(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> {
+ imp::net::syscalls::recv(fd.as_fd(), buf, flags)
+}
+
+/// `send(fd, buf, flags)`—Writes data to a socket.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/send.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/send.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send
+#[inline]
+pub fn send<Fd: AsFd>(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
+ imp::net::syscalls::send(fd.as_fd(), buf, flags)
+}
+
+/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and
+/// returns the sender address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/recvfrom.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvfrom.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom
+#[inline]
+pub fn recvfrom<Fd: AsFd>(
+ fd: Fd,
+ buf: &mut [u8],
+ flags: RecvFlags,
+) -> io::Result<(usize, Option<SocketAddrAny>)> {
+ imp::net::syscalls::recvfrom(fd.as_fd(), buf, flags)
+}
+
+/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP
+/// address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
+pub fn sendto<Fd: AsFd>(
+ fd: Fd,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddr,
+) -> io::Result<usize> {
+ _sendto(fd.as_fd(), buf, flags, addr)
+}
+
+fn _sendto(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddr,
+) -> io::Result<usize> {
+ match addr {
+ SocketAddr::V4(v4) => imp::net::syscalls::sendto_v4(fd, buf, flags, v4),
+ SocketAddr::V6(v6) => imp::net::syscalls::sendto_v6(fd, buf, flags, v6),
+ }
+}
+
+/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific
+/// address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
+pub fn sendto_any<Fd: AsFd>(
+ fd: Fd,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrAny,
+) -> io::Result<usize> {
+ _sendto_any(fd.as_fd(), buf, flags, addr)
+}
+
+fn _sendto_any(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrAny,
+) -> io::Result<usize> {
+ match addr {
+ SocketAddrAny::V4(v4) => imp::net::syscalls::sendto_v4(fd, buf, flags, v4),
+ SocketAddrAny::V6(v6) => imp::net::syscalls::sendto_v6(fd, buf, flags, v6),
+ #[cfg(unix)]
+ SocketAddrAny::Unix(unix) => imp::net::syscalls::sendto_unix(fd, buf, flags, unix),
+ }
+}
+
+/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in))`—Writes data to
+/// a socket to a specific IPv4 address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
+#[inline]
+#[doc(alias = "sendto")]
+pub fn sendto_v4<Fd: AsFd>(
+ fd: Fd,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrV4,
+) -> io::Result<usize> {
+ imp::net::syscalls::sendto_v4(fd.as_fd(), buf, flags, addr)
+}
+
+/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in6))`—Writes data
+/// to a socket to a specific IPv6 address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
+#[inline]
+#[doc(alias = "sendto")]
+pub fn sendto_v6<Fd: AsFd>(
+ fd: Fd,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrV6,
+) -> io::Result<usize> {
+ imp::net::syscalls::sendto_v6(fd.as_fd(), buf, flags, addr)
+}
+
+/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_un))`—Writes data to
+/// a socket to a specific Unix-domain socket address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto
+#[cfg(unix)]
+#[inline]
+#[doc(alias = "sendto")]
+pub fn sendto_unix<Fd: AsFd>(
+ fd: Fd,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrUnix,
+) -> io::Result<usize> {
+ imp::net::syscalls::sendto_unix(fd.as_fd(), buf, flags, addr)
+}
+
+// TODO: `recvmsg`, `sendmsg`
diff --git a/vendor/rustix/src/net/socket.rs b/vendor/rustix/src/net/socket.rs
new file mode 100644
index 000000000..cd8f149f6
--- /dev/null
+++ b/vendor/rustix/src/net/socket.rs
@@ -0,0 +1,439 @@
+use crate::imp;
+use crate::io::{self, OwnedFd};
+use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
+use imp::fd::{AsFd, BorrowedFd};
+
+#[cfg(unix)]
+pub use imp::net::addr::SocketAddrUnix;
+pub use imp::net::types::{
+ AcceptFlags, AddressFamily, Protocol, Shutdown, SocketFlags, SocketType,
+};
+
+impl Default for Protocol {
+ #[inline]
+ fn default() -> Self {
+ Self::IP
+ }
+}
+
+/// `socket(domain, type_, protocol)`—Creates a socket.
+///
+/// POSIX guarantees that `socket` 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]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/socket.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket
+#[inline]
+pub fn socket(domain: AddressFamily, type_: SocketType, protocol: Protocol) -> io::Result<OwnedFd> {
+ imp::net::syscalls::socket(domain, type_, protocol)
+}
+
+/// `socket_with(domain, type_ | flags, protocol)`—Creates a socket, with
+/// flags.
+///
+/// POSIX guarantees that `socket` 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.
+///
+/// `socket_with` is the same as [`socket`] but adds an additional flags
+/// operand.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/socket.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket
+#[inline]
+pub fn socket_with(
+ domain: AddressFamily,
+ type_: SocketType,
+ flags: SocketFlags,
+ protocol: Protocol,
+) -> io::Result<OwnedFd> {
+ imp::net::syscalls::socket_with(domain, type_, flags, protocol)
+}
+
+/// `bind(sockfd, addr)`—Binds a socket to an IP address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
+pub fn bind<Fd: AsFd>(sockfd: Fd, addr: &SocketAddr) -> io::Result<()> {
+ _bind(sockfd.as_fd(), addr)
+}
+
+fn _bind(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> {
+ match addr {
+ SocketAddr::V4(v4) => imp::net::syscalls::bind_v4(sockfd, v4),
+ SocketAddr::V6(v6) => imp::net::syscalls::bind_v6(sockfd, v6),
+ }
+}
+
+/// `bind(sockfd, addr)`—Binds a socket to an address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
+#[doc(alias = "bind")]
+pub fn bind_any<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> {
+ _bind_any(sockfd.as_fd(), addr)
+}
+
+fn _bind_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> {
+ match addr {
+ SocketAddrAny::V4(v4) => imp::net::syscalls::bind_v4(sockfd, v4),
+ SocketAddrAny::V6(v6) => imp::net::syscalls::bind_v6(sockfd, v6),
+ #[cfg(unix)]
+ SocketAddrAny::Unix(unix) => imp::net::syscalls::bind_unix(sockfd, unix),
+ }
+}
+
+/// `bind(sockfd, addr, sizeof(struct sockaddr_in))`—Binds a socket to an
+/// IPv4 address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
+#[inline]
+#[doc(alias = "bind")]
+pub fn bind_v4<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> {
+ imp::net::syscalls::bind_v4(sockfd.as_fd(), addr)
+}
+
+/// `bind(sockfd, addr, sizeof(struct sockaddr_in6))`—Binds a socket to an
+/// IPv6 address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
+#[inline]
+#[doc(alias = "bind")]
+pub fn bind_v6<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> {
+ imp::net::syscalls::bind_v6(sockfd.as_fd(), addr)
+}
+
+/// `bind(sockfd, addr, sizeof(struct sockaddr_un))`—Binds a socket to a
+/// Unix-domain address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind
+#[cfg(unix)]
+#[inline]
+#[doc(alias = "bind")]
+pub fn bind_unix<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> {
+ imp::net::syscalls::bind_unix(sockfd.as_fd(), addr)
+}
+
+/// `connect(sockfd, addr)`—Initiates a connection to an IP address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
+pub fn connect<Fd: AsFd>(sockfd: Fd, addr: &SocketAddr) -> io::Result<()> {
+ _connect(sockfd.as_fd(), addr)
+}
+
+fn _connect(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> {
+ match addr {
+ SocketAddr::V4(v4) => imp::net::syscalls::connect_v4(sockfd, v4),
+ SocketAddr::V6(v6) => imp::net::syscalls::connect_v6(sockfd, v6),
+ }
+}
+
+/// `connect(sockfd, addr)`—Initiates a connection.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
+#[doc(alias = "connect")]
+pub fn connect_any<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> {
+ _connect_any(sockfd.as_fd(), addr)
+}
+
+fn _connect_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> {
+ match addr {
+ SocketAddrAny::V4(v4) => imp::net::syscalls::connect_v4(sockfd, v4),
+ SocketAddrAny::V6(v6) => imp::net::syscalls::connect_v6(sockfd, v6),
+ #[cfg(unix)]
+ SocketAddrAny::Unix(unix) => imp::net::syscalls::connect_unix(sockfd, unix),
+ }
+}
+
+/// `connect(sockfd, addr, sizeof(struct sockaddr_in))`—Initiates a
+/// connection to an IPv4 address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
+#[inline]
+#[doc(alias = "connect")]
+pub fn connect_v4<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> {
+ imp::net::syscalls::connect_v4(sockfd.as_fd(), addr)
+}
+
+/// `connect(sockfd, addr, sizeof(struct sockaddr_in6))`—Initiates a
+/// connection to an IPv6 address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
+#[inline]
+#[doc(alias = "connect")]
+pub fn connect_v6<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> {
+ imp::net::syscalls::connect_v6(sockfd.as_fd(), addr)
+}
+
+/// `connect(sockfd, addr, sizeof(struct sockaddr_un))`—Initiates a
+/// connection to a Unix-domain address.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect
+#[cfg(unix)]
+#[inline]
+#[doc(alias = "connect")]
+pub fn connect_unix<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> {
+ imp::net::syscalls::connect_unix(sockfd.as_fd(), addr)
+}
+
+/// `listen(fd, backlog)`—Enables listening for incoming connections.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/listen.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/listen.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen
+#[inline]
+pub fn listen<Fd: AsFd>(sockfd: Fd, backlog: i32) -> io::Result<()> {
+ imp::net::syscalls::listen(sockfd.as_fd(), backlog)
+}
+
+/// `accept(fd, NULL, NULL)`—Accepts an incoming connection.
+///
+/// Use [`acceptfrom`] to retrieve the peer address.
+///
+/// POSIX guarantees that `accept` 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]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/accept.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/accept.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept
+#[inline]
+#[doc(alias = "accept4")]
+pub fn accept<Fd: AsFd>(sockfd: Fd) -> io::Result<OwnedFd> {
+ imp::net::syscalls::accept(sockfd.as_fd())
+}
+
+/// `accept4(fd, NULL, NULL, flags)`—Accepts an incoming connection, with
+/// flags.
+///
+/// Use [`acceptfrom_with`] to retrieve the peer address.
+///
+/// Even though POSIX guarantees that this will use the lowest unused file
+/// descriptor, it is not safe in general to rely on this, as file descriptors
+/// may be unexpectedly allocated on other threads or in libraries.
+///
+/// `accept_with` is the same as [`accept`] but adds an additional flags
+/// operand.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/accept4.2.html
+#[inline]
+#[doc(alias = "accept4")]
+pub fn accept_with<Fd: AsFd>(sockfd: Fd, flags: AcceptFlags) -> io::Result<OwnedFd> {
+ imp::net::syscalls::accept_with(sockfd.as_fd(), flags)
+}
+
+/// `accept(fd, &addr, &len)`—Accepts an incoming connection and returns the
+/// peer address.
+///
+/// Use [`accept`] if the peer address isn't needed.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/accept.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/accept.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept
+#[inline]
+#[doc(alias = "accept4")]
+pub fn acceptfrom<Fd: AsFd>(sockfd: Fd) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ imp::net::syscalls::acceptfrom(sockfd.as_fd())
+}
+
+/// `accept4(fd, &addr, &len, flags)`—Accepts an incoming connection and
+/// returns the peer address, with flags.
+///
+/// Use [`accept_with`] if the peer address isn't needed.
+///
+/// `acceptfrom_with` is the same as [`acceptfrom`] but adds an additional
+/// flags operand.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/accept4.2.html
+#[inline]
+#[doc(alias = "accept4")]
+pub fn acceptfrom_with<Fd: AsFd>(
+ sockfd: Fd,
+ flags: AcceptFlags,
+) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ imp::net::syscalls::acceptfrom_with(sockfd.as_fd(), flags)
+}
+
+/// `shutdown(fd, how)`—Closes the read and/or write sides of a stream.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/shutdown.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/shutdown.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-shutdown
+#[inline]
+pub fn shutdown<Fd: AsFd>(sockfd: Fd, how: Shutdown) -> io::Result<()> {
+ imp::net::syscalls::shutdown(sockfd.as_fd(), how)
+}
+
+/// `getsockname(fd, addr, len)`—Returns the address a socket is bound to.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getsockname.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockname.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockname
+#[inline]
+pub fn getsockname<Fd: AsFd>(sockfd: Fd) -> io::Result<SocketAddrAny> {
+ imp::net::syscalls::getsockname(sockfd.as_fd())
+}
+
+/// `getpeername(fd, addr, len)`—Returns the address a socket is connected
+/// to.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+/// - [Winsock2]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getpeername.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpeername.2.html
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getpeername
+#[inline]
+pub fn getpeername<Fd: AsFd>(sockfd: Fd) -> io::Result<Option<SocketAddrAny>> {
+ imp::net::syscalls::getpeername(sockfd.as_fd())
+}
diff --git a/vendor/rustix/src/net/socket_addr_any.rs b/vendor/rustix/src/net/socket_addr_any.rs
new file mode 100644
index 000000000..4970dbf74
--- /dev/null
+++ b/vendor/rustix/src/net/socket_addr_any.rs
@@ -0,0 +1,81 @@
+//! A socket address for any kind of socket.
+//!
+//! This is similar to [`std::net::SocketAddr`], but also supports Unix-domain
+//! socket addresses.
+//!
+//! # Safety
+//!
+//! The `read` and `write` functions allow decoding and encoding from and to
+//! OS-specific socket address representations in memory.
+#![allow(unsafe_code)]
+
+#[cfg(unix)]
+use crate::net::SocketAddrUnix;
+use crate::net::{AddressFamily, SocketAddrV4, SocketAddrV6};
+use crate::{imp, io};
+#[cfg(feature = "std")]
+use core::fmt;
+
+pub use imp::net::addr::SocketAddrStorage;
+
+/// `struct sockaddr_storage` as a Rust enum.
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[doc(alias = "sockaddr")]
+#[non_exhaustive]
+pub enum SocketAddrAny {
+ /// `struct sockaddr_in`
+ V4(SocketAddrV4),
+ /// `struct sockaddr_in6`
+ V6(SocketAddrV6),
+ /// `struct sockaddr_un`
+ #[cfg(unix)]
+ Unix(SocketAddrUnix),
+}
+
+impl SocketAddrAny {
+ /// Return the address family of this socket address.
+ #[inline]
+ pub const fn address_family(&self) -> AddressFamily {
+ match self {
+ SocketAddrAny::V4(_) => AddressFamily::INET,
+ SocketAddrAny::V6(_) => AddressFamily::INET6,
+ #[cfg(unix)]
+ SocketAddrAny::Unix(_) => AddressFamily::UNIX,
+ }
+ }
+
+ /// Writes a platform-specific encoding of this socket address to
+ /// the memory pointed to by `storage`, and returns the number of
+ /// bytes used.
+ ///
+ /// # Safety
+ ///
+ /// `storage` must point to valid memory for encoding the socket
+ /// address.
+ pub unsafe fn write(&self, storage: *mut SocketAddrStorage) -> usize {
+ imp::net::write_sockaddr::write_sockaddr(self, storage)
+ }
+
+ /// Reads a platform-specific encoding of a socket address from
+ /// the memory pointed to by `storage`, which uses `len` bytes.
+ ///
+ /// # Safety
+ ///
+ /// `storage` must point to valid memory for decoding a socket
+ /// address.
+ pub unsafe fn read(storage: *const SocketAddrStorage, len: usize) -> io::Result<Self> {
+ imp::net::read_sockaddr::read_sockaddr(storage, len)
+ }
+}
+
+#[cfg(feature = "std")]
+impl fmt::Debug for SocketAddrAny {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ SocketAddrAny::V4(v4) => v4.fmt(fmt),
+ SocketAddrAny::V6(v6) => v6.fmt(fmt),
+ #[cfg(unix)]
+ SocketAddrAny::Unix(unix) => unix.fmt(fmt),
+ }
+ }
+}
diff --git a/vendor/rustix/src/net/socketpair.rs b/vendor/rustix/src/net/socketpair.rs
new file mode 100644
index 000000000..68a58f3e9
--- /dev/null
+++ b/vendor/rustix/src/net/socketpair.rs
@@ -0,0 +1,21 @@
+use crate::imp;
+use crate::io::{self, OwnedFd};
+use crate::net::{AddressFamily, Protocol, SocketFlags, SocketType};
+
+/// `socketpair(domain, type_ | accept_flags, protocol)`
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/socketpair.2.html
+#[inline]
+pub fn socketpair(
+ domain: AddressFamily,
+ type_: SocketType,
+ flags: SocketFlags,
+ protocol: Protocol,
+) -> io::Result<(OwnedFd, OwnedFd)> {
+ imp::net::syscalls::socketpair(domain, type_, flags, protocol)
+}
diff --git a/vendor/rustix/src/net/sockopt.rs b/vendor/rustix/src/net/sockopt.rs
new file mode 100644
index 000000000..f5b149b37
--- /dev/null
+++ b/vendor/rustix/src/net/sockopt.rs
@@ -0,0 +1,600 @@
+//! `getsockopt` and `setsockopt` functions.
+//!
+//! In the rustix API, there is a separate function for each option, so that
+//! it can be given an option-specific type signature.
+
+#![doc(alias = "getsockopt")]
+#![doc(alias = "setsockopt")]
+
+use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
+use crate::{imp, io};
+use core::time::Duration;
+use imp::fd::AsFd;
+
+pub use imp::net::types::Timeout;
+
+/// `getsockopt(fd, SOL_SOCKET, SO_TYPE)`—Returns the type of a socket.
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `sys/socket.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `socket`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `SOL_SOCKET` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
+#[inline]
+#[doc(alias = "SO_TYPE")]
+pub fn get_socket_type<Fd: AsFd>(fd: Fd) -> io::Result<SocketType> {
+ imp::net::syscalls::sockopt::get_socket_type(fd.as_fd())
+}
+
+/// `setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, value)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `sys/socket.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `socket`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `SOL_SOCKET` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
+#[inline]
+#[doc(alias = "SO_REUSEADDR")]
+pub fn set_socket_reuseaddr<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_socket_reuseaddr(fd.as_fd(), value)
+}
+
+/// `setsockopt(fd, SOL_SOCKET, SO_BROADCAST, broadcast)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `sys/socket.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `socket`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `SOL_SOCKET` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
+#[inline]
+#[doc(alias = "SO_BROADCAST")]
+pub fn set_socket_broadcast<Fd: AsFd>(fd: Fd, broadcast: bool) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_socket_broadcast(fd.as_fd(), broadcast)
+}
+
+/// `getsockopt(fd, SOL_SOCKET, SO_BROADCAST)`
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `sys/socket.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `socket`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `SOL_SOCKET` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
+#[inline]
+#[doc(alias = "SO_BROADCAST")]
+pub fn get_socket_broadcast<Fd: AsFd>(fd: Fd) -> io::Result<bool> {
+ imp::net::syscalls::sockopt::get_socket_broadcast(fd.as_fd())
+}
+
+/// `setsockopt(fd, SOL_SOCKET, SO_LINGER, linger)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `sys/socket.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `socket`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `SOL_SOCKET` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
+#[inline]
+#[doc(alias = "SO_LINGER")]
+pub fn set_socket_linger<Fd: AsFd>(fd: Fd, linger: Option<Duration>) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_socket_linger(fd.as_fd(), linger)
+}
+
+/// `getsockopt(fd, SOL_SOCKET, SO_LINGER)`
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `sys/socket.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `socket`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `SOL_SOCKET` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
+#[inline]
+#[doc(alias = "SO_LINGER")]
+pub fn get_socket_linger<Fd: AsFd>(fd: Fd) -> io::Result<Option<Duration>> {
+ imp::net::syscalls::sockopt::get_socket_linger(fd.as_fd())
+}
+
+/// `setsockopt(fd, SOL_SOCKET, SO_PASSCRED, passcred)`
+///
+/// # References
+/// - [Linux `setsockopt`]
+/// - [Linux `socket`]
+///
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[doc(alias = "SO_PASSCRED")]
+pub fn set_socket_passcred<Fd: AsFd>(fd: Fd, passcred: bool) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_socket_passcred(fd.as_fd(), passcred)
+}
+
+/// `getsockopt(fd, SOL_SOCKET, SO_PASSCRED)`
+///
+/// # References
+/// - [Linux `getsockopt`]
+/// - [Linux `socket`]
+///
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+#[doc(alias = "SO_PASSCRED")]
+pub fn get_socket_passcred<Fd: AsFd>(fd: Fd) -> io::Result<bool> {
+ imp::net::syscalls::sockopt::get_socket_passcred(fd.as_fd())
+}
+
+/// `setsockopt(fd, SOL_SOCKET, id, timeout)`—Set the sending
+/// or receiving timeout.
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `sys/socket.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `socket`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `SOL_SOCKET` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
+#[inline]
+#[doc(alias = "SO_RCVTIMEO")]
+#[doc(alias = "SO_SNDTIMEO")]
+pub fn set_socket_timeout<Fd: AsFd>(
+ fd: Fd,
+ id: Timeout,
+ timeout: Option<Duration>,
+) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_socket_timeout(fd.as_fd(), id, timeout)
+}
+
+/// `getsockopt(fd, SOL_SOCKET, id)`—Get the sending or receiving timeout.
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `sys/socket.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `socket`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `SOL_SOCKET` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options
+#[inline]
+#[doc(alias = "SO_RCVTIMEO")]
+#[doc(alias = "SO_SNDTIMEO")]
+pub fn get_socket_timeout<Fd: AsFd>(fd: Fd, id: Timeout) -> io::Result<Option<Duration>> {
+ imp::net::syscalls::sockopt::get_socket_timeout(fd.as_fd(), id)
+}
+
+/// `setsockopt(fd, IPPROTO_IP, IP_TTL, ttl)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ip`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IP` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
+#[inline]
+#[doc(alias = "IP_TTL")]
+pub fn set_ip_ttl<Fd: AsFd>(fd: Fd, ttl: u32) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ip_ttl(fd.as_fd(), ttl)
+}
+
+/// `getsockopt(fd, IPPROTO_IP, IP_TTL)`
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `ip`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `IPPROTO_IPV6` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
+#[inline]
+#[doc(alias = "IP_TTL")]
+pub fn get_ip_ttl<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
+ imp::net::syscalls::sockopt::get_ip_ttl(fd.as_fd())
+}
+
+/// `setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, only_v6)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ipv6`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IPV6` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options
+#[inline]
+#[doc(alias = "IPV6_V6ONLY")]
+pub fn set_ipv6_v6only<Fd: AsFd>(fd: Fd, only_v6: bool) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ipv6_v6only(fd.as_fd(), only_v6)
+}
+
+/// `getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY)`
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `ipv6`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `IPPROTO_IPV6` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options
+#[inline]
+#[doc(alias = "IPV6_V6ONLY")]
+pub fn get_ipv6_v6only<Fd: AsFd>(fd: Fd) -> io::Result<bool> {
+ imp::net::syscalls::sockopt::get_ipv6_v6only(fd.as_fd())
+}
+
+/// `setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, multicast_loop)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ip`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IP` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
+#[inline]
+#[doc(alias = "IP_MULTICAST_LOOP")]
+pub fn set_ip_multicast_loop<Fd: AsFd>(fd: Fd, multicast_loop: bool) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ip_multicast_loop(fd.as_fd(), multicast_loop)
+}
+
+/// `getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP)`
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `ip`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `IPPROTO_IP` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
+#[inline]
+#[doc(alias = "IP_MULTICAST_LOOP")]
+pub fn get_ip_multicast_loop<Fd: AsFd>(fd: Fd) -> io::Result<bool> {
+ imp::net::syscalls::sockopt::get_ip_multicast_loop(fd.as_fd())
+}
+
+/// `setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, multicast_ttl)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ip`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IP` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
+#[inline]
+#[doc(alias = "IP_MULTICAST_TTL")]
+pub fn set_ip_multicast_ttl<Fd: AsFd>(fd: Fd, multicast_ttl: u32) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ip_multicast_ttl(fd.as_fd(), multicast_ttl)
+}
+
+/// `getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL)`
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `ip`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `IPPROTO_IP` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
+#[inline]
+#[doc(alias = "IP_MULTICAST_TTL")]
+pub fn get_ip_multicast_ttl<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
+ imp::net::syscalls::sockopt::get_ip_multicast_ttl(fd.as_fd())
+}
+
+/// `setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, multicast_loop)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ipv6`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IPV6` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options
+#[inline]
+#[doc(alias = "IPV6_MULTICAST_LOOP")]
+pub fn set_ipv6_multicast_loop<Fd: AsFd>(fd: Fd, multicast_loop: bool) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ipv6_multicast_loop(fd.as_fd(), multicast_loop)
+}
+
+/// `getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP)`
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `ipv6`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `IPPROTO_IPV6` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html
+/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt
+/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options
+#[inline]
+#[doc(alias = "IPV6_MULTICAST_LOOP")]
+pub fn get_ipv6_multicast_loop<Fd: AsFd>(fd: Fd) -> io::Result<bool> {
+ imp::net::syscalls::sockopt::get_ipv6_multicast_loop(fd.as_fd())
+}
+
+/// `setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, multiaddr, interface)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ip`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IP` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
+#[inline]
+#[doc(alias = "IP_ADD_MEMBERSHIP")]
+pub fn set_ip_add_membership<Fd: AsFd>(
+ fd: Fd,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ip_add_membership(fd.as_fd(), multiaddr, interface)
+}
+
+/// `setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, multiaddr, interface)`
+///
+/// `IPV6_ADD_MEMBERSHIP` is the same as `IPV6_JOIN_GROUP` in POSIX.
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ipv6]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IPV6` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options
+#[inline]
+#[doc(alias = "IPV6_JOIN_GROUP")]
+#[doc(alias = "IPV6_ADD_MEMBERSHIP")]
+pub fn set_ipv6_add_membership<Fd: AsFd>(
+ fd: Fd,
+ multiaddr: &Ipv6Addr,
+ interface: u32,
+) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ipv6_add_membership(fd.as_fd(), multiaddr, interface)
+}
+
+/// `setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, multiaddr, interface)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ip`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IP` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
+#[inline]
+#[doc(alias = "IP_DROP_MEMBERSHIP")]
+pub fn set_ip_drop_membership<Fd: AsFd>(
+ fd: Fd,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ip_drop_membership(fd.as_fd(), multiaddr, interface)
+}
+
+/// `setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, multiaddr, interface)`
+///
+/// `IPV6_DROP_MEMBERSHIP` is the same as `IPV6_LEAVE_GROUP` in POSIX.
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/in.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `ipv6`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_IPV6` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options
+#[inline]
+#[doc(alias = "IPV6_LEAVE_GROUP")]
+#[doc(alias = "IPV6_DROP_MEMBERSHIP")]
+pub fn set_ipv6_drop_membership<Fd: AsFd>(
+ fd: Fd,
+ multiaddr: &Ipv6Addr,
+ interface: u32,
+) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_ipv6_drop_membership(fd.as_fd(), multiaddr, interface)
+}
+
+/// `setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, nodelay)`
+///
+/// # References
+/// - [POSIX `setsockopt`]
+/// - [POSIX `netinet/tcp.h`]
+/// - [Linux `setsockopt`]
+/// - [Linux `tcp`]
+/// - [Winsock2 `setsockopt`]
+/// - [Winsock2 `IPPROTO_TCP` options]
+///
+/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html
+/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html
+/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html
+/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options
+#[inline]
+#[doc(alias = "TCP_NODELAY")]
+pub fn set_tcp_nodelay<Fd: AsFd>(fd: Fd, nodelay: bool) -> io::Result<()> {
+ imp::net::syscalls::sockopt::set_tcp_nodelay(fd.as_fd(), nodelay)
+}
+
+/// `getsockopt(fd, IPPROTO_TCP, TCP_NODELAY)`
+///
+/// # References
+/// - [POSIX `getsockopt`]
+/// - [POSIX `netinet/tcp.h`]
+/// - [Linux `getsockopt`]
+/// - [Linux `tcp`]
+/// - [Winsock2 `getsockopt`]
+/// - [Winsock2 `IPPROTO_TCP` options]
+///
+/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html
+/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html
+/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html
+/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
+/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options
+#[inline]
+#[doc(alias = "TCP_NODELAY")]
+pub fn get_tcp_nodelay<Fd: AsFd>(fd: Fd) -> io::Result<bool> {
+ imp::net::syscalls::sockopt::get_tcp_nodelay(fd.as_fd())
+}
diff --git a/vendor/rustix/src/net/wsa.rs b/vendor/rustix/src/net/wsa.rs
new file mode 100644
index 000000000..e2a70c97b
--- /dev/null
+++ b/vendor/rustix/src/net/wsa.rs
@@ -0,0 +1,49 @@
+use crate::io;
+use core::mem::MaybeUninit;
+use windows_sys::Win32::Networking::WinSock::{WSACleanup, WSAData, WSAGetLastError, WSAStartup};
+
+/// `WSAStartup()`—Initialize process-wide Windows support for sockets.
+///
+/// On Windows, it's necessary to initialize the sockets subsystem before
+/// using sockets APIs. The function performs the necessary initialization.
+///
+/// # References
+/// - [Winsock2]
+///
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsastartup
+pub fn wsa_startup() -> io::Result<WSAData> {
+ // Request version 2.2, which has been the latest version since far older
+ // versions of Windows than we support here. For more information about
+ // the version, see [here].
+ //
+ // [here]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsastartup#remarks
+ let version = 0x202;
+ let mut data = MaybeUninit::uninit();
+ unsafe {
+ let ret = WSAStartup(version, data.as_mut_ptr());
+ if ret == 0 {
+ Ok(data.assume_init())
+ } else {
+ Err(io::Errno::from_raw_os_error(WSAGetLastError()))
+ }
+ }
+}
+
+/// `WSACleanup()`—Clean up process-wide Windows support for sockets.
+///
+/// In a program where `init` is called, if sockets are no longer necessary,
+/// this function releases associated resources.
+///
+/// # References
+/// - [Winsock2]
+///
+/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsacleanup
+pub fn wsa_cleanup() -> io::Result<()> {
+ unsafe {
+ if WSACleanup() == 0 {
+ Ok(())
+ } else {
+ Err(io::Errno::from_raw_os_error(WSAGetLastError()))
+ }
+ }
+}
diff --git a/vendor/rustix/src/param/auxv.rs b/vendor/rustix/src/param/auxv.rs
new file mode 100644
index 000000000..6aec061f7
--- /dev/null
+++ b/vendor/rustix/src/param/auxv.rs
@@ -0,0 +1,96 @@
+#[cfg(any(
+ linux_raw,
+ all(
+ libc,
+ any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+ )
+ )
+))]
+use crate::ffi::CStr;
+use crate::imp;
+
+/// `sysconf(_SC_PAGESIZE)`—Returns the process' page size.
+///
+/// Also known as `getpagesize`.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux `sysconf`]
+/// - [Linux `getpagesize`]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html
+/// [Linux `sysconf`]: https://man7.org/linux/man-pages/man3/sysconf.3.html
+/// [Linux `getpagesize`]: https://man7.org/linux/man-pages/man2/getpagesize.2.html
+#[inline]
+#[doc(alias = "_SC_PAGESIZE")]
+#[doc(alias = "_SC_PAGE_SIZE")]
+#[doc(alias = "getpagesize")]
+pub fn page_size() -> usize {
+ imp::param::auxv::page_size()
+}
+
+/// `sysconf(_SC_CLK_TCK)`—Returns the process' clock ticks per second.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/sysconf.3.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[doc(alias = "_SC_CLK_TCK")]
+pub fn clock_ticks_per_second() -> u64 {
+ imp::param::auxv::clock_ticks_per_second()
+}
+
+/// `(getauxval(AT_HWCAP), getauxval(AT_HWCAP2)`—Returns the Linux "hwcap"
+/// data.
+///
+/// Return the Linux `AT_HWCAP` and `AT_HWCAP2` values passed to the
+/// current process. Returns 0 for each value if it is not available.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/getauxval.3.html
+#[cfg(any(
+ linux_raw,
+ all(
+ libc,
+ any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+ )
+ )
+))]
+#[inline]
+pub fn linux_hwcap() -> (usize, usize) {
+ imp::param::auxv::linux_hwcap()
+}
+
+/// `getauxval(AT_EXECFN)`—Returns the Linux "execfn" string.
+///
+/// Return the string that Linux has recorded as the filesystem path to the
+/// executable. Returns an empty string if the string is not available.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/getauxval.3.html
+#[cfg(any(
+ linux_raw,
+ all(
+ libc,
+ any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+ )
+ )
+))]
+#[inline]
+pub fn linux_execfn() -> &'static CStr {
+ imp::param::auxv::linux_execfn()
+}
diff --git a/vendor/rustix/src/param/init.rs b/vendor/rustix/src/param/init.rs
new file mode 100644
index 000000000..e66ff82bb
--- /dev/null
+++ b/vendor/rustix/src/param/init.rs
@@ -0,0 +1,23 @@
+//! rustix's `init` function.
+//!
+//! # Safety
+//!
+//! On mustang, or on any non-glibc non-musl platform, the `init` function must
+//! be called before any other function in this module. It is unsafe because it
+//! operates on raw pointers.
+#![allow(unsafe_code)]
+
+use crate::imp;
+
+/// Initialize process-wide state.
+///
+/// # Safety
+///
+/// This must be passed a pointer to the original environment variable block
+/// set up by the OS at process startup, and it must be called before any
+/// other rustix functions are called.
+#[inline]
+#[doc(hidden)]
+pub unsafe fn init(envp: *mut *mut u8) {
+ imp::param::auxv::init(envp)
+}
diff --git a/vendor/rustix/src/param/mod.rs b/vendor/rustix/src/param/mod.rs
new file mode 100644
index 000000000..5169d0a51
--- /dev/null
+++ b/vendor/rustix/src/param/mod.rs
@@ -0,0 +1,37 @@
+//! Process parameters.
+//!
+//! These values correspond to `sysconf` in POSIX, and the auxv array in Linux.
+//! Despite the POSIX name “sysconf”, these aren't *system* configuration
+//! parameters; they're *process* configuration parameters, as they may differ
+//! between different processes on the same system.
+
+#[cfg(feature = "param")]
+mod auxv;
+#[cfg(any(
+ target_vendor = "mustang",
+ not(any(target_env = "gnu", target_env = "musl")),
+))]
+mod init;
+
+#[cfg(feature = "param")]
+#[cfg(not(target_os = "wasi"))]
+pub use auxv::clock_ticks_per_second;
+#[cfg(feature = "param")]
+pub use auxv::page_size;
+#[cfg(feature = "param")]
+#[cfg(any(
+ linux_raw,
+ all(
+ libc,
+ any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+ )
+ )
+))]
+pub use auxv::{linux_execfn, linux_hwcap};
+#[cfg(any(
+ target_vendor = "mustang",
+ not(any(target_env = "gnu", target_env = "musl")),
+))]
+pub use init::init;
diff --git a/vendor/rustix/src/path/arg.rs b/vendor/rustix/src/path/arg.rs
new file mode 100644
index 000000000..7f66f71f2
--- /dev/null
+++ b/vendor/rustix/src/path/arg.rs
@@ -0,0 +1,963 @@
+//! Convenient and efficient string argument passing.
+//!
+//! This module defines the `Arg` trait and implements it for several common
+//! string types. This allows users to pass any of these string types directly
+//! to rustix APIs with string arguments, and it allows rustix to implement
+//! NUL-termination without the need for copying where possible.
+
+use crate::ffi::{CStr, CString};
+use crate::io;
+#[cfg(feature = "itoa")]
+use crate::path::DecInt;
+use crate::path::SMALL_PATH_BUFFER_SIZE;
+use alloc::borrow::Cow;
+#[cfg(feature = "itoa")]
+use alloc::borrow::ToOwned;
+use alloc::string::String;
+use alloc::vec::Vec;
+use core::str;
+#[cfg(feature = "std")]
+use std::ffi::{OsStr, OsString};
+#[cfg(feature = "std")]
+#[cfg(target_os = "hermit")]
+use std::os::hermit::ext::ffi::{OsStrExt, OsStringExt};
+#[cfg(feature = "std")]
+#[cfg(unix)]
+use std::os::unix::ffi::{OsStrExt, OsStringExt};
+#[cfg(feature = "std")]
+#[cfg(target_os = "vxworks")]
+use std::os::vxworks::ext::ffi::{OsStrExt, OsStringExt};
+#[cfg(feature = "std")]
+#[cfg(target_os = "wasi")]
+use std::os::wasi::ffi::{OsStrExt, OsStringExt};
+#[cfg(feature = "std")]
+use std::path::{Component, Components, Iter, Path, PathBuf};
+
+/// A trait for passing path arguments.
+///
+/// This is similar to [`AsRef`]`<`[`Path`]`>`, but is implemented for more
+/// kinds of strings and can convert into more kinds of strings.
+///
+/// # Example
+///
+/// ```rust
+/// # #[cfg(any(feature = "fs", feature = "net"))]
+/// use rustix::ffi::CStr;
+/// use rustix::io;
+/// # #[cfg(any(feature = "fs", feature = "net"))]
+/// use rustix::path::Arg;
+///
+/// # #[cfg(any(feature = "fs", feature = "net"))]
+/// pub fn touch<P: Arg>(path: P) -> io::Result<()> {
+/// let path = path.into_c_str()?;
+/// _touch(&path)
+/// }
+///
+/// # #[cfg(any(feature = "fs", feature = "net"))]
+/// fn _touch(path: &CStr) -> io::Result<()> {
+/// // implementation goes here
+/// Ok(())
+/// }
+/// ```
+///
+/// Users can then call `touch("foo")`, `touch(cstr!("foo"))`,
+/// `touch(Path::new("foo"))`, or many other things.
+///
+/// [`AsRef`]: std::convert::AsRef
+pub trait Arg {
+ /// Returns a view of this string as a string slice.
+ fn as_str(&self) -> io::Result<&str>;
+
+ /// Returns a potentially-lossy rendering of this string as a `Cow<'_,
+ /// str>`.
+ fn to_string_lossy(&self) -> Cow<'_, str>;
+
+ /// Returns a view of this string as a maybe-owned [`CStr`].
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>>;
+
+ /// Consumes `self` and returns a view of this string as a maybe-owned
+ /// [`CStr`].
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b;
+
+ /// Runs a closure with `self` passed in as a `&CStr`.
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>;
+}
+
+impl Arg for &str {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ Ok(self)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ Cow::Borrowed(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(*self).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_bytes(), f)
+ }
+}
+
+impl Arg for &String {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ Ok(self)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ Cow::Borrowed(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(String::as_str(self)).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ self.as_str().into_c_str()
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_bytes(), f)
+ }
+}
+
+impl Arg for String {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ Ok(self)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ Cow::Borrowed(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_str()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(&CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Arg for &OsStr {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ OsStr::to_string_lossy(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_bytes(), f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Arg for &OsString {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ OsString::as_os_str(self).to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ self.as_os_str().to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(OsString::as_os_str(self).as_bytes())
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ self.as_os_str().into_c_str()
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_bytes(), f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Arg for OsString {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.as_os_str().to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ self.as_os_str().to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self.into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(&CString::new(self.into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Arg for &Path {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.as_os_str().to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ Path::to_string_lossy(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_os_str().as_bytes(), f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Arg for &PathBuf {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ PathBuf::as_path(self)
+ .as_os_str()
+ .to_str()
+ .ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ self.as_path().to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(PathBuf::as_path(self).as_os_str().as_bytes())
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ self.as_path().into_c_str()
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_os_str().as_bytes(), f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Arg for PathBuf {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.as_os_str().to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ self.as_os_str().to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self.into_os_string().into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(
+ &CString::new(self.into_os_string().into_vec())
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ )
+ }
+}
+
+impl Arg for &CStr {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.to_str().map_err(|_utf8_err| io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ CStr::to_string_lossy(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Borrowed(self))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Borrowed(self))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(self)
+ }
+}
+
+impl Arg for &CString {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ unimplemented!()
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ unimplemented!()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Borrowed(self))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Borrowed(self))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(self)
+ }
+}
+
+impl Arg for CString {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.to_str().map_err(|_utf8_err| io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ CStr::to_string_lossy(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Borrowed(self))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(self))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(&self)
+ }
+}
+
+impl<'a> Arg for Cow<'a, str> {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ Ok(self)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ Cow::Borrowed(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_ref()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ match self {
+ Cow::Owned(s) => CString::new(s),
+ Cow::Borrowed(s) => CString::new(s),
+ }
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_bytes(), f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'a> Arg for Cow<'a, OsStr> {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ (**self).to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ (**self).to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ match self {
+ Cow::Owned(os) => CString::new(os.into_vec()),
+ Cow::Borrowed(os) => CString::new(os.as_bytes()),
+ }
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_bytes(), f)
+ }
+}
+
+impl<'a> Arg for Cow<'a, CStr> {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.to_str().map_err(|_utf8_err| io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ let borrow: &CStr = core::borrow::Borrow::borrow(self);
+ borrow.to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Borrowed(self))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(self)
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(&self)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'a> Arg for Component<'a> {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.as_os_str().to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ self.as_os_str().to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_os_str().as_bytes(), f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'a> Arg for Components<'a> {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.as_path().to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ self.as_path().to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_path().as_os_str().as_bytes())
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self.as_path().as_os_str().as_bytes())
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_path().as_os_str().as_bytes(), f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<'a> Arg for Iter<'a> {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ self.as_path().to_str().ok_or(io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ self.as_path().to_string_lossy()
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_path().as_os_str().as_bytes())
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self.as_path().as_os_str().as_bytes())
+ .map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self.as_path().as_os_str().as_bytes(), f)
+ }
+}
+
+impl Arg for &[u8] {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ str::from_utf8(self).map_err(|_utf8_err| io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ String::from_utf8_lossy(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(*self).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self, f)
+ }
+}
+
+impl Arg for &Vec<u8> {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ str::from_utf8(self).map_err(|_utf8_err| io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ String::from_utf8_lossy(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_slice()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self.as_slice()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ with_c_str(self, f)
+ }
+}
+
+impl Arg for Vec<u8> {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ str::from_utf8(self).map_err(|_utf8_err| io::Errno::INVAL)
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ String::from_utf8_lossy(self)
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Owned(
+ CString::new(self.as_slice()).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(
+ CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?,
+ ))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(&CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?)
+ }
+}
+
+#[cfg(feature = "itoa")]
+impl Arg for DecInt {
+ #[inline]
+ fn as_str(&self) -> io::Result<&str> {
+ Ok(self.as_str())
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Cow<'_, str> {
+ Cow::Borrowed(self.as_str())
+ }
+
+ #[inline]
+ fn as_cow_c_str(&self) -> io::Result<Cow<'_, CStr>> {
+ Ok(Cow::Borrowed(self.as_c_str()))
+ }
+
+ #[inline]
+ fn into_c_str<'b>(self) -> io::Result<Cow<'b, CStr>>
+ where
+ Self: 'b,
+ {
+ Ok(Cow::Owned(self.as_c_str().to_owned()))
+ }
+
+ #[inline]
+ fn into_with_c_str<T, F>(self, f: F) -> io::Result<T>
+ where
+ Self: Sized,
+ F: FnOnce(&CStr) -> io::Result<T>,
+ {
+ f(self.as_c_str())
+ }
+}
+
+/// Runs a closure with `bytes` passed in as a `&CStr`.
+#[inline]
+fn with_c_str<T, F>(bytes: &[u8], f: F) -> io::Result<T>
+where
+ F: FnOnce(&CStr) -> io::Result<T>,
+{
+ // Most paths are less than `SMALL_PATH_BUFFER_SIZE` long. The rest can go
+ // through the dynamic allocation path. If you're opening many files in a
+ // directory with a long path, consider opening the directory and using
+ // `openat` to open the files under it, which will avoid this, and is often
+ // faster in the OS as well.
+
+ // Test with >= so that we have room for the trailing NUL.
+ if bytes.len() >= SMALL_PATH_BUFFER_SIZE {
+ return with_c_str_slow_path(bytes, f);
+ }
+ let mut buffer: [u8; SMALL_PATH_BUFFER_SIZE] = [0_u8; SMALL_PATH_BUFFER_SIZE];
+ // Copy the bytes in; the buffer already has zeros for the trailing NUL.
+ buffer[..bytes.len()].copy_from_slice(bytes);
+ f(CStr::from_bytes_with_nul(&buffer[..=bytes.len()]).map_err(|_cstr_err| io::Errno::INVAL)?)
+}
+
+/// The slow path which handles any length. In theory OS's only support up
+/// to `PATH_MAX`, but we let the OS enforce that.
+#[cold]
+fn with_c_str_slow_path<T, F>(bytes: &[u8], f: F) -> io::Result<T>
+where
+ F: FnOnce(&CStr) -> io::Result<T>,
+{
+ f(&CString::new(bytes).map_err(|_cstr_err| io::Errno::INVAL)?)
+}
diff --git a/vendor/rustix/src/path/dec_int.rs b/vendor/rustix/src/path/dec_int.rs
new file mode 100644
index 000000000..4006fb06c
--- /dev/null
+++ b/vendor/rustix/src/path/dec_int.rs
@@ -0,0 +1,126 @@
+//! Efficient decimal integer formatting.
+//!
+//! # Safety
+//!
+//! This uses `CStr::from_bytes_with_nul_unchecked` and
+//! `str::from_utf8_unchecked`on the buffer that it filled itself.
+#![allow(unsafe_code)]
+
+use crate::ffi::CStr;
+use crate::imp::fd::{AsFd, AsRawFd};
+#[cfg(feature = "std")]
+use core::fmt;
+use core::fmt::Write;
+use itoa::{Buffer, Integer};
+#[cfg(feature = "std")]
+use std::ffi::OsStr;
+#[cfg(feature = "std")]
+#[cfg(unix)]
+use std::os::unix::ffi::OsStrExt;
+#[cfg(feature = "std")]
+#[cfg(target_os = "wasi")]
+use std::os::wasi::ffi::OsStrExt;
+#[cfg(feature = "std")]
+use std::path::Path;
+
+/// Format an integer into a decimal `Path` component, without constructing a
+/// temporary `PathBuf` or `String`.
+///
+/// This is used for opening paths such as `/proc/self/fd/<fd>` on Linux.
+///
+/// # Example
+///
+/// ```rust
+/// # #[cfg(feature = "path")]
+/// use rustix::path::DecInt;
+///
+/// # #[cfg(feature = "path")]
+/// assert_eq!(
+/// format!("hello {}", DecInt::new(9876).as_ref().display()),
+/// "hello 9876"
+/// );
+/// ```
+#[derive(Clone)]
+pub struct DecInt {
+ // 20 `u8`s is enough to hold the decimal ASCII representation of any
+ // `u64`, and we add one for a NUL terminator for `as_c_str`.
+ buf: [u8; 20 + 1],
+ len: usize,
+}
+
+impl DecInt {
+ /// Construct a new path component from an integer.
+ #[inline]
+ pub fn new<Int: Integer>(i: Int) -> Self {
+ let mut me = DecIntWriter(Self {
+ buf: [0; 20 + 1],
+ len: 0,
+ });
+ let mut buf = Buffer::new();
+ me.write_str(buf.format(i)).unwrap();
+ me.0
+ }
+
+ /// Construct a new path component from a file descriptor.
+ #[inline]
+ pub fn from_fd<Fd: AsFd>(fd: Fd) -> Self {
+ Self::new(fd.as_fd().as_raw_fd())
+ }
+
+ /// Return the raw byte buffer as a `&str`.
+ #[inline]
+ pub fn as_str(&self) -> &str {
+ // Safety: `DecInt` always holds a formatted decimal number, so it's
+ // always valid UTF-8.
+ unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
+ }
+
+ /// Return the raw byte buffer as a `&CStr`.
+ #[inline]
+ pub fn as_c_str(&self) -> &CStr {
+ let bytes_with_nul = &self.buf[..=self.len];
+ debug_assert!(CStr::from_bytes_with_nul(bytes_with_nul).is_ok());
+
+ // Safety: `self.buf` holds a single decimal ASCII representation and
+ // at least one extra NUL byte.
+ unsafe { CStr::from_bytes_with_nul_unchecked(bytes_with_nul) }
+ }
+
+ /// Return the raw byte buffer.
+ #[inline]
+ pub fn as_bytes(&self) -> &[u8] {
+ &self.buf[..self.len]
+ }
+}
+
+struct DecIntWriter(DecInt);
+
+impl core::fmt::Write for DecIntWriter {
+ #[inline]
+ fn write_str(&mut self, s: &str) -> core::fmt::Result {
+ match self.0.buf.get_mut(self.0.len..self.0.len + s.len()) {
+ Some(slice) => {
+ slice.copy_from_slice(s.as_bytes());
+ self.0.len += s.len();
+ Ok(())
+ }
+ None => Err(core::fmt::Error),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl AsRef<Path> for DecInt {
+ #[inline]
+ fn as_ref(&self) -> &Path {
+ let as_os_str: &OsStr = OsStrExt::from_bytes(&self.buf[..self.len]);
+ Path::new(as_os_str)
+ }
+}
+
+#[cfg(feature = "std")]
+impl fmt::Debug for DecInt {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.as_str().fmt(fmt)
+ }
+}
diff --git a/vendor/rustix/src/path/mod.rs b/vendor/rustix/src/path/mod.rs
new file mode 100644
index 000000000..bd6e9fc8b
--- /dev/null
+++ b/vendor/rustix/src/path/mod.rs
@@ -0,0 +1,11 @@
+//! Filesystem path operations.
+
+mod arg;
+#[cfg(feature = "itoa")]
+mod dec_int;
+
+pub use arg::Arg;
+#[cfg(feature = "itoa")]
+pub use dec_int::DecInt;
+
+pub(crate) const SMALL_PATH_BUFFER_SIZE: usize = 256;
diff --git a/vendor/rustix/src/process/chdir.rs b/vendor/rustix/src/process/chdir.rs
new file mode 100644
index 000000000..d8e251074
--- /dev/null
+++ b/vendor/rustix/src/process/chdir.rs
@@ -0,0 +1,72 @@
+use crate::ffi::CString;
+use crate::path::SMALL_PATH_BUFFER_SIZE;
+use crate::{imp, io, path};
+use alloc::vec::Vec;
+#[cfg(not(target_os = "fuchsia"))]
+use imp::fd::AsFd;
+
+/// `chdir(path)`—Change the current working directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/chdir.2.html
+#[inline]
+pub fn chdir<P: path::Arg>(path: P) -> io::Result<()> {
+ path.into_with_c_str(imp::process::syscalls::chdir)
+}
+
+/// `fchdir(fd)`—Change the current working directory.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fchdir.2.html
+#[cfg(not(target_os = "fuchsia"))]
+#[inline]
+pub fn fchdir<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::process::syscalls::fchdir(fd.as_fd())
+}
+
+/// `getcwd()`—Return the current working directory.
+///
+/// If `reuse` is non-empty, reuse its buffer to store the result if possible.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/getcwd.3.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn getcwd<B: Into<Vec<u8>>>(reuse: B) -> io::Result<CString> {
+ _getcwd(reuse.into())
+}
+
+fn _getcwd(mut buffer: Vec<u8>) -> io::Result<CString> {
+ // This code would benefit from having a better way to read into
+ // uninitialized memory, but that requires `unsafe`.
+ buffer.clear();
+ buffer.reserve(SMALL_PATH_BUFFER_SIZE);
+ buffer.resize(buffer.capacity(), 0_u8);
+
+ loop {
+ match imp::process::syscalls::getcwd(&mut buffer) {
+ Err(io::Errno::RANGE) => {
+ buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially
+ buffer.resize(buffer.capacity(), 0_u8);
+ }
+ Ok(_) => {
+ let len = buffer.iter().position(|x| *x == b'\0').unwrap();
+ buffer.resize(len, 0_u8);
+ return Ok(CString::new(buffer).unwrap());
+ }
+ Err(errno) => return Err(errno),
+ }
+ }
+}
diff --git a/vendor/rustix/src/process/exit.rs b/vendor/rustix/src/process/exit.rs
new file mode 100644
index 000000000..26a2340ab
--- /dev/null
+++ b/vendor/rustix/src/process/exit.rs
@@ -0,0 +1,34 @@
+use crate::imp;
+
+/// `EXIT_SUCCESS` for use with [`exit`].
+///
+/// [`exit`]: std::process::exit
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdlib.h.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/exit.3.html
+pub const EXIT_SUCCESS: i32 = imp::process::types::EXIT_SUCCESS;
+
+/// `EXIT_FAILURE` for use with [`exit`].
+///
+/// [`exit`]: std::process::exit
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdlib.h.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/exit.3.html
+pub const EXIT_FAILURE: i32 = imp::process::types::EXIT_FAILURE;
+
+/// The exit status used by a process terminated with `SIGABRT` signal.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://tldp.org/LDP/abs/html/exitcodes.html
+#[cfg(not(target_os = "wasi"))]
+pub const EXIT_SIGNALED_SIGABRT: i32 = imp::process::types::EXIT_SIGNALED_SIGABRT;
diff --git a/vendor/rustix/src/process/id.rs b/vendor/rustix/src/process/id.rs
new file mode 100644
index 000000000..5f6ff5bfb
--- /dev/null
+++ b/vendor/rustix/src/process/id.rs
@@ -0,0 +1,298 @@
+//! Unix user, group, and process identifiers.
+//!
+//! # Safety
+//!
+//! The `Uid`, `Gid`, and `Pid` types can be constructed from raw integers,
+//! which is marked unsafe because actual OS's assign special meaning to some
+//! integer values.
+#![allow(unsafe_code)]
+
+use crate::{imp, io};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use imp::process::types::RawCpuid;
+
+/// The raw integer value of a Unix user ID.
+pub use imp::process::types::RawUid;
+
+/// The raw integer value of a Unix group ID.
+pub use imp::process::types::RawGid;
+
+/// The raw integer value of a Unix process ID.
+pub use imp::process::types::RawPid;
+
+/// The raw integer value of a Unix process ID.
+pub use imp::process::types::RawNonZeroPid;
+
+/// `uid_t`—A Unix user ID.
+#[repr(transparent)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
+pub struct Uid(RawUid);
+
+/// `gid_t`—A Unix group ID.
+#[repr(transparent)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
+pub struct Gid(RawGid);
+
+/// `pid_t`—A non-zero Unix process ID.
+///
+/// This is a pid, and not a pidfd. It is not a file descriptor, and the
+/// process it refers to could disappear at any time and be replaced by
+/// another, unrelated, process.
+#[repr(transparent)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
+pub struct Pid(RawNonZeroPid);
+
+/// A Linux CPU ID.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[repr(transparent)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
+pub struct Cpuid(RawCpuid);
+
+impl Uid {
+ /// A `Uid` corresponding to the root user (uid 0).
+ pub const ROOT: Self = Self(0);
+
+ /// Converts a `RawUid` into a `Uid`.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be the value of a valid Unix user ID.
+ #[inline]
+ pub const unsafe fn from_raw(raw: RawUid) -> Self {
+ Self(raw)
+ }
+
+ /// Converts a `Uid` into a `RawUid`.
+ #[inline]
+ pub const fn as_raw(self) -> RawUid {
+ self.0
+ }
+
+ /// Test whether this uid represents the root user (uid 0).
+ #[inline]
+ pub const fn is_root(self) -> bool {
+ self.0 == Self::ROOT.0
+ }
+}
+
+impl Gid {
+ /// A `Gid` corresponding to the root group (gid 0).
+ pub const ROOT: Self = Self(0);
+
+ /// Converts a `RawGid` into a `Gid`.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be the value of a valid Unix group ID.
+ #[inline]
+ pub const unsafe fn from_raw(raw: RawGid) -> Self {
+ Self(raw)
+ }
+
+ /// Converts a `Gid` into a `RawGid`.
+ #[inline]
+ pub const fn as_raw(self) -> RawGid {
+ self.0
+ }
+
+ /// Test whether this gid represents the root group (gid 0).
+ #[inline]
+ pub const fn is_root(self) -> bool {
+ self.0 == Self::ROOT.0
+ }
+}
+
+impl Pid {
+ /// A `Pid` corresponding to the init process (pid 1).
+ pub const INIT: Self = Self(
+ // Safety: The init process' pid is always valid.
+ unsafe { RawNonZeroPid::new_unchecked(1) },
+ );
+
+ /// Converts a `RawPid` into a `Pid`.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be the value of a valid Unix process ID, or zero.
+ #[inline]
+ pub const unsafe fn from_raw(raw: RawPid) -> Option<Self> {
+ match RawNonZeroPid::new(raw) {
+ Some(pid) => Some(Self(pid)),
+ None => None,
+ }
+ }
+
+ /// Converts a known non-zero `RawPid` into a `Pid`.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be the value of a valid Unix process ID. It must not be
+ /// zero.
+ #[inline]
+ pub const unsafe fn from_raw_nonzero(raw: RawNonZeroPid) -> Self {
+ Self(raw)
+ }
+
+ /// Creates a `Pid` holding the ID of the given child process.
+ #[cfg(feature = "std")]
+ #[inline]
+ pub fn from_child(child: &std::process::Child) -> Self {
+ let id = child.id();
+ debug_assert_ne!(id, 0);
+
+ // Safety: We know the returned ID is valid because it came directly
+ // from an OS API.
+ unsafe { Self::from_raw_nonzero(RawNonZeroPid::new_unchecked(id as _)) }
+ }
+
+ /// Converts a `Pid` into a `RawNonZeroPid`.
+ #[inline]
+ pub const fn as_raw_nonzero(self) -> RawNonZeroPid {
+ self.0
+ }
+
+ /// Converts an `Option<Pid>` into a `RawPid`.
+ #[inline]
+ pub fn as_raw(pid: Option<Self>) -> RawPid {
+ pid.map_or(0, |pid| pid.0.get())
+ }
+
+ /// Test whether this pid represents the init process (pid 0).
+ #[inline]
+ pub const fn is_init(self) -> bool {
+ self.0.get() == Self::INIT.0.get()
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+impl Cpuid {
+ /// Converts a `RawCpuid` into a `Cpuid`.
+ ///
+ /// # Safety
+ ///
+ /// `raw` must be the value of a valid Linux CPU ID.
+ #[inline]
+ pub const unsafe fn from_raw(raw: RawCpuid) -> Self {
+ Self(raw)
+ }
+
+ /// Converts a `Cpuid` into a `RawCpuid`.
+ #[inline]
+ pub const fn as_raw(self) -> RawCpuid {
+ self.0
+ }
+}
+
+/// `getuid()`—Returns the process' real user ID.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getuid.2.html
+#[inline]
+#[must_use]
+pub fn getuid() -> Uid {
+ imp::process::syscalls::getuid()
+}
+
+/// `geteuid()`—Returns the process' effective user ID.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/geteuid.2.html
+#[inline]
+#[must_use]
+pub fn geteuid() -> Uid {
+ imp::process::syscalls::geteuid()
+}
+
+/// `getgid()`—Returns the process' real group ID.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getgid.2.html
+#[inline]
+#[must_use]
+pub fn getgid() -> Gid {
+ imp::process::syscalls::getgid()
+}
+
+/// `getegid()`—Returns the process' effective group ID.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getegid.2.html
+#[inline]
+#[must_use]
+pub fn getegid() -> Gid {
+ imp::process::syscalls::getegid()
+}
+
+/// `getpid()`—Returns the process' ID.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getpid.2.html
+#[inline]
+#[must_use]
+pub fn getpid() -> Pid {
+ imp::process::syscalls::getpid()
+}
+
+/// `getppid()`—Returns the parent process' ID.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getppid.2.html
+#[inline]
+#[must_use]
+pub fn getppid() -> Option<Pid> {
+ imp::process::syscalls::getppid()
+}
+
+/// `setsid()`—Create a new session.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/setsid.2.html
+#[inline]
+pub fn setsid() -> io::Result<Pid> {
+ imp::process::syscalls::setsid()
+}
+
+// translate_fchown_args returns the raw value of the IDs. In case of `None`
+// it returns `u32::MAX` since it has the same bit pattern as `-1` indicating
+// no change to the owner/group ID.
+pub(crate) fn translate_fchown_args(owner: Option<Uid>, group: Option<Gid>) -> (u32, u32) {
+ let ow = match owner {
+ Some(o) => o.as_raw(),
+ None => u32::MAX,
+ };
+
+ let gr = match group {
+ Some(g) => g.as_raw(),
+ None => u32::MAX,
+ };
+
+ (ow, gr)
+}
diff --git a/vendor/rustix/src/process/kill.rs b/vendor/rustix/src/process/kill.rs
new file mode 100644
index 000000000..d8daaf8da
--- /dev/null
+++ b/vendor/rustix/src/process/kill.rs
@@ -0,0 +1,51 @@
+use crate::process::Pid;
+use crate::{imp, io};
+
+pub use imp::process::types::Signal;
+
+/// `kill(pid, sig)`—Sends a signal to a process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/kill.2.html
+#[inline]
+#[doc(alias = "kill")]
+pub fn kill_process(pid: Pid, sig: Signal) -> io::Result<()> {
+ imp::process::syscalls::kill_process(pid, sig)
+}
+
+/// `kill(-pid, sig)`—Sends a signal to all processes in a process group.
+///
+/// If `pid` is 1, this sends a signal to all processes the current process
+/// has permission to send signals to, except process `1`, possibly other
+/// system-specific processes, and on some systems, the current process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/kill.2.html
+#[inline]
+#[doc(alias = "kill")]
+pub fn kill_process_group(pid: Pid, sig: Signal) -> io::Result<()> {
+ imp::process::syscalls::kill_process_group(pid, sig)
+}
+
+/// `kill(0, sig)`—Sends a signal to all processes in the current process
+/// group.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/kill.2.html
+#[inline]
+#[doc(alias = "kill")]
+pub fn kill_current_process_group(sig: Signal) -> io::Result<()> {
+ imp::process::syscalls::kill_current_process_group(sig)
+}
diff --git a/vendor/rustix/src/process/membarrier.rs b/vendor/rustix/src/process/membarrier.rs
new file mode 100644
index 000000000..0062f273b
--- /dev/null
+++ b/vendor/rustix/src/process/membarrier.rs
@@ -0,0 +1,93 @@
+//! The Linux `membarrier` syscall.
+//!
+//! # Safety
+//!
+//! This file defines an enum and a bitflags type that represent the same
+//! set of values and are kept in sync.
+#![allow(unsafe_code)]
+
+use crate::process::Cpuid;
+use crate::{imp, io};
+
+pub use imp::process::types::MembarrierCommand;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags::bitflags! {
+ /// A result from [`membarrier_query`].
+ ///
+ /// These flags correspond to values of [`MembarrierCommand`] which are
+ /// supported in the OS.
+ pub struct MembarrierQuery: u32 {
+ /// `MEMBARRIER_CMD_GLOBAL`
+ #[doc(alias = "SHARED")]
+ #[doc(alias = "MEMBARRIER_CMD_SHARED")]
+ const GLOBAL = MembarrierCommand::Global as _;
+ /// `MEMBARRIER_CMD_GLOBAL_EXPEDITED`
+ const GLOBAL_EXPEDITED = MembarrierCommand::GlobalExpedited as _;
+ /// `MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED`
+ const REGISTER_GLOBAL_EXPEDITED = MembarrierCommand::RegisterGlobalExpedited as _;
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED`
+ const PRIVATE_EXPEDITED = MembarrierCommand::PrivateExpedited as _;
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED`
+ const REGISTER_PRIVATE_EXPEDITED = MembarrierCommand::RegisterPrivateExpedited as _;
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE`
+ const PRIVATE_EXPEDITED_SYNC_CORE = MembarrierCommand::PrivateExpeditedSyncCore as _;
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE`
+ const REGISTER_PRIVATE_EXPEDITED_SYNC_CORE = MembarrierCommand::RegisterPrivateExpeditedSyncCore as _;
+ /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
+ const PRIVATE_EXPEDITED_RSEQ = MembarrierCommand::PrivateExpeditedRseq as _;
+ /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
+ const REGISTER_PRIVATE_EXPEDITED_RSEQ = MembarrierCommand::RegisterPrivateExpeditedRseq as _;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+impl MembarrierQuery {
+ /// Test whether this query result contains the given command.
+ #[inline]
+ pub fn contains_command(self, cmd: MembarrierCommand) -> bool {
+ // Safety: `MembarrierCommand` is an enum that only contains values
+ // also valid in `MembarrierQuery`.
+ self.contains(unsafe { Self::from_bits_unchecked(cmd as _) })
+ }
+}
+
+/// `membarrier(MEMBARRIER_CMD_QUERY, 0, 0)`—Query the supported `membarrier`
+/// commands.
+///
+/// This function doesn't return a `Result` because it always succeeds; if
+/// the underlying OS doesn't support the `membarrier` syscall, it returns
+/// an empty `MembarrierQuery` value.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
+#[inline]
+#[doc(alias = "MEMBARRIER_CMD_QUERY")]
+pub fn membarrier_query() -> MembarrierQuery {
+ imp::process::syscalls::membarrier_query()
+}
+
+/// `membarrier(cmd, 0, 0)`—Perform a memory barrier.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
+#[inline]
+pub fn membarrier(cmd: MembarrierCommand) -> io::Result<()> {
+ imp::process::syscalls::membarrier(cmd)
+}
+
+/// `membarrier(cmd, MEMBARRIER_CMD_FLAG_CPU, cpu)`—Perform a memory barrier
+/// with a specific CPU.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
+#[inline]
+pub fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
+ imp::process::syscalls::membarrier_cpu(cmd, cpu)
+}
diff --git a/vendor/rustix/src/process/mod.rs b/vendor/rustix/src/process/mod.rs
new file mode 100644
index 000000000..45673c0ea
--- /dev/null
+++ b/vendor/rustix/src/process/mod.rs
@@ -0,0 +1,76 @@
+//! Process-associated operations.
+
+#[cfg(not(target_os = "wasi"))]
+mod chdir;
+mod exit;
+#[cfg(not(target_os = "wasi"))] // WASI doesn't have get[gpu]id.
+mod id;
+#[cfg(not(target_os = "wasi"))]
+mod kill;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod membarrier;
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] // WASI doesn't have [gs]etpriority.
+mod priority;
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+mod rlimit;
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+mod sched;
+mod sched_yield;
+#[cfg(not(target_os = "wasi"))] // WASI doesn't have uname.
+mod uname;
+#[cfg(not(target_os = "wasi"))]
+mod wait;
+
+#[cfg(not(target_os = "wasi"))]
+pub use chdir::chdir;
+#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
+pub use chdir::fchdir;
+#[cfg(not(target_os = "wasi"))]
+pub use chdir::getcwd;
+#[cfg(not(target_os = "wasi"))]
+pub use exit::EXIT_SIGNALED_SIGABRT;
+pub use exit::{EXIT_FAILURE, EXIT_SUCCESS};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use id::Cpuid;
+#[cfg(not(target_os = "wasi"))]
+pub use id::{
+ getegid, geteuid, getgid, getpid, getppid, getuid, setsid, Gid, Pid, RawGid, RawNonZeroPid,
+ RawPid, RawUid, Uid,
+};
+#[cfg(not(target_os = "wasi"))]
+pub use kill::{kill_current_process_group, kill_process, kill_process_group, Signal};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use membarrier::{
+ membarrier, membarrier_cpu, membarrier_query, MembarrierCommand, MembarrierQuery,
+};
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+pub use priority::nice;
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+pub use priority::{
+ getpriority_pgrp, getpriority_process, getpriority_user, setpriority_pgrp, setpriority_process,
+ setpriority_user,
+};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use rlimit::prlimit;
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+pub use rlimit::{getrlimit, setrlimit, Resource, Rlimit};
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "linux",
+))]
+pub use sched::{sched_getaffinity, sched_setaffinity, CpuSet};
+pub use sched_yield::sched_yield;
+#[cfg(not(target_os = "wasi"))]
+pub use uname::{uname, Uname};
+#[cfg(not(target_os = "wasi"))]
+pub use wait::{wait, waitpid, WaitOptions, WaitStatus};
+
+#[cfg(not(target_os = "wasi"))]
+pub(crate) use id::translate_fchown_args;
diff --git a/vendor/rustix/src/process/priority.rs b/vendor/rustix/src/process/priority.rs
new file mode 100644
index 000000000..ae43a0b75
--- /dev/null
+++ b/vendor/rustix/src/process/priority.rs
@@ -0,0 +1,131 @@
+use crate::process::{Pid, Uid};
+use crate::{imp, io};
+
+/// `nice()`—Adjust the scheduling priority of the current process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/nice.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/nice.2.html
+#[inline]
+pub fn nice(inc: i32) -> io::Result<i32> {
+ imp::process::syscalls::nice(inc)
+}
+
+/// `getpriority(PRIO_USER, uid)`—Get the scheduling priority of the given
+/// user.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpriority.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getpriority.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+#[doc(alias = "getpriority")]
+pub fn getpriority_user(uid: Uid) -> io::Result<i32> {
+ imp::process::syscalls::getpriority_user(uid)
+}
+
+/// `getpriority(PRIO_PGRP, gid)`—Get the scheduling priority of the given
+/// process group.
+///
+/// A `pgid` of `None` means the process group of the calling process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpriority.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getpriority.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+#[doc(alias = "getpriority")]
+pub fn getpriority_pgrp(pgid: Option<Pid>) -> io::Result<i32> {
+ imp::process::syscalls::getpriority_pgrp(pgid)
+}
+
+/// `getpriority(PRIO_PROCESS, pid)`—Get the scheduling priority of the given
+/// process.
+///
+/// A `pid` of `None` means the calling process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpriority.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getpriority.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+#[doc(alias = "getpriority")]
+pub fn getpriority_process(pid: Option<Pid>) -> io::Result<i32> {
+ imp::process::syscalls::getpriority_process(pid)
+}
+
+/// `setpriority(PRIO_USER, uid)`—Get the scheduling priority of the given
+/// user.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpriority.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/setpriority.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+#[doc(alias = "setpriority")]
+pub fn setpriority_user(uid: Uid, priority: i32) -> io::Result<()> {
+ imp::process::syscalls::setpriority_user(uid, priority)
+}
+
+/// `setpriority(PRIO_PGRP, pgid)`—Get the scheduling priority of the given
+/// process group.
+///
+/// A `pgid` of `None` means the process group of the calling process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpriority.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/setpriority.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+#[doc(alias = "setpriority")]
+pub fn setpriority_pgrp(pgid: Option<Pid>, priority: i32) -> io::Result<()> {
+ imp::process::syscalls::setpriority_pgrp(pgid, priority)
+}
+
+/// `setpriority(PRIO_PROCESS, pid)`—Get the scheduling priority of the given
+/// process.
+///
+/// A `pid` of `None` means the calling process.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+/// - [Apple]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpriority.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/setpriority.2.html
+/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html
+#[cfg(not(target_os = "redox"))]
+#[inline]
+#[doc(alias = "setpriority")]
+pub fn setpriority_process(pid: Option<Pid>, priority: i32) -> io::Result<()> {
+ imp::process::syscalls::setpriority_process(pid, priority)
+}
diff --git a/vendor/rustix/src/process/rlimit.rs b/vendor/rustix/src/process/rlimit.rs
new file mode 100644
index 000000000..ffb22d2ae
--- /dev/null
+++ b/vendor/rustix/src/process/rlimit.rs
@@ -0,0 +1,53 @@
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::process::Pid;
+use crate::{imp, io};
+
+pub use imp::process::types::Resource;
+
+/// `struct rlimit`—Current and maximum values used in [`getrlimit`],
+/// [`setrlimit`], and [`prlimit`].
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Rlimit {
+ /// Current effective, "soft", limit.
+ pub current: Option<u64>,
+ /// Maximum, "hard", value that `current` may be dynamically increased to.
+ pub maximum: Option<u64>,
+}
+
+/// `getrlimit(resource)`—Get a process resource limit value.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/getrlimit.2.html
+#[inline]
+pub fn getrlimit(resource: Resource) -> Rlimit {
+ imp::process::syscalls::getrlimit(resource)
+}
+
+/// `setrlimit(resource, new)`—Set a process resource limit value.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setrlimit.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/setrlimit.2.html
+#[inline]
+pub fn setrlimit(resource: Resource, new: Rlimit) -> io::Result<()> {
+ imp::process::syscalls::setrlimit(resource, new)
+}
+
+/// `prlimit(pid, resource, new)`—Get and set a process resource limit value.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/prlimit.2.html
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub fn prlimit(pid: Option<Pid>, resource: Resource, new: Rlimit) -> io::Result<Rlimit> {
+ imp::process::syscalls::prlimit(pid, resource, new)
+}
diff --git a/vendor/rustix/src/process/sched.rs b/vendor/rustix/src/process/sched.rs
new file mode 100644
index 000000000..56ba95a6b
--- /dev/null
+++ b/vendor/rustix/src/process/sched.rs
@@ -0,0 +1,110 @@
+use crate::process::Pid;
+use crate::{imp, io};
+
+/// `CpuSet` represents a bit-mask of CPUs.
+///
+/// `CpuSet`s are used by [`sched_setaffinity`] and [`sched_getaffinity`], for
+/// example.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/CPU_SET.3.html
+/// [`sched_setaffinity`]: crate::process::sched_setaffinity
+/// [`sched_getaffinity`]: crate::process::sched_getaffinity
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct CpuSet {
+ cpu_set: imp::process::types::RawCpuSet,
+}
+
+impl CpuSet {
+ /// The maximum number of CPU in `CpuSet`.
+ pub const MAX_CPU: usize = imp::process::types::CPU_SETSIZE;
+
+ /// Create a new and empty `CpuSet`.
+ #[inline]
+ pub fn new() -> Self {
+ Self {
+ cpu_set: imp::process::types::raw_cpu_set_new(),
+ }
+ }
+
+ /// Test to see if a CPU is in the `CpuSet`.
+ ///
+ /// `field` is the CPU id to test.
+ #[inline]
+ pub fn is_set(&self, field: usize) -> bool {
+ imp::process::cpu_set::CPU_ISSET(field, &self.cpu_set)
+ }
+
+ /// Add a CPU to `CpuSet`.
+ ///
+ /// `field` is the CPU id to add.
+ #[inline]
+ pub fn set(&mut self, field: usize) {
+ imp::process::cpu_set::CPU_SET(field, &mut self.cpu_set)
+ }
+
+ /// Remove a CPU from `CpuSet`.
+ ///
+ /// `field` is the CPU id to remove.
+ #[inline]
+ pub fn unset(&mut self, field: usize) {
+ imp::process::cpu_set::CPU_CLR(field, &mut self.cpu_set)
+ }
+
+ /// Count the number of CPUs set in the `CpuSet`.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+ pub fn count(&self) -> u32 {
+ imp::process::cpu_set::CPU_COUNT(&self.cpu_set)
+ }
+
+ /// Zeroes the `CpuSet`.
+ #[inline]
+ pub fn clear(&mut self) {
+ imp::process::cpu_set::CPU_ZERO(&mut self.cpu_set)
+ }
+}
+
+impl Default for CpuSet {
+ #[inline]
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+/// `sched_setaffinity(pid, cpuset)`—Set a thread's CPU affinity mask.
+///
+/// `pid` is the thread ID to update. If pid is `None`, then the current thread
+/// is updated.
+///
+/// The `CpuSet` argument specifies the set of CPUs on which the thread will
+/// be eligible to run.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html
+#[inline]
+pub fn sched_setaffinity(pid: Option<Pid>, cpuset: &CpuSet) -> io::Result<()> {
+ imp::process::syscalls::sched_setaffinity(pid, &cpuset.cpu_set)
+}
+
+/// `sched_getaffinity(pid)`—Get a thread's CPU affinity mask.
+///
+/// `pid` is the thread ID to check. If pid is `None`, then the current thread
+/// is checked.
+///
+/// Returns the set of CPUs on which the thread is eligible to run.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/sched_getaffinity.2.html
+#[inline]
+pub fn sched_getaffinity(pid: Option<Pid>) -> io::Result<CpuSet> {
+ let mut cpuset = CpuSet::new();
+ imp::process::syscalls::sched_getaffinity(pid, &mut cpuset.cpu_set).and(Ok(cpuset))
+}
diff --git a/vendor/rustix/src/process/sched_yield.rs b/vendor/rustix/src/process/sched_yield.rs
new file mode 100644
index 000000000..24367773f
--- /dev/null
+++ b/vendor/rustix/src/process/sched_yield.rs
@@ -0,0 +1,16 @@
+use crate::imp;
+
+/// `sched_yield()`—Hints to the OS that other processes should run.
+///
+/// This function always succeeds.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/sched_yield.2.html
+#[inline]
+pub fn sched_yield() {
+ imp::process::syscalls::sched_yield()
+}
diff --git a/vendor/rustix/src/process/uname.rs b/vendor/rustix/src/process/uname.rs
new file mode 100644
index 000000000..a17d0be7a
--- /dev/null
+++ b/vendor/rustix/src/process/uname.rs
@@ -0,0 +1,101 @@
+//! Uname support.
+//!
+//! # Safety
+//!
+//! This function converts from `struct utsname` fields provided from the
+//! kernel into `&str` references, which assumes that they're NUL-terminated.
+#![allow(unsafe_code)]
+
+use crate::ffi::CStr;
+use crate::imp;
+use core::fmt;
+
+/// `uname()`—Returns high-level information about the runtime OS and
+/// hardware.
+#[inline]
+pub fn uname() -> Uname {
+ Uname(imp::process::syscalls::uname())
+}
+
+/// `struct utsname`—Return type for [`uname`].
+#[doc(alias = "utsname")]
+pub struct Uname(imp::process::types::RawUname);
+
+impl Uname {
+ /// `sysname`—Operating system release name
+ #[inline]
+ pub fn sysname(&self) -> &CStr {
+ Self::to_cstr(self.0.sysname.as_ptr().cast())
+ }
+
+ /// `nodename`—Name with vague meaning
+ ///
+ /// This is intended to be a network name, however it's unable to convey
+ /// information about hosts that have multiple names, or any information
+ /// about where the names are visible.
+ #[inline]
+ pub fn nodename(&self) -> &CStr {
+ Self::to_cstr(self.0.nodename.as_ptr().cast())
+ }
+
+ /// `release`—Operating system release version string
+ #[inline]
+ pub fn release(&self) -> &CStr {
+ Self::to_cstr(self.0.release.as_ptr().cast())
+ }
+
+ /// `version`—Operating system build identifiers
+ #[inline]
+ pub fn version(&self) -> &CStr {
+ Self::to_cstr(self.0.version.as_ptr().cast())
+ }
+
+ /// `machine`—Hardware architecture identifier
+ #[inline]
+ pub fn machine(&self) -> &CStr {
+ Self::to_cstr(self.0.machine.as_ptr().cast())
+ }
+
+ /// `domainname`—NIS or YP domain identifier
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+ pub fn domainname(&self) -> &CStr {
+ Self::to_cstr(self.0.domainname.as_ptr().cast())
+ }
+
+ #[inline]
+ fn to_cstr<'a>(ptr: *const u8) -> &'a CStr {
+ // Safety: Strings returned from the kernel are always NUL-terminated.
+ unsafe { CStr::from_ptr(ptr.cast()) }
+ }
+}
+
+impl fmt::Debug for Uname {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ #[cfg(not(any(target_os = "android", target_os = "linux")))]
+ {
+ write!(
+ fmt,
+ "{} {} {} {} {}",
+ self.sysname().to_string_lossy(),
+ self.nodename().to_string_lossy(),
+ self.release().to_string_lossy(),
+ self.version().to_string_lossy(),
+ self.machine().to_string_lossy(),
+ )
+ }
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ {
+ write!(
+ fmt,
+ "{} {} {} {} {} {}",
+ self.sysname().to_string_lossy(),
+ self.nodename().to_string_lossy(),
+ self.release().to_string_lossy(),
+ self.version().to_string_lossy(),
+ self.machine().to_string_lossy(),
+ self.domainname().to_string_lossy(),
+ )
+ }
+ }
+}
diff --git a/vendor/rustix/src/process/wait.rs b/vendor/rustix/src/process/wait.rs
new file mode 100644
index 000000000..383b34d06
--- /dev/null
+++ b/vendor/rustix/src/process/wait.rs
@@ -0,0 +1,129 @@
+use crate::process::Pid;
+use crate::{imp, io};
+use bitflags::bitflags;
+
+bitflags! {
+ /// Options for modifying the behavior of wait/waitpid
+ pub struct WaitOptions: u32 {
+ /// Return immediately if no child has exited.
+ const NOHANG = imp::process::wait::WNOHANG as _;
+ /// Return if a child has stopped (but not traced via `ptrace(2)`)
+ const UNTRACED = imp::process::wait::WUNTRACED as _;
+ /// Return if a stopped child has been resumed by delivery of `SIGCONT`
+ const CONTINUED = imp::process::wait::WCONTINUED as _;
+ }
+}
+
+/// the status of the child processes the caller waited on
+#[derive(Debug, Clone, Copy)]
+pub struct WaitStatus(u32);
+
+impl WaitStatus {
+ /// create a `WaitStatus` out of an integer.
+ #[inline]
+ pub(crate) fn new(status: u32) -> Self {
+ Self(status)
+ }
+
+ /// Converts a `WaitStatus` into its raw representation as an integer.
+ #[inline]
+ pub const fn as_raw(self) -> u32 {
+ self.0
+ }
+
+ /// Returns whether the process is currently stopped.
+ #[inline]
+ pub fn stopped(self) -> bool {
+ imp::process::wait::WIFSTOPPED(self.0 as _)
+ }
+
+ /// Returns whether the process has continued from a job control stop.
+ #[inline]
+ pub fn continued(self) -> bool {
+ imp::process::wait::WIFCONTINUED(self.0 as _)
+ }
+
+ /// Returns the number of the signal that stopped the process,
+ /// if the process was stopped by a signal.
+ #[inline]
+ pub fn stopping_signal(self) -> Option<u32> {
+ if self.stopped() {
+ Some(imp::process::wait::WSTOPSIG(self.0 as _) as _)
+ } else {
+ None
+ }
+ }
+
+ /// Returns the exit status number returned by the process,
+ /// if it exited normally.
+ #[inline]
+ pub fn exit_status(self) -> Option<u32> {
+ if imp::process::wait::WIFEXITED(self.0 as _) {
+ Some(imp::process::wait::WEXITSTATUS(self.0 as _) as _)
+ } else {
+ None
+ }
+ }
+
+ /// Returns the number of the signal that terminated the process,
+ /// if the process was terminated by a signal.
+ #[inline]
+ pub fn terminating_signal(self) -> Option<u32> {
+ if imp::process::wait::WIFSIGNALED(self.0 as _) {
+ Some(imp::process::wait::WTERMSIG(self.0 as _) as _)
+ } else {
+ None
+ }
+ }
+}
+
+/// `waitpid(pid, waitopts)`—Wait for a specific process to change state.
+///
+/// If the pid is `None`, the call will wait for any child process whose
+/// process group id matches that of the calling process.
+///
+/// If the pid is equal to `RawPid::MAX`, the call will wait for any child
+/// process.
+///
+/// Otherwise if the `wrapping_neg` of pid is less than pid, the call will wait
+/// for any child process with a group ID equal to the `wrapping_neg` of `pid`.
+///
+/// Otherwise, the call will wait for the child process with the given pid.
+///
+/// On Success, returns the status of the selected process.
+///
+/// If `NOHANG` was specified in the options, and the selected child process
+/// didn't change state, returns `None`.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/waitpid.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn waitpid(pid: Option<Pid>, waitopts: WaitOptions) -> io::Result<Option<WaitStatus>> {
+ Ok(imp::process::syscalls::waitpid(pid, waitopts)?.map(|(_, status)| status))
+}
+
+/// `wait(waitopts)`—Wait for any of the children of calling process to
+/// change state.
+///
+/// On success, returns the pid of the child process whose state changed, and
+/// the status of said process.
+///
+/// If `NOHANG` was specified in the options, and the selected child process
+/// didn't change state, returns `None`.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/waitpid.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn wait(waitopts: WaitOptions) -> io::Result<Option<(Pid, WaitStatus)>> {
+ imp::process::syscalls::wait(waitopts)
+}
diff --git a/vendor/rustix/src/rand/getrandom.rs b/vendor/rustix/src/rand/getrandom.rs
new file mode 100644
index 000000000..f5d7e365d
--- /dev/null
+++ b/vendor/rustix/src/rand/getrandom.rs
@@ -0,0 +1,21 @@
+use crate::{imp, io};
+
+/// `GRND_*`
+pub use imp::rand::types::GetRandomFlags;
+
+/// `getrandom(buf, flags)`—Reads a sequence of random bytes.
+///
+/// This is a very low-level API which may be difficult to use correctly. Most
+/// users should prefer to use [`getrandom`] or [`rand`] APIs instead.
+///
+/// [`getrandom`]: https://crates.io/crates/getrandom
+/// [`rand`]: https://crates.io/crates/rand
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/getrandom.2.html
+#[inline]
+pub fn getrandom(buf: &mut [u8], flags: GetRandomFlags) -> io::Result<usize> {
+ imp::rand::syscalls::getrandom(buf, flags)
+}
diff --git a/vendor/rustix/src/rand/mod.rs b/vendor/rustix/src/rand/mod.rs
new file mode 100644
index 000000000..b8a1320a8
--- /dev/null
+++ b/vendor/rustix/src/rand/mod.rs
@@ -0,0 +1,7 @@
+//! Random-related operations.
+
+#[cfg(any(linux_raw, all(libc, target_os = "linux")))]
+mod getrandom;
+
+#[cfg(any(linux_raw, all(libc, target_os = "linux")))]
+pub use getrandom::{getrandom, GetRandomFlags};
diff --git a/vendor/rustix/src/runtime.rs b/vendor/rustix/src/runtime.rs
new file mode 100644
index 000000000..187da6341
--- /dev/null
+++ b/vendor/rustix/src/runtime.rs
@@ -0,0 +1,265 @@
+//! Low-level implementation details for libc-like runtime libraries such as
+//! [origin].
+//!
+//! These functions are for implementing thread-local storage (TLS), managing
+//! threads, loaded libraries, and other process-wide resources. Most of
+//! `rustix` doesn't care about what other libraries are linked into the
+//! program or what they're doing, but the features in this module generally
+//! can only be used by one entity within a process.
+//!
+//! The API for these functions is not stable, and this module is
+//! `doc(hidden)`.
+//!
+//! [origin]: https://github.com/sunfishcode/mustang/tree/main/origin
+//!
+//! # Safety
+//!
+//! This module is intended to be used for implementing a runtime library such
+//! as libc. Use of these features for any other purpose is likely to create
+//! serious problems.
+#![allow(unsafe_code)]
+
+#[cfg(linux_raw)]
+use crate::ffi::CStr;
+#[cfg(linux_raw)]
+use crate::fs::AtFlags;
+use crate::imp;
+#[cfg(linux_raw)]
+use crate::io;
+#[cfg(linux_raw)]
+use crate::process::Pid;
+#[cfg(linux_raw)]
+use core::ffi::c_void;
+#[cfg(linux_raw)]
+use imp::fd::AsFd;
+
+#[cfg(linux_raw)]
+#[cfg(target_arch = "x86")]
+#[inline]
+pub unsafe fn set_thread_area(u_info: &mut UserDesc) -> io::Result<()> {
+ imp::runtime::syscalls::tls::set_thread_area(u_info)
+}
+
+#[cfg(linux_raw)]
+#[cfg(target_arch = "arm")]
+#[inline]
+pub unsafe fn arm_set_tls(data: *mut c_void) -> io::Result<()> {
+ imp::runtime::syscalls::tls::arm_set_tls(data)
+}
+
+#[cfg(linux_raw)]
+#[cfg(target_arch = "x86_64")]
+#[inline]
+pub unsafe fn set_fs(data: *mut c_void) {
+ imp::runtime::syscalls::tls::set_fs(data)
+}
+
+#[cfg(linux_raw)]
+#[inline]
+pub unsafe fn set_tid_address(data: *mut c_void) -> Pid {
+ imp::runtime::syscalls::tls::set_tid_address(data)
+}
+
+/// `prctl(PR_SET_NAME, name)`
+///
+/// # References
+/// - [Linux]: https://man7.org/linux/man-pages/man2/prctl.2.html
+///
+/// # Safety
+///
+/// This is a very low-level feature for implementing threading libraries.
+/// See the references links above.
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/prctl.2.html
+#[cfg(linux_raw)]
+#[inline]
+pub unsafe fn set_thread_name(name: &CStr) -> io::Result<()> {
+ imp::runtime::syscalls::tls::set_thread_name(name)
+}
+
+#[cfg(linux_raw)]
+#[cfg(target_arch = "x86")]
+pub use imp::runtime::tls::UserDesc;
+
+/// `syscall(SYS_exit, status)`—Exit the current thread.
+///
+/// # Safety
+///
+/// This is a very low-level feature for implementing threading libraries.
+#[cfg(linux_raw)]
+#[inline]
+pub unsafe fn exit_thread(status: i32) -> ! {
+ imp::runtime::syscalls::tls::exit_thread(status)
+}
+
+/// Exit all the threads in the current process' thread group.
+///
+/// This is equivalent to `_exit` and `_Exit` in libc.
+///
+/// This does not all any `__cxa_atexit`, `atexit`, or any other destructors.
+/// Most programs should use [`std::process::exit`] instead of calling this
+/// directly.
+///
+/// # References
+/// - [POSIX `_Exit`]
+/// - [Linux `exit_group`]
+/// - [Linux `_Exit`]
+///
+/// [POSIX `_Exit`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html
+/// [Linux `exit_group`]: https://man7.org/linux/man-pages/man2/exit_group.2.html
+/// [Linux `_Exit`]: https://man7.org/linux/man-pages/man2/exit.2.html
+#[doc(alias = "_exit")]
+#[doc(alias = "_Exit")]
+#[inline]
+pub fn exit_group(status: i32) -> ! {
+ imp::process::syscalls::exit_group(status)
+}
+
+/// Return fields from the main executable segment headers ("phdrs") relevant
+/// to initializing TLS provided to the program at startup.
+#[cfg(linux_raw)]
+#[inline]
+pub fn startup_tls_info() -> StartupTlsInfo {
+ imp::runtime::tls::startup_tls_info()
+}
+
+/// `(getauxval(AT_PHDR), getauxval(AT_PHNUM))`—Returns the address and
+/// number of ELF segment headers for the main executable.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man3/getauxval.3.html
+#[cfg(linux_raw)]
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[inline]
+pub fn exe_phdrs() -> (*const c_void, usize) {
+ imp::param::auxv::exe_phdrs()
+}
+
+#[cfg(linux_raw)]
+pub use imp::runtime::tls::StartupTlsInfo;
+
+/// `fork()`—Creates a new process by duplicating the calling process.
+///
+/// On success, the pid of the child process is returned in the parent, and
+/// `None` is returned in the child.
+///
+/// Unlike its POSIX and libc counterparts, this `fork` does not invoke any
+/// handlers (such as those registered with `pthread_atfork`).
+///
+/// The program environment in the child after a `fork` and before an `execve`
+/// is very special. All code that executes in this environment must avoid:
+///
+/// - Acquiring any other locks that are held in other threads on the parent
+/// at the time of the `fork`, as the child only contains one thread, and
+/// attempting to acquire such locks will deadlock (though this is [not
+/// considered unsafe]).
+///
+/// - Performing any dynamic allocation using the global allocator, since
+/// global allocators may use locks to ensure thread safety, and their locks
+/// may not be released in the child process, so attempts to allocate may
+/// deadlock (as described in the previous point).
+///
+/// - Accessing any external state which the parent assumes it has exclusive
+/// access to, such as a file protected by a file lock, as this could
+/// corrupt the external state.
+///
+/// - Accessing any random-number-generator state inherited from the parent,
+/// as the parent may have the same state and generate the same random
+/// numbers, which may violate security invariants.
+///
+/// - Accessing any thread runtime state, since this function does not update
+/// the thread id in the thread runtime, so thread runtime functions could
+/// cause undefined behavior.
+///
+/// - Accessing any memory shared with the parent, such as a [`MAP_SHARED`]
+/// mapping, even with anonymous or [`memfd_create`] mappings, as this could
+/// cause undefined behavior.
+///
+/// - Calling any C function which isn't known to be [async-signal-safe], as
+/// that could cause undefined behavior. The extent to which this also
+/// applies to Rust functions is unclear at this time.
+///
+/// # Safety
+///
+/// The child must avoid accessing any memory shared with the parent in a
+/// way that invokes undefined behavior. It must avoid accessing any threading
+/// runtime functions in a way that invokes undefined behavior. And it must
+/// avoid invoking any undefined behavior through any function that is not
+/// guaranteed to be async-signal-safe.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// # Literary interlude
+///
+/// > Do not jump on ancient uncles.
+/// > Do not yell at average mice.
+/// > Do not wear a broom to breakfast.
+/// > Do not ask a snake’s advice.
+/// > Do not bathe in chocolate pudding.
+/// > Do not talk to bearded bears.
+/// > Do not smoke cigars on sofas.
+/// > Do not dance on velvet chairs.
+/// > Do not take a whale to visit
+/// > Russell’s mother’s cousin’s yacht.
+/// > And whatever else you do do
+/// > It is better you
+/// > Do not.
+///
+/// - "Rules", by Karla Kuskin
+///
+/// [`MAP_SHARED`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
+/// [not considered unsafe]: https://doc.rust-lang.org/reference/behavior-not-considered-unsafe.html#deadlocks
+/// [`memfd_create`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/fork.2.html
+/// [async-signal-safe]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
+#[cfg(linux_raw)]
+pub unsafe fn fork() -> io::Result<Option<Pid>> {
+ imp::runtime::syscalls::fork()
+}
+
+/// `execveat(dirfd, path.as_c_str(), argv, envp, flags)`—Execute a new
+/// command using the current process.
+///
+/// # Safety
+///
+/// The `argv` and `envp` pointers must point to NUL-terminated arrays, and
+/// their contents must be pointers to NUL-terminated byte arrays.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/execveat.2.html
+#[cfg(linux_raw)]
+#[inline]
+pub unsafe fn execveat<Fd: AsFd>(
+ dirfd: Fd,
+ path: &CStr,
+ argv: *const *const u8,
+ envp: *const *const u8,
+ flags: AtFlags,
+) -> io::Errno {
+ imp::runtime::syscalls::execveat(dirfd.as_fd(), path, argv, envp, flags)
+}
+
+/// `execve(path.as_c_str(), argv, envp)`—Execute a new command using the
+/// current process.
+///
+/// # Safety
+///
+/// The `argv` and `envp` pointers must point to NUL-terminated arrays, and
+/// their contents must be pointers to NUL-terminated byte arrays.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/execve.2.html
+#[cfg(linux_raw)]
+#[inline]
+pub unsafe fn execve(path: &CStr, argv: *const *const u8, envp: *const *const u8) -> io::Errno {
+ imp::runtime::syscalls::execve(path, argv, envp)
+}
diff --git a/vendor/rustix/src/termios/cf.rs b/vendor/rustix/src/termios/cf.rs
new file mode 100644
index 000000000..d28b65e03
--- /dev/null
+++ b/vendor/rustix/src/termios/cf.rs
@@ -0,0 +1,40 @@
+use crate::termios::{Speed, Termios};
+use crate::{imp, io};
+
+/// `cfgetospeed(termios)`
+#[inline]
+#[must_use]
+pub fn cfgetospeed(termios: &Termios) -> Speed {
+ imp::termios::syscalls::cfgetospeed(termios)
+}
+
+/// `cfgetispeed(termios)`
+#[inline]
+#[must_use]
+pub fn cfgetispeed(termios: &Termios) -> Speed {
+ imp::termios::syscalls::cfgetispeed(termios)
+}
+
+/// `cfmakeraw(termios)`
+#[inline]
+pub fn cfmakeraw(termios: &mut Termios) {
+ imp::termios::syscalls::cfmakeraw(termios)
+}
+
+/// `cfsetospeed(termios, speed)`
+#[inline]
+pub fn cfsetospeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
+ imp::termios::syscalls::cfsetospeed(termios, speed)
+}
+
+/// `cfsetispeed(termios, speed)`
+#[inline]
+pub fn cfsetispeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
+ imp::termios::syscalls::cfsetispeed(termios, speed)
+}
+
+/// `cfsetspeed(termios, speed)`
+#[inline]
+pub fn cfsetspeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
+ imp::termios::syscalls::cfsetspeed(termios, speed)
+}
diff --git a/vendor/rustix/src/termios/constants.rs b/vendor/rustix/src/termios/constants.rs
new file mode 100644
index 000000000..5c10c12ed
--- /dev/null
+++ b/vendor/rustix/src/termios/constants.rs
@@ -0,0 +1,719 @@
+use crate::imp;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B1000000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B1152000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B1500000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B2000000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B2500000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B3000000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B3500000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B4000000;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "openbsd")))]
+pub use imp::termios::types::B460800;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B500000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::B576000;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "openbsd")))]
+pub use imp::termios::types::B921600;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::BRKINT;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::BS0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::BS1;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::BSDLY;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CBAUD;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CBAUDEX;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CIBAUD;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::CLOCAL;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CMSPAR;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CR0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CR1;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CR2;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CR3;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::CRDLY;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::CREAD;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::CRTSCTS;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::CS5;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::CS6;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::CS7;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::CS8;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::CSIZE;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::CSTOPB;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ECHO;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::ECHOCTL;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ECHOE;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ECHOK;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::ECHOKE;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ECHONL;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::ECHOPRT;
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::EXTA;
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::EXTB;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::EXTPROC;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::FF0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::FF1;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::FFDLY;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::FLUSHO;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::HUPCL;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ICRNL;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::IEXTEN;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::IGNBRK;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::IGNCR;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::IGNPAR;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::IMAXBEL;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::INLCR;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::INPCK;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ISIG;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ISTRIP;
+#[cfg(any(
+ linux_raw,
+ all(
+ libc,
+ any(target_os = "haiku", target_os = "illumos", target_os = "solaris"),
+ )
+))]
+pub use imp::termios::types::IUCLC;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::IUTF8;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::IXANY;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::IXOFF;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::IXON;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::NL0;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::NL1;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::NLDLY;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::NOFLSH;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::OCRNL;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::OFDEL;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::OFILL;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::OLCUC;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ONLCR;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ONLRET;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::ONOCR;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::OPOST;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::PARENB;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::PARMRK;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::PARODD;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use imp::termios::types::PENDIN;
+#[cfg(not(any(
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::TAB0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::TAB1;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::TAB2;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::TAB3;
+#[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "illumos",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::TABDLY;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use imp::termios::types::TOSTOP;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use imp::termios::types::VSWTC;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::VT0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::VT1;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::VTDLY;
+#[cfg(any(linux_raw, all(libc, any(target_arch = "s390x", target_os = "haiku"))))]
+pub use imp::termios::types::XCASE;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use imp::termios::types::XTABS;
+pub use imp::termios::types::{
+ B0, B110, B115200, B1200, B134, B150, B1800, B19200, B200, B230400, B2400, B300, B38400, B4800,
+ B50, B57600, B600, B75, B9600, ICANON, VDISCARD, VEOF, VEOL, VEOL2, VERASE, VINTR, VKILL,
+ VLNEXT, VMIN, VQUIT, VREPRINT, VSTART, VSTOP, VSUSP, VTIME, VWERASE,
+};
+
+/// Translate from a `Speed` code to a speed value `u32`.
+///
+/// ```rust
+/// let speed = rustix::termios::speed_value(rustix::termios::B57600);
+/// assert_eq!(speed, Some(57600));
+/// ```
+pub fn speed_value(speed: imp::termios::types::Speed) -> Option<u32> {
+ match speed {
+ imp::termios::types::B0 => Some(0),
+ imp::termios::types::B50 => Some(50),
+ imp::termios::types::B75 => Some(75),
+ imp::termios::types::B110 => Some(110),
+ imp::termios::types::B134 => Some(134),
+ imp::termios::types::B150 => Some(150),
+ imp::termios::types::B200 => Some(200),
+ imp::termios::types::B300 => Some(300),
+ imp::termios::types::B600 => Some(600),
+ imp::termios::types::B1200 => Some(1200),
+ imp::termios::types::B1800 => Some(1800),
+ imp::termios::types::B2400 => Some(2400),
+ imp::termios::types::B4800 => Some(4800),
+ imp::termios::types::B9600 => Some(9600),
+ imp::termios::types::B19200 => Some(19200),
+ imp::termios::types::B38400 => Some(38400),
+ imp::termios::types::B57600 => Some(57600),
+ imp::termios::types::B115200 => Some(115_200),
+ imp::termios::types::B230400 => Some(230_400),
+ #[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "openbsd")))]
+ imp::termios::types::B460800 => Some(460_800),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B500000 => Some(500_000),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B576000 => Some(576_000),
+ #[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "openbsd")))]
+ imp::termios::types::B921600 => Some(921_600),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B1000000 => Some(1_000_000),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B1152000 => Some(1_152_000),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B1500000 => Some(1_500_000),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B2000000 => Some(2_000_000),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B2500000 => Some(2_500_000),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B3000000 => Some(3_000_000),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B3500000 => Some(3_500_000),
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ imp::termios::types::B4000000 => Some(4_000_000),
+ _ => None,
+ }
+}
diff --git a/vendor/rustix/src/termios/mod.rs b/vendor/rustix/src/termios/mod.rs
new file mode 100644
index 000000000..79f2f6b38
--- /dev/null
+++ b/vendor/rustix/src/termios/mod.rs
@@ -0,0 +1,610 @@
+//! Terminal I/O stream operations.
+
+mod cf;
+mod constants;
+mod tc;
+#[cfg(not(windows))]
+mod tty;
+
+pub use cf::{cfgetispeed, cfgetospeed, cfmakeraw, cfsetispeed, cfsetospeed, cfsetspeed};
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B1000000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B1152000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B1500000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B2000000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B2500000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B3000000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B3500000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B4000000;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "openbsd")))]
+pub use constants::B460800;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B500000;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::B576000;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "openbsd")))]
+pub use constants::B921600;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::BRKINT;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::BS0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::BS1;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::BSDLY;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CBAUD;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CBAUDEX;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CIBAUD;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::CLOCAL;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CMSPAR;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CR0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CR1;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CR2;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CR3;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::CRDLY;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::CREAD;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::CRTSCTS;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::CS5;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::CS6;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::CS7;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::CS8;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::CSIZE;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::CSTOPB;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ECHO;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::ECHOCTL;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ECHOE;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ECHOK;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::ECHOKE;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ECHONL;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::ECHOPRT;
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub use constants::EXTA;
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+)))]
+pub use constants::EXTB;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::EXTPROC;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::FF0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::FF1;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::FFDLY;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::FLUSHO;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::HUPCL;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ICRNL;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::IEXTEN;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::IGNBRK;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::IGNCR;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::IGNPAR;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::IMAXBEL;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::INLCR;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::INPCK;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ISIG;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ISTRIP;
+#[cfg(any(
+ linux_raw,
+ all(
+ libc,
+ any(target_os = "haiku", target_os = "illumos", target_os = "solaris"),
+ )
+))]
+pub use constants::IUCLC;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::IUTF8;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::IXANY;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::IXOFF;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::IXON;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::NL0;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::NL1;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::NLDLY;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::NOFLSH;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::OCRNL;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::OFDEL;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::OFILL;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "redox",
+)))]
+pub use constants::OLCUC;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ONLCR;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ONLRET;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::ONOCR;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::OPOST;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::PARENB;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::PARMRK;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::PARODD;
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+pub use constants::PENDIN;
+#[cfg(not(any(
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::TAB0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::TAB1;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::TAB2;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::TAB3;
+#[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "illumos",
+ target_os = "redox",
+)))]
+pub use constants::TABDLY;
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+pub use constants::TOSTOP;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+)))]
+pub use constants::VSWTC;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::VT0;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::VT1;
+#[cfg(not(any(
+ all(libc, target_env = "musl"),
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::VTDLY;
+#[cfg(any(linux_raw, all(libc, any(target_arch = "s390x", target_os = "haiku"))))]
+pub use constants::XCASE;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+pub use constants::XTABS;
+pub use constants::{
+ speed_value, B0, B110, B115200, B1200, B134, B150, B1800, B19200, B200, B230400, B2400, B300,
+ B38400, B4800, B50, B57600, B600, B75, B9600, ICANON, VDISCARD, VEOF, VEOL, VEOL2, VERASE,
+ VINTR, VKILL, VLNEXT, VMIN, VQUIT, VREPRINT, VSTART, VSTOP, VSUSP, VTIME, VWERASE,
+};
+pub use tc::{
+ tcdrain, tcflow, tcflush, tcgetattr, tcgetpgrp, tcgetsid, tcgetwinsize, tcsendbreak, tcsetattr,
+ tcsetpgrp, tcsetwinsize, Action, OptionalActions, QueueSelector, Speed, Tcflag, Termios,
+ Winsize,
+};
+#[cfg(not(windows))]
+pub use tty::isatty;
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+#[cfg(feature = "procfs")]
+pub use tty::ttyname;
diff --git a/vendor/rustix/src/termios/tc.rs b/vendor/rustix/src/termios/tc.rs
new file mode 100644
index 000000000..b44eafde3
--- /dev/null
+++ b/vendor/rustix/src/termios/tc.rs
@@ -0,0 +1,196 @@
+use crate::fd::AsFd;
+use crate::process::Pid;
+use crate::{imp, io};
+
+pub use imp::termios::types::{
+ Action, OptionalActions, QueueSelector, Speed, Tcflag, Termios, Winsize,
+};
+
+/// `tcgetattr(fd)`—Get terminal attributes.
+///
+/// Also known as the `TCGETS` operation with `ioctl`.
+///
+/// # References
+/// - [POSIX `tcgetattr`]
+/// - [Linux `ioctl_tty`]
+/// - [Linux `termios`]
+///
+/// [POSIX `tcgetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html
+/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[inline]
+#[doc(alias = "TCGETS")]
+pub fn tcgetattr<Fd: AsFd>(fd: Fd) -> io::Result<Termios> {
+ imp::termios::syscalls::tcgetattr(fd.as_fd())
+}
+
+/// `tcgetwinsize(fd)`—Get the current terminal window size.
+///
+/// Also known as the `TIOCGWINSZ` operation with `ioctl`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[inline]
+#[doc(alias = "TIOCGWINSZ")]
+pub fn tcgetwinsize<Fd: AsFd>(fd: Fd) -> io::Result<Winsize> {
+ imp::termios::syscalls::tcgetwinsize(fd.as_fd())
+}
+
+/// `tcgetpgrp(fd)`—Get the terminal foreground process group.
+///
+/// Also known as the `TIOCGPGRP` operation with `ioctl`.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/tcgetpgrp.3.html
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[inline]
+#[doc(alias = "TIOCGPGRP")]
+pub fn tcgetpgrp<Fd: AsFd>(fd: Fd) -> io::Result<Pid> {
+ imp::termios::syscalls::tcgetpgrp(fd.as_fd())
+}
+
+/// `tcsetpgrp(fd, pid)`—Set the terminal foreground process group.
+///
+/// Also known as the `TIOCSPGRP` operation with `ioctl`.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/tcsetpgrp.3.html
+#[cfg(not(any(windows, target_os = "wasi")))]
+#[inline]
+#[doc(alias = "TIOCSPGRP")]
+pub fn tcsetpgrp<Fd: AsFd>(fd: Fd, pid: Pid) -> io::Result<()> {
+ imp::termios::syscalls::tcsetpgrp(fd.as_fd(), pid)
+}
+
+/// `tcsetattr(fd)`—Set terminal attributes.
+///
+/// Also known as the `TCSETS` operation with `ioctl`.
+///
+/// # References
+/// - [POSIX `tcsetattr`]
+/// - [Linux `ioctl_tty`]
+/// - [Linux `termios`]
+///
+/// [POSIX `tcsetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html
+/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
+#[inline]
+#[doc(alias = "TCSETS")]
+pub fn tcsetattr<Fd: AsFd>(
+ fd: Fd,
+ optional_actions: OptionalActions,
+ termios: &Termios,
+) -> io::Result<()> {
+ imp::termios::syscalls::tcsetattr(fd.as_fd(), optional_actions, termios)
+}
+
+/// `tcsendbreak(fd, 0)`—Transmit zero-valued bits.
+///
+/// Also known as the `TCSBRK` operation with `ioctl`, with a duration of 0.
+///
+/// This function always uses an effective duration parameter of zero. For the
+/// equivalent of a `tcsendbreak` with a non-zero duration parameter, use
+/// `tcdrain`.
+///
+/// # References
+/// - [POSIX `tcsendbreak`]
+/// - [Linux `ioctl_tty`]
+/// - [Linux `termios`]
+///
+/// [POSIX `tcsendbreak`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html
+/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
+#[inline]
+#[doc(alias = "TCSBRK")]
+pub fn tcsendbreak<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::termios::syscalls::tcsendbreak(fd.as_fd())
+}
+
+/// `tcdrain(fd, duration)`—Wait until all pending output has been written.
+///
+/// # References
+/// - [POSIX `tcdrain`]
+/// - [Linux `ioctl_tty`]
+/// - [Linux `termios`]
+///
+/// [POSIX `tcsetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html
+/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
+#[inline]
+pub fn tcdrain<Fd: AsFd>(fd: Fd) -> io::Result<()> {
+ imp::termios::syscalls::tcdrain(fd.as_fd())
+}
+
+/// `tcflush(fd, queue_selector)`—Wait until all pending output has been
+/// written.
+///
+/// # References
+/// - [POSIX `tcflush`]
+/// - [Linux `ioctl_tty`]
+/// - [Linux `termios`]
+///
+/// [POSIX `tcflush`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html
+/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
+#[inline]
+#[doc(alias = "TCFLSH")]
+pub fn tcflush<Fd: AsFd>(fd: Fd, queue_selector: QueueSelector) -> io::Result<()> {
+ imp::termios::syscalls::tcflush(fd.as_fd(), queue_selector)
+}
+
+/// `tcflow(fd, action)`—Suspend or resume transmission or reception.
+///
+/// # References
+/// - [POSIX `tcflow`]
+/// - [Linux `ioctl_tty`]
+/// - [Linux `termios`]
+///
+/// [POSIX `tcflow`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html
+/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
+#[inline]
+#[doc(alias = "TCXONC")]
+pub fn tcflow<Fd: AsFd>(fd: Fd, action: Action) -> io::Result<()> {
+ imp::termios::syscalls::tcflow(fd.as_fd(), action)
+}
+
+/// `tcgetsid(fd)`—Return the session ID of the current session with `fd` as
+/// its controlling terminal.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/tcgetsid.3.html
+#[inline]
+#[doc(alias = "TIOCGSID")]
+pub fn tcgetsid<Fd: AsFd>(fd: Fd) -> io::Result<Pid> {
+ imp::termios::syscalls::tcgetsid(fd.as_fd())
+}
+
+/// `tcsetwinsize(fd)`—Set the current terminal window size.
+///
+/// Also known as the `TIOCSWINSZ` operation with `ioctl`.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
+#[inline]
+#[doc(alias = "TIOCSWINSZ")]
+pub fn tcsetwinsize<Fd: AsFd>(fd: Fd, winsize: Winsize) -> io::Result<()> {
+ imp::termios::syscalls::tcsetwinsize(fd.as_fd(), winsize)
+}
diff --git a/vendor/rustix/src/termios/tty.rs b/vendor/rustix/src/termios/tty.rs
new file mode 100644
index 000000000..1651a3c3b
--- /dev/null
+++ b/vendor/rustix/src/termios/tty.rs
@@ -0,0 +1,72 @@
+//! Functions which operate on file descriptors which might be terminals.
+
+use crate::imp;
+#[cfg(any(
+ all(linux_raw, feature = "procfs"),
+ all(libc, not(any(target_os = "fuchsia", target_os = "wasi"))),
+))]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+use crate::io;
+use imp::fd::AsFd;
+#[cfg(any(
+ all(linux_raw, feature = "procfs"),
+ all(libc, not(any(target_os = "fuchsia", target_os = "wasi"))),
+))]
+use {
+ crate::ffi::CString, crate::path::SMALL_PATH_BUFFER_SIZE, alloc::vec::Vec, imp::fd::BorrowedFd,
+};
+
+/// `isatty(fd)`—Tests whether a file descriptor refers to a terminal.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/isatty.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/isatty.3.html
+#[inline]
+pub fn isatty<Fd: AsFd>(fd: Fd) -> bool {
+ imp::termios::syscalls::isatty(fd.as_fd())
+}
+
+/// `ttyname_r(fd)`
+///
+/// If `reuse` is non-empty, reuse its buffer to store the result if possible.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/ttyname.html
+/// [Linux]: https://man7.org/linux/man-pages/man3/ttyname.3.html
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+#[cfg(feature = "procfs")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))]
+#[inline]
+pub fn ttyname<Fd: AsFd, B: Into<Vec<u8>>>(dirfd: Fd, reuse: B) -> io::Result<CString> {
+ _ttyname(dirfd.as_fd(), reuse.into())
+}
+
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
+#[cfg(feature = "procfs")]
+fn _ttyname(dirfd: BorrowedFd<'_>, mut buffer: Vec<u8>) -> io::Result<CString> {
+ // This code would benefit from having a better way to read into
+ // uninitialized memory, but that requires `unsafe`.
+ buffer.clear();
+ buffer.reserve(SMALL_PATH_BUFFER_SIZE);
+ buffer.resize(buffer.capacity(), 0_u8);
+
+ loop {
+ match imp::termios::syscalls::ttyname(dirfd, &mut buffer) {
+ Err(io::Errno::RANGE) => {
+ buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially
+ buffer.resize(buffer.capacity(), 0_u8);
+ }
+ Ok(len) => {
+ buffer.resize(len, 0_u8);
+ return Ok(CString::new(buffer).unwrap());
+ }
+ Err(errno) => return Err(errno),
+ }
+ }
+}
diff --git a/vendor/rustix/src/thread/clock.rs b/vendor/rustix/src/thread/clock.rs
new file mode 100644
index 000000000..206703088
--- /dev/null
+++ b/vendor/rustix/src/thread/clock.rs
@@ -0,0 +1,96 @@
+use crate::{imp, io};
+
+pub use imp::time::types::Timespec;
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub use imp::time::types::ClockId;
+
+/// `clock_nanosleep(id, 0, request, remain)`—Sleeps for a duration on a
+/// given clock.
+///
+/// This is `clock_nanosleep` specialized for the case of a relative sleep
+/// interval. See [`clock_nanosleep_absolute`] for absolute intervals.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_nanosleep.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[inline]
+pub fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
+ imp::thread::syscalls::clock_nanosleep_relative(id, request)
+}
+
+/// `clock_nanosleep(id, TIMER_ABSTIME, request, NULL)`—Sleeps until an
+/// absolute time on a given clock.
+///
+/// This is `clock_nanosleep` specialized for the case of an absolute sleep
+/// interval. See [`clock_nanosleep_relative`] for relative intervals.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_nanosleep.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[inline]
+pub fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::Result<()> {
+ imp::thread::syscalls::clock_nanosleep_absolute(id, request)
+}
+
+/// `nanosleep(request, remain)`—Sleeps for a duration.
+///
+/// This effectively uses the system monotonic clock.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/nanosleep.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/nanosleep.2.html
+#[inline]
+pub fn nanosleep(request: &Timespec) -> NanosleepRelativeResult {
+ imp::thread::syscalls::nanosleep(request)
+}
+
+/// A return type for `nanosleep` and `clock_nanosleep_relative`.
+#[derive(Debug, Clone)]
+#[must_use]
+pub enum NanosleepRelativeResult {
+ /// The sleep completed normally.
+ Ok,
+ /// The sleep was interrupted, the remaining time is returned.
+ Interrupted(Timespec),
+ /// An invalid time value was provided.
+ Err(io::Errno),
+}
diff --git a/vendor/rustix/src/thread/futex.rs b/vendor/rustix/src/thread/futex.rs
new file mode 100644
index 000000000..df5b561f1
--- /dev/null
+++ b/vendor/rustix/src/thread/futex.rs
@@ -0,0 +1,38 @@
+//! Linux `futex`.
+//!
+//! # Safety
+//!
+//! Futex is a very low-level mechanism for implementing concurrency
+//! primitives.
+#![allow(unsafe_code)]
+
+use crate::thread::Timespec;
+use crate::{imp, io};
+
+pub use imp::thread::{FutexFlags, FutexOperation};
+
+/// `futex(uaddr, op, val, utime, uaddr2, val3)`
+///
+/// # References
+/// - [Linux `futex` system call]
+/// - [Linux `futex` feature]
+///
+/// # Safety
+///
+/// This is a very low-level feature for implementing synchronization
+/// primitives. See the references links above.
+///
+/// [Linux `futex` system call]: https://man7.org/linux/man-pages/man2/futex.2.html
+/// [Linux `futex` feature]: https://man7.org/linux/man-pages/man7/futex.7.html
+#[inline]
+pub unsafe fn futex(
+ uaddr: *mut u32,
+ op: FutexOperation,
+ flags: FutexFlags,
+ val: u32,
+ utime: *const Timespec,
+ uaddr2: *mut u32,
+ val3: u32,
+) -> io::Result<usize> {
+ imp::thread::syscalls::futex(uaddr, op, flags, val, utime, uaddr2, val3)
+}
diff --git a/vendor/rustix/src/thread/id.rs b/vendor/rustix/src/thread/id.rs
new file mode 100644
index 000000000..964d2654c
--- /dev/null
+++ b/vendor/rustix/src/thread/id.rs
@@ -0,0 +1,17 @@
+use crate::imp;
+use crate::process::Pid;
+
+/// `gettid()`—Returns the thread ID.
+///
+/// This returns the OS thread ID, which is not necessarily the same as the
+/// `rust::thread::Thread::id` or the pthread ID.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/gettid.2.html
+#[inline]
+#[must_use]
+pub fn gettid() -> Pid {
+ imp::thread::syscalls::gettid()
+}
diff --git a/vendor/rustix/src/thread/mod.rs b/vendor/rustix/src/thread/mod.rs
new file mode 100644
index 000000000..ac48b435b
--- /dev/null
+++ b/vendor/rustix/src/thread/mod.rs
@@ -0,0 +1,26 @@
+//! Thread-associated operations.
+
+#[cfg(not(target_os = "redox"))]
+mod clock;
+#[cfg(linux_raw)]
+mod futex;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod id;
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+pub use clock::{clock_nanosleep_absolute, clock_nanosleep_relative, ClockId};
+#[cfg(not(target_os = "redox"))]
+pub use clock::{nanosleep, NanosleepRelativeResult, Timespec};
+#[cfg(linux_raw)]
+pub use futex::{futex, FutexFlags, FutexOperation};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use id::gettid;
diff --git a/vendor/rustix/src/time/clock.rs b/vendor/rustix/src/time/clock.rs
new file mode 100644
index 000000000..32d888749
--- /dev/null
+++ b/vendor/rustix/src/time/clock.rs
@@ -0,0 +1,56 @@
+use crate::{imp, io};
+
+pub use imp::time::types::{Nsecs, Secs, Timespec};
+
+/// `clockid_t`
+#[cfg(any(not(target_os = "wasi")))]
+pub use imp::time::types::{ClockId, DynamicClockId};
+
+/// `clock_getres(id)`—Returns the resolution of a clock.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/clock_getres.2.html
+#[cfg(any(not(any(target_os = "redox", target_os = "wasi"))))]
+#[inline]
+#[must_use]
+pub fn clock_getres(id: ClockId) -> Timespec {
+ imp::time::syscalls::clock_getres(id)
+}
+
+/// `clock_gettime(id)`—Returns the current value of a clock.
+///
+/// This function uses `ClockId` which only contains clocks which are known to
+/// always be supported at runtime, allowing this function to be infallible.
+/// For a greater set of clocks and dynamic clock support, see
+/// [`clock_gettime_dynamic`].
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/clock_gettime.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+#[must_use]
+pub fn clock_gettime(id: ClockId) -> Timespec {
+ imp::time::syscalls::clock_gettime(id)
+}
+
+/// Like [`clock_gettime`] but with support for dynamic clocks.
+///
+/// # References
+/// - [POSIX]
+/// - [Linux]
+///
+/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html
+/// [Linux]: https://man7.org/linux/man-pages/man2/clock_gettime.2.html
+#[cfg(not(target_os = "wasi"))]
+#[inline]
+pub fn clock_gettime_dynamic(id: DynamicClockId<'_>) -> io::Result<Timespec> {
+ imp::time::syscalls::clock_gettime_dynamic(id)
+}
diff --git a/vendor/rustix/src/time/mod.rs b/vendor/rustix/src/time/mod.rs
new file mode 100644
index 000000000..ca5b2b2dd
--- /dev/null
+++ b/vendor/rustix/src/time/mod.rs
@@ -0,0 +1,20 @@
+//! Time-related operations.
+
+mod clock;
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(feature = "time")]
+mod timerfd;
+
+// TODO: Convert WASI'S clock APIs to use handles rather than ambient clock
+// identifiers, update `wasi-libc`, and then add support in `rustix`.
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub use clock::clock_getres;
+#[cfg(not(target_os = "wasi"))]
+pub use clock::{clock_gettime, clock_gettime_dynamic, ClockId, DynamicClockId};
+pub use clock::{Nsecs, Secs, Timespec};
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[cfg(feature = "time")]
+pub use timerfd::{
+ timerfd_create, timerfd_gettime, timerfd_settime, Itimerspec, TimerfdClockId, TimerfdFlags,
+ TimerfdTimerFlags,
+};
diff --git a/vendor/rustix/src/time/timerfd.rs b/vendor/rustix/src/time/timerfd.rs
new file mode 100644
index 000000000..5abe6ff52
--- /dev/null
+++ b/vendor/rustix/src/time/timerfd.rs
@@ -0,0 +1,42 @@
+use crate::fd::AsFd;
+use crate::imp;
+use crate::io::{self, OwnedFd};
+
+pub use imp::time::types::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags};
+
+/// `timerfd_create(clockid, flags)`—Create a timer.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/timerfd_create.2.html
+#[inline]
+pub fn timerfd_create(clockid: TimerfdClockId, flags: TimerfdFlags) -> io::Result<OwnedFd> {
+ imp::time::syscalls::timerfd_create(clockid, flags)
+}
+
+/// `timerfd_settime(clockid, flags, new_value)`—Set the time on a timer.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/timerfd_settime.2.html
+#[inline]
+pub fn timerfd_settime<Fd: AsFd>(
+ fd: Fd,
+ flags: TimerfdTimerFlags,
+ new_value: &Itimerspec,
+) -> io::Result<Itimerspec> {
+ imp::time::syscalls::timerfd_settime(fd.as_fd(), flags, new_value)
+}
+
+/// `timerfd_gettime(clockid, flags)`—Query a timer.
+///
+/// # References
+/// - [Linux]
+///
+/// [Linux]: https://man7.org/linux/man-pages/man2/timerfd_gettime.2.html
+#[inline]
+pub fn timerfd_gettime<Fd: AsFd>(fd: Fd) -> io::Result<Itimerspec> {
+ imp::time::syscalls::timerfd_gettime(fd.as_fd())
+}
diff --git a/vendor/rustix/src/utils.rs b/vendor/rustix/src/utils.rs
new file mode 100644
index 000000000..efbbe81aa
--- /dev/null
+++ b/vendor/rustix/src/utils.rs
@@ -0,0 +1,13 @@
+/// Convert a `&T` into a `*const T` without using an `as`.
+#[inline]
+#[allow(dead_code)]
+pub(crate) const fn as_ptr<T>(t: &T) -> *const T {
+ t
+}
+
+/// Convert a `&mut T` into a `*mut T` without using an `as`.
+#[inline]
+#[allow(dead_code)]
+pub(crate) fn as_mut_ptr<T>(t: &mut T) -> *mut T {
+ t
+}