From 1b6a04ca5504955c571d1c97504fb45ea0befee4 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Mon, 8 Jan 2024 01:21:28 +0400 Subject: Initial vendor packages Signed-off-by: Valentin Popov --- vendor/rustix/src/backend/linux_raw/io/errno.rs | 553 +++++++++++++++++++++ vendor/rustix/src/backend/linux_raw/io/mod.rs | 3 + vendor/rustix/src/backend/linux_raw/io/syscalls.rs | 379 ++++++++++++++ vendor/rustix/src/backend/linux_raw/io/types.rs | 57 +++ 4 files changed, 992 insertions(+) create mode 100644 vendor/rustix/src/backend/linux_raw/io/errno.rs create mode 100644 vendor/rustix/src/backend/linux_raw/io/mod.rs create mode 100644 vendor/rustix/src/backend/linux_raw/io/syscalls.rs create mode 100644 vendor/rustix/src/backend/linux_raw/io/types.rs (limited to 'vendor/rustix/src/backend/linux_raw/io') diff --git a/vendor/rustix/src/backend/linux_raw/io/errno.rs b/vendor/rustix/src/backend/linux_raw/io/errno.rs new file mode 100644 index 0000000..bc40e9a --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/io/errno.rs @@ -0,0 +1,553 @@ +//! 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 crate::backend::c; +use crate::backend::fd::RawFd; +use crate::backend::reg::{RetNumber, RetReg}; +use crate::io; +use linux_raw_sys::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] +/// - [Winsock] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/errno.html +/// [Linux]: https://man7.org/linux/man-pages/man3/errno.3.html +/// [Winsock]: https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2 +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?errno +/// [NetBSD]: https://man.netbsd.org/errno.2 +/// [OpenBSD]: https://man.openbsd.org/errno.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=errno§ion=2 +/// [illumos]: https://illumos.org/man/3C/errno +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Error-Codes.html +/// [`std::io::Error`]: Result +#[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 { + 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`. + 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::backend) fn try_decode_c_int( + raw: RetReg, +) -> io::Result { + 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::backend) fn try_decode_c_uint( + raw: RetReg, +) -> io::Result { + 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::backend) fn try_decode_usize(raw: RetReg) -> io::Result { + 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::backend) fn try_decode_void_star( + raw: RetReg, +) -> 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::backend) fn try_decode_u64(raw: RetReg) -> io::Result { + 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::backend) unsafe fn try_decode_raw_fd( + raw: RetReg, +) -> io::Result { + // 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::backend) unsafe fn try_decode_void( + raw: RetReg, +) -> 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(any(feature = "event", feature = "runtime"))] +#[inline] +pub(in crate::backend) unsafe fn try_decode_error(raw: RetReg) -> 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::backend) fn decode_usize_infallible(raw: RetReg) -> usize { + raw.decode_usize() +} + +/// Return the contained `c_int` value. +#[cfg(not(debug_assertions))] +#[inline] +pub(in crate::backend) fn decode_c_int_infallible(raw: RetReg) -> c::c_int { + raw.decode_c_int() +} + +/// Return the contained `c_uint` value. +#[cfg(not(debug_assertions))] +#[inline] +pub(in crate::backend) fn decode_c_uint_infallible(raw: RetReg) -> c::c_uint { + raw.decode_c_uint() +} + +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/backend/linux_raw/io/mod.rs b/vendor/rustix/src/backend/linux_raw/io/mod.rs new file mode 100644 index 0000000..9477b9b --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/io/mod.rs @@ -0,0 +1,3 @@ +pub(crate) mod errno; +pub(crate) mod syscalls; +pub(crate) mod types; diff --git a/vendor/rustix/src/backend/linux_raw/io/syscalls.rs b/vendor/rustix/src/backend/linux_raw/io/syscalls.rs new file mode 100644 index 0000000..c38f28f --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/io/syscalls.rs @@ -0,0 +1,379 @@ +//! linux_raw syscalls supporting `rustix::io`. +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code)] +#![allow(clippy::undocumented_unsafe_blocks)] + +#[cfg(target_pointer_width = "64")] +use crate::backend::conv::loff_t_from_u64; +#[cfg(all( + target_pointer_width = "32", + any(target_arch = "arm", target_arch = "mips", target_arch = "mips32r6"), +))] +use crate::backend::conv::zero; +use crate::backend::conv::{ + c_uint, pass_usize, raw_fd, ret, ret_c_int, ret_c_uint, ret_discarded_fd, ret_owned_fd, + ret_usize, slice, +}; +#[cfg(target_pointer_width = "32")] +use crate::backend::conv::{hi, lo}; +use crate::backend::{c, MAX_IOV}; +use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd}; +use crate::io::{self, DupFlags, FdFlags, IoSlice, IoSliceMut, ReadWriteFlags}; +use crate::ioctl::{IoctlOutput, RawOpcode}; +#[cfg(all(feature = "fs", feature = "net"))] +use crate::net::{RecvFlags, SendFlags}; +use core::cmp; +use linux_raw_sys::general::{F_DUPFD_CLOEXEC, F_GETFD, F_SETFD}; + +#[inline] +pub(crate) unsafe fn read(fd: BorrowedFd<'_>, buf: *mut u8, len: usize) -> io::Result { + ret_usize(syscall!(__NR_read, fd, buf, pass_usize(len))) +} + +#[inline] +pub(crate) unsafe fn pread( + fd: BorrowedFd<'_>, + buf: *mut u8, + len: usize, + pos: u64, +) -> io::Result { + // + #[cfg(all( + target_pointer_width = "32", + any(target_arch = "arm", target_arch = "mips", target_arch = "mips32r6"), + ))] + { + ret_usize(syscall!( + __NR_pread64, + fd, + buf, + pass_usize(len), + zero(), + hi(pos), + lo(pos) + )) + } + #[cfg(all( + target_pointer_width = "32", + not(any(target_arch = "arm", target_arch = "mips", target_arch = "mips32r6")), + ))] + { + ret_usize(syscall!( + __NR_pread64, + fd, + buf, + pass_usize(len), + hi(pos), + lo(pos) + )) + } + #[cfg(target_pointer_width = "64")] + ret_usize(syscall!( + __NR_pread64, + fd, + buf, + pass_usize(len), + loff_t_from_u64(pos) + )) +} + +#[inline] +pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + 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 { + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); + + // Unlike the plain "p" functions, the "pv" functions pass their offset in + // an endian-independent way, and always in two registers. + unsafe { + ret_usize(syscall!( + __NR_preadv, + fd, + bufs_addr, + bufs_len, + pass_usize(pos as usize), + pass_usize((pos >> 32) as usize) + )) + } +} + +#[inline] +pub(crate) fn preadv2( + fd: BorrowedFd<'_>, + bufs: &mut [IoSliceMut<'_>], + pos: u64, + flags: ReadWriteFlags, +) -> io::Result { + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); + + // Unlike the plain "p" functions, the "pv" functions pass their offset in + // an endian-independent way, and always in two registers. + unsafe { + ret_usize(syscall!( + __NR_preadv2, + fd, + bufs_addr, + bufs_len, + pass_usize(pos as usize), + pass_usize((pos >> 32) as usize), + flags + )) + } +} + +#[inline] +pub(crate) fn write(fd: BorrowedFd<'_>, buf: &[u8]) -> io::Result { + 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 { + let (buf_addr, buf_len) = slice(buf); + + // + #[cfg(all( + target_pointer_width = "32", + any(target_arch = "arm", target_arch = "mips", target_arch = "mips32r6"), + ))] + 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 = "mips32r6")), + ))] + 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 { + 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 { + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); + + // Unlike the plain "p" functions, the "pv" functions pass their offset in + // an endian-independent way, and always in two registers. + unsafe { + ret_usize(syscall_readonly!( + __NR_pwritev, + fd, + bufs_addr, + bufs_len, + pass_usize(pos as usize), + pass_usize((pos >> 32) as usize) + )) + } +} + +#[inline] +pub(crate) fn pwritev2( + fd: BorrowedFd<'_>, + bufs: &[IoSlice<'_>], + pos: u64, + flags: ReadWriteFlags, +) -> io::Result { + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); + + // Unlike the plain "p" functions, the "pv" functions pass their offset in + // an endian-independent way, and always in two registers. + unsafe { + ret_usize(syscall_readonly!( + __NR_pwritev2, + fd, + bufs_addr, + bufs_len, + pass_usize(pos as usize), + pass_usize((pos >> 32) as usize), + flags + )) + } +} + +#[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) unsafe fn ioctl( + fd: BorrowedFd<'_>, + request: RawOpcode, + arg: *mut c::c_void, +) -> io::Result { + ret_c_int(syscall!(__NR_ioctl, fd, c_uint(request), arg)) +} + +#[inline] +pub(crate) unsafe fn ioctl_readonly( + fd: BorrowedFd<'_>, + request: RawOpcode, + arg: *mut c::c_void, +) -> io::Result { + ret_c_int(syscall_readonly!(__NR_ioctl, fd, c_uint(request), arg)) +} + +#[cfg(all(feature = "fs", 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. + let mut buf = [core::mem::MaybeUninit::::uninit()]; + match unsafe { + crate::backend::net::syscalls::recv( + fd, + buf.as_mut_ptr() as *mut u8, + 1, + 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 crate::backend::net::syscalls::send(fd, &[], SendFlags::DONTWAIT) { + Err(io::Errno::AGAIN | io::Errno::WOULDBLOCK | 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 { + unsafe { ret_owned_fd(syscall_readonly!(__NR_dup, fd)) } +} + +#[allow(clippy::needless_pass_by_ref_mut)] +#[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())) + } +} + +#[allow(clippy::needless_pass_by_ref_mut)] +#[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 fcntl_getfd(fd: BorrowedFd<'_>) -> io::Result { + #[cfg(target_pointer_width = "32")] + unsafe { + ret_c_uint(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETFD))) + .map(FdFlags::from_bits_retain) + } + #[cfg(target_pointer_width = "64")] + unsafe { + ret_c_uint(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETFD))) + .map(FdFlags::from_bits_retain) + } +} + +#[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_dupfd_cloexec(fd: BorrowedFd<'_>, min: RawFd) -> io::Result { + #[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) + )) + } +} diff --git a/vendor/rustix/src/backend/linux_raw/io/types.rs b/vendor/rustix/src/backend/linux_raw/io/types.rs new file mode 100644 index 0000000..4b3dfc6 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/io/types.rs @@ -0,0 +1,57 @@ +use crate::backend::c; +use bitflags::bitflags; + +bitflags! { + /// `FD_*` constants for use with [`fcntl_getfd`] and [`fcntl_setfd`]. + /// + /// [`fcntl_getfd`]: crate::io::fcntl_getfd + /// [`fcntl_setfd`]: crate::io::fcntl_setfd + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FdFlags: c::c_uint { + /// `FD_CLOEXEC` + const CLOEXEC = linux_raw_sys::general::FD_CLOEXEC; + + /// + const _ = !0; + } +} + +bitflags! { + /// `RWF_*` constants for use with [`preadv2`] and [`pwritev2`]. + /// + /// [`preadv2`]: crate::io::preadv2 + /// [`pwritev2`]: crate::io::pwritev + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + 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; + + /// + const _ = !0; + } +} + +bitflags! { + /// `O_*` constants for use with [`dup2`]. + /// + /// [`dup2`]: crate::io::dup2 + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct DupFlags: c::c_uint { + /// `O_CLOEXEC` + const CLOEXEC = linux_raw_sys::general::O_CLOEXEC; + + /// + const _ = !0; + } +} -- cgit v1.2.3