Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
468
third-party/vendor/rustix/src/backend/libc/c.rs
vendored
Normal file
468
third-party/vendor/rustix/src/backend/libc/c.rs
vendored
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
//! Libc and supplemental types and constants.
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
// Import everything from libc, but we'll add some stuff and override some
|
||||
// things below.
|
||||
pub(crate) use libc::*;
|
||||
|
||||
/// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem.
|
||||
#[cfg(all(linux_kernel, target_env = "musl"))]
|
||||
pub(crate) const PROC_SUPER_MAGIC: u32 = 0x0000_9fa0;
|
||||
|
||||
/// `NFS_SUPER_MAGIC`—The magic number for the NFS filesystem.
|
||||
#[cfg(all(linux_kernel, target_env = "musl"))]
|
||||
pub(crate) const NFS_SUPER_MAGIC: u32 = 0x0000_6969;
|
||||
|
||||
#[cfg(feature = "process")]
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
pub(crate) const EXIT_SIGNALED_SIGABRT: c_int = 128 + SIGABRT as c_int;
|
||||
|
||||
// TODO: Upstream these.
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_TSN: c_int = linux_raw_sys::if_ether::ETH_P_TSN as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_ERSPAN2: c_int = linux_raw_sys::if_ether::ETH_P_ERSPAN2 as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_ERSPAN: c_int = linux_raw_sys::if_ether::ETH_P_ERSPAN as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_PROFINET: c_int = linux_raw_sys::if_ether::ETH_P_PROFINET as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_REALTEK: c_int = linux_raw_sys::if_ether::ETH_P_REALTEK as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_ETHERCAT: c_int = linux_raw_sys::if_ether::ETH_P_ETHERCAT as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_PREAUTH: c_int = linux_raw_sys::if_ether::ETH_P_PREAUTH as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_LLDP: c_int = linux_raw_sys::if_ether::ETH_P_LLDP as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_MRP: c_int = linux_raw_sys::if_ether::ETH_P_MRP as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_NCSI: c_int = linux_raw_sys::if_ether::ETH_P_NCSI as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_CFM: c_int = linux_raw_sys::if_ether::ETH_P_CFM as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_IBOE: c_int = linux_raw_sys::if_ether::ETH_P_IBOE as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_HSR: c_int = linux_raw_sys::if_ether::ETH_P_HSR as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_NSH: c_int = linux_raw_sys::if_ether::ETH_P_NSH as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_DSA_8021Q: c_int = linux_raw_sys::if_ether::ETH_P_DSA_8021Q as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_DSA_A5PSW: c_int = linux_raw_sys::if_ether::ETH_P_DSA_A5PSW as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_IFE: c_int = linux_raw_sys::if_ether::ETH_P_IFE as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_CAN: c_int = linux_raw_sys::if_ether::ETH_P_CAN as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_CANXL: c_int = linux_raw_sys::if_ether::ETH_P_CANXL as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_XDSA: c_int = linux_raw_sys::if_ether::ETH_P_XDSA as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_MAP: c_int = linux_raw_sys::if_ether::ETH_P_MAP as _;
|
||||
#[cfg(all(linux_kernel, feature = "net"))]
|
||||
pub(crate) const ETH_P_MCTP: c_int = linux_raw_sys::if_ether::ETH_P_MCTP as _;
|
||||
|
||||
#[cfg(all(
|
||||
linux_kernel,
|
||||
any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
)
|
||||
))]
|
||||
pub(crate) const SIGEMT: c_int = linux_raw_sys::general::SIGEMT as _;
|
||||
|
||||
// TODO: Upstream these.
|
||||
#[cfg(all(linux_kernel, feature = "termios"))]
|
||||
pub(crate) const IUCLC: tcflag_t = linux_raw_sys::general::IUCLC as _;
|
||||
#[cfg(all(linux_kernel, feature = "termios"))]
|
||||
pub(crate) const XCASE: tcflag_t = linux_raw_sys::general::XCASE as _;
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
pub(crate) const MSG_DONTWAIT: c_int = libc::MSG_NONBLOCK;
|
||||
|
||||
// TODO: Remove once https://github.com/rust-lang/libc/pull/3377 is merged and released.
|
||||
#[cfg(target_os = "netbsd")]
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const SO_NOSIGPIPE: c_int = 0x0800;
|
||||
|
||||
// On PowerPC, the regular `termios` has the `termios2` fields and there is no
|
||||
// `termios2`. linux-raw-sys has aliases `termios2` to `termios` to cover this
|
||||
// difference, but we still need to manually import it since `libc` doesn't
|
||||
// have this.
|
||||
#[cfg(all(
|
||||
linux_kernel,
|
||||
feature = "termios",
|
||||
any(target_arch = "powerpc", target_arch = "powerpc64")
|
||||
))]
|
||||
pub(crate) use {
|
||||
linux_raw_sys::general::{termios2, CIBAUD},
|
||||
linux_raw_sys::ioctl::{TCGETS2, TCSETS2, TCSETSF2, TCSETSW2},
|
||||
};
|
||||
|
||||
// Automatically enable “large file” support (LFS) features.
|
||||
|
||||
#[cfg(target_os = "vxworks")]
|
||||
pub(super) use libc::_Vx_ticks64_t as _Vx_ticks_t;
|
||||
#[cfg(linux_kernel)]
|
||||
pub(super) use libc::fallocate64 as fallocate;
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
|
||||
#[cfg(any(linux_like, target_os = "aix"))]
|
||||
pub(super) use libc::open64 as open;
|
||||
#[cfg(any(
|
||||
linux_kernel,
|
||||
target_os = "aix",
|
||||
target_os = "hurd",
|
||||
target_os = "l4re"
|
||||
))]
|
||||
pub(super) use libc::posix_fallocate64 as posix_fallocate;
|
||||
#[cfg(any(all(linux_like, not(target_os = "android")), target_os = "aix"))]
|
||||
pub(super) use libc::{blkcnt64_t as blkcnt_t, rlim64_t as rlim_t};
|
||||
// TODO: AIX has `stat64x`, `fstat64x`, `lstat64x`, and `stat64xat`; add them
|
||||
// to the upstream libc crate and implement rustix's `statat` etc. with them.
|
||||
#[cfg(target_os = "aix")]
|
||||
pub(super) use libc::{
|
||||
blksize64_t as blksize_t, fstat64 as fstat, fstatfs64 as fstatfs, fstatvfs64 as fstatvfs,
|
||||
ftruncate64 as ftruncate, getrlimit64 as getrlimit, ino_t, lseek64 as lseek, mmap,
|
||||
off64_t as off_t, openat, posix_fadvise64 as posix_fadvise, preadv, pwritev,
|
||||
rlimit64 as rlimit, setrlimit64 as setrlimit, stat64at as fstatat, statfs64 as statfs,
|
||||
statvfs64 as statvfs, RLIM_INFINITY,
|
||||
};
|
||||
#[cfg(any(linux_like, target_os = "hurd"))]
|
||||
pub(super) use libc::{
|
||||
fstat64 as fstat, fstatat64 as fstatat, fstatfs64 as fstatfs, fstatvfs64 as fstatvfs,
|
||||
ftruncate64 as ftruncate, getrlimit64 as getrlimit, ino64_t as ino_t, lseek64 as lseek,
|
||||
mmap64 as mmap, off64_t as off_t, openat64 as openat, posix_fadvise64 as posix_fadvise,
|
||||
rlimit64 as rlimit, setrlimit64 as setrlimit, statfs64 as statfs, statvfs64 as statvfs,
|
||||
RLIM64_INFINITY as RLIM_INFINITY,
|
||||
};
|
||||
#[cfg(apple)]
|
||||
pub(super) use libc::{
|
||||
host_info64_t as host_info_t, host_statistics64 as host_statistics,
|
||||
vm_statistics64_t as vm_statistics_t,
|
||||
};
|
||||
#[cfg(not(all(
|
||||
linux_kernel,
|
||||
any(
|
||||
target_pointer_width = "32",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6"
|
||||
)
|
||||
)))]
|
||||
#[cfg(any(linux_like, target_os = "aix", target_os = "hurd"))]
|
||||
pub(super) use libc::{lstat64 as lstat, stat64 as stat};
|
||||
#[cfg(any(
|
||||
linux_kernel,
|
||||
target_os = "aix",
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten"
|
||||
))]
|
||||
pub(super) use libc::{pread64 as pread, pwrite64 as pwrite};
|
||||
#[cfg(any(target_os = "linux", target_os = "hurd", target_os = "emscripten"))]
|
||||
pub(super) use libc::{preadv64 as preadv, pwritev64 as pwritev};
|
||||
|
||||
#[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]
|
||||
pub(super) unsafe fn prlimit(
|
||||
pid: libc::pid_t,
|
||||
resource: libc::__rlimit_resource_t,
|
||||
new_limit: *const libc::rlimit64,
|
||||
old_limit: *mut libc::rlimit64,
|
||||
) -> libc::c_int {
|
||||
// `prlimit64` wasn't supported in glibc until 2.13.
|
||||
weak_or_syscall! {
|
||||
fn prlimit64(
|
||||
pid: libc::pid_t,
|
||||
resource: libc::__rlimit_resource_t,
|
||||
new_limit: *const libc::rlimit64,
|
||||
old_limit: *mut libc::rlimit64
|
||||
) via SYS_prlimit64 -> libc::c_int
|
||||
}
|
||||
|
||||
prlimit64(pid, resource, new_limit, old_limit)
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", target_env = "musl"))]
|
||||
pub(super) unsafe fn prlimit(
|
||||
pid: libc::pid_t,
|
||||
resource: libc::c_int,
|
||||
new_limit: *const libc::rlimit64,
|
||||
old_limit: *mut libc::rlimit64,
|
||||
) -> libc::c_int {
|
||||
weak_or_syscall! {
|
||||
fn prlimit64(
|
||||
pid: libc::pid_t,
|
||||
resource: libc::c_int,
|
||||
new_limit: *const libc::rlimit64,
|
||||
old_limit: *mut libc::rlimit64
|
||||
) via SYS_prlimit64 -> libc::c_int
|
||||
}
|
||||
|
||||
prlimit64(pid, resource, new_limit, old_limit)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub(super) unsafe fn prlimit(
|
||||
pid: libc::pid_t,
|
||||
resource: libc::c_int,
|
||||
new_limit: *const libc::rlimit64,
|
||||
old_limit: *mut libc::rlimit64,
|
||||
) -> libc::c_int {
|
||||
weak_or_syscall! {
|
||||
fn prlimit64(
|
||||
pid: libc::pid_t,
|
||||
resource: libc::c_int,
|
||||
new_limit: *const libc::rlimit64,
|
||||
old_limit: *mut libc::rlimit64
|
||||
) via SYS_prlimit64 -> libc::c_int
|
||||
}
|
||||
|
||||
prlimit64(pid, resource, new_limit, old_limit)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
mod readwrite_pv64 {
|
||||
use super::*;
|
||||
|
||||
pub(in super::super) unsafe fn preadv64(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset: libc::off64_t,
|
||||
) -> libc::ssize_t {
|
||||
// Older Android libc lacks `preadv64`, so use the `weak!` mechanism to
|
||||
// test for it, and call back to `libc::syscall`. We don't use
|
||||
// `weak_or_syscall` here because we need to pass the 64-bit offset
|
||||
// specially.
|
||||
weak! {
|
||||
fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t) -> libc::ssize_t
|
||||
}
|
||||
if let Some(fun) = preadv64.get() {
|
||||
fun(fd, iov, iovcnt, offset)
|
||||
} else {
|
||||
// Unlike the plain "p" functions, the "pv" functions pass their
|
||||
// offset in an endian-independent way, and always in two registers.
|
||||
syscall! {
|
||||
fn preadv(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset_lo: usize,
|
||||
offset_hi: usize
|
||||
) via SYS_preadv -> libc::ssize_t
|
||||
}
|
||||
preadv(fd, iov, iovcnt, offset as usize, (offset >> 32) as usize)
|
||||
}
|
||||
}
|
||||
pub(in super::super) unsafe fn pwritev64(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset: libc::off64_t,
|
||||
) -> libc::ssize_t {
|
||||
// See the comments in `preadv64`.
|
||||
weak! {
|
||||
fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t) -> libc::ssize_t
|
||||
}
|
||||
if let Some(fun) = pwritev64.get() {
|
||||
fun(fd, iov, iovcnt, offset)
|
||||
} else {
|
||||
// Unlike the plain "p" functions, the "pv" functions pass their
|
||||
// offset in an endian-independent way, and always in two registers.
|
||||
syscall! {
|
||||
fn pwritev(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset_lo: usize,
|
||||
offset_hi: usize
|
||||
) via SYS_pwritev -> libc::ssize_t
|
||||
}
|
||||
pwritev(fd, iov, iovcnt, offset as usize, (offset >> 32) as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "android")]
|
||||
pub(super) use readwrite_pv64::{preadv64 as preadv, pwritev64 as pwritev};
|
||||
|
||||
// macOS added `preadv` and `pwritev` in version 11.0.
|
||||
#[cfg(apple)]
|
||||
mod readwrite_pv {
|
||||
weakcall! {
|
||||
pub(in super::super) fn preadv(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset: libc::off_t
|
||||
) -> libc::ssize_t
|
||||
}
|
||||
weakcall! {
|
||||
pub(in super::super) fn pwritev(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int, offset: libc::off_t
|
||||
) -> libc::ssize_t
|
||||
}
|
||||
}
|
||||
#[cfg(apple)]
|
||||
pub(super) use readwrite_pv::{preadv, pwritev};
|
||||
|
||||
// glibc added `preadv64v2` and `pwritev64v2` in version 2.26.
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
mod readwrite_pv64v2 {
|
||||
use super::*;
|
||||
|
||||
pub(in super::super) unsafe fn preadv64v2(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset: libc::off64_t,
|
||||
flags: libc::c_int,
|
||||
) -> libc::ssize_t {
|
||||
// Older glibc lacks `preadv64v2`, so use the `weak!` mechanism to
|
||||
// test for it, and call back to `libc::syscall`. We don't use
|
||||
// `weak_or_syscall` here because we need to pass the 64-bit offset
|
||||
// specially.
|
||||
weak! {
|
||||
fn preadv64v2(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t, libc::c_int) -> libc::ssize_t
|
||||
}
|
||||
if let Some(fun) = preadv64v2.get() {
|
||||
fun(fd, iov, iovcnt, offset, flags)
|
||||
} else {
|
||||
// Unlike the plain "p" functions, the "pv" functions pass their
|
||||
// offset in an endian-independent way, and always in two registers.
|
||||
syscall! {
|
||||
fn preadv2(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset_lo: usize,
|
||||
offset_hi: usize,
|
||||
flags: libc::c_int
|
||||
) via SYS_preadv2 -> libc::ssize_t
|
||||
}
|
||||
preadv2(
|
||||
fd,
|
||||
iov,
|
||||
iovcnt,
|
||||
offset as usize,
|
||||
(offset >> 32) as usize,
|
||||
flags,
|
||||
)
|
||||
}
|
||||
}
|
||||
pub(in super::super) unsafe fn pwritev64v2(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset: libc::off64_t,
|
||||
flags: libc::c_int,
|
||||
) -> libc::ssize_t {
|
||||
// See the comments in `preadv64v2`.
|
||||
weak! {
|
||||
fn pwritev64v2(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t, libc::c_int) -> libc::ssize_t
|
||||
}
|
||||
if let Some(fun) = pwritev64v2.get() {
|
||||
fun(fd, iov, iovcnt, offset, flags)
|
||||
} else {
|
||||
// Unlike the plain "p" functions, the "pv" functions pass their
|
||||
// offset in an endian-independent way, and always in two registers.
|
||||
syscall! {
|
||||
fn pwritev2(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovec: libc::c_int,
|
||||
offset_lo: usize,
|
||||
offset_hi: usize,
|
||||
flags: libc::c_int
|
||||
) via SYS_pwritev2 -> libc::ssize_t
|
||||
}
|
||||
pwritev2(
|
||||
fd,
|
||||
iov,
|
||||
iovcnt,
|
||||
offset as usize,
|
||||
(offset >> 32) as usize,
|
||||
flags,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2};
|
||||
|
||||
// On non-glibc, assume we don't have `pwritev2`/`preadv2` in libc and use
|
||||
// `c::syscall` instead.
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
all(target_os = "linux", not(target_env = "gnu")),
|
||||
))]
|
||||
mod readwrite_pv64v2 {
|
||||
use super::*;
|
||||
|
||||
pub(in super::super) unsafe fn preadv64v2(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset: libc::off64_t,
|
||||
flags: libc::c_int,
|
||||
) -> libc::ssize_t {
|
||||
// Unlike the plain "p" functions, the "pv" functions pass their offset
|
||||
// in an endian-independent way, and always in two registers.
|
||||
syscall! {
|
||||
fn preadv2(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset_lo: usize,
|
||||
offset_hi: usize,
|
||||
flags: libc::c_int
|
||||
) via SYS_preadv2 -> libc::ssize_t
|
||||
}
|
||||
preadv2(
|
||||
fd,
|
||||
iov,
|
||||
iovcnt,
|
||||
offset as usize,
|
||||
(offset >> 32) as usize,
|
||||
flags,
|
||||
)
|
||||
}
|
||||
pub(in super::super) unsafe fn pwritev64v2(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset: libc::off64_t,
|
||||
flags: libc::c_int,
|
||||
) -> libc::ssize_t {
|
||||
// Unlike the plain "p" functions, the "pv" functions pass their offset
|
||||
// in an endian-independent way, and always in two registers.
|
||||
syscall! {
|
||||
fn pwritev2(
|
||||
fd: libc::c_int,
|
||||
iov: *const libc::iovec,
|
||||
iovcnt: libc::c_int,
|
||||
offset_lo: usize,
|
||||
offset_hi: usize,
|
||||
flags: libc::c_int
|
||||
) via SYS_pwritev2 -> libc::ssize_t
|
||||
}
|
||||
pwritev2(
|
||||
fd,
|
||||
iov,
|
||||
iovcnt,
|
||||
offset as usize,
|
||||
(offset >> 32) as usize,
|
||||
flags,
|
||||
)
|
||||
}
|
||||
}
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
all(target_os = "linux", not(target_env = "gnu")),
|
||||
))]
|
||||
pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2};
|
||||
255
third-party/vendor/rustix/src/backend/libc/conv.rs
vendored
Normal file
255
third-party/vendor/rustix/src/backend/libc/conv.rs
vendored
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
//! 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.
|
||||
|
||||
use super::c;
|
||||
#[cfg(all(feature = "alloc", not(any(windows, target_os = "espidf"))))]
|
||||
use super::fd::IntoRawFd;
|
||||
use super::fd::{AsRawFd, BorrowedFd, FromRawFd, LibcFd, OwnedFd, RawFd};
|
||||
#[cfg(not(windows))]
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(super) fn c_str(c: &CStr) -> *const c::c_char {
|
||||
c.as_ptr()
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(super) fn no_fd() -> LibcFd {
|
||||
-1
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn borrowed_fd(fd: BorrowedFd<'_>) -> LibcFd {
|
||||
fd.as_raw_fd() as LibcFd
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "alloc",
|
||||
not(any(windows, target_os = "espidf", target_os = "redox"))
|
||||
))]
|
||||
#[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())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(apple)]
|
||||
#[inline]
|
||||
pub(super) fn nonnegative_ret(raw: c::c_int) -> io::Result<()> {
|
||||
if raw >= 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Errno::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "wasi")))]
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, all(target_os = "redox", feature = "event")))]
|
||||
#[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_usize(raw: c::ssize_t) -> io::Result<usize> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
debug_assert!(raw >= 0);
|
||||
Ok(raw as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "fs")]
|
||||
#[inline]
|
||||
pub(super) fn ret_off_t(raw: c::off_t) -> io::Result<c::off_t> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(raw)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "wasi")))]
|
||||
#[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))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(super) fn ret_discarded_fd(raw: LibcFd) -> io::Result<()> {
|
||||
if raw == !0 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "alloc", not(any(windows, target_os = "wasi"))))]
|
||||
#[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 the buffer-length argument value of a `send` or `recv` call.
|
||||
#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
|
||||
#[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(any(windows, target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(super) fn ret_send_recv(len: isize) -> io::Result<usize> {
|
||||
ret_usize(len)
|
||||
}
|
||||
|
||||
/// Convert the return value of a `send` or `recv` call.
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(super) fn ret_send_recv(len: i32) -> io::Result<usize> {
|
||||
ret_usize(len as isize)
|
||||
}
|
||||
|
||||
/// Convert the value to the `msg_iovlen` field of a `msghdr` struct.
|
||||
#[cfg(all(
|
||||
not(any(windows, target_os = "espidf", target_os = "redox", target_os = "wasi")),
|
||||
any(
|
||||
target_os = "android",
|
||||
all(
|
||||
target_os = "linux",
|
||||
not(target_env = "musl"),
|
||||
not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
|
||||
)
|
||||
)
|
||||
))]
|
||||
#[inline]
|
||||
pub(super) fn msg_iov_len(len: usize) -> c::size_t {
|
||||
len
|
||||
}
|
||||
|
||||
/// Convert the value to the `msg_iovlen` field of a `msghdr` struct.
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
windows,
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)),
|
||||
not(any(
|
||||
target_os = "android",
|
||||
all(
|
||||
target_os = "linux",
|
||||
not(target_env = "musl"),
|
||||
not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
|
||||
)
|
||||
))
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn msg_iov_len(len: usize) -> c::c_int {
|
||||
len.try_into().unwrap_or(c::c_int::MAX)
|
||||
}
|
||||
|
||||
/// Convert the value to a `socklen_t`.
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_env = "musl",
|
||||
target_os = "aix",
|
||||
target_os = "emscripten",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn msg_control_len(len: usize) -> c::socklen_t {
|
||||
len.try_into().unwrap_or(c::socklen_t::MAX)
|
||||
}
|
||||
|
||||
/// Convert the value to a `size_t`.
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
windows,
|
||||
target_env = "musl",
|
||||
target_os = "aix",
|
||||
target_os = "emscripten",
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn msg_control_len(len: usize) -> c::size_t {
|
||||
len
|
||||
}
|
||||
506
third-party/vendor/rustix/src/backend/libc/event/epoll.rs
vendored
Normal file
506
third-party/vendor/rustix/src/backend/libc/event/epoll.rs
vendored
Normal file
|
|
@ -0,0 +1,506 @@
|
|||
//! Linux `epoll` support.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # #[cfg(feature = "net")]
|
||||
//! # fn main() -> std::io::Result<()> {
|
||||
//! use rustix::event::epoll;
|
||||
//! use rustix::fd::AsFd;
|
||||
//! use rustix::io::{ioctl_fionbio, read, write};
|
||||
//! use rustix::net::{
|
||||
//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, SocketType,
|
||||
//! };
|
||||
//! use std::collections::HashMap;
|
||||
//! use std::os::unix::io::AsRawFd;
|
||||
//!
|
||||
//! // Create a socket and listen on it.
|
||||
//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, None)?;
|
||||
//! 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::create(epoll::CreateFlags::CLOEXEC)?;
|
||||
//!
|
||||
//! // Register the socket with the epoll object.
|
||||
//! epoll::add(
|
||||
//! &epoll,
|
||||
//! &listen_sock,
|
||||
//! epoll::EventData::new_u64(1),
|
||||
//! epoll::EventFlags::IN,
|
||||
//! )?;
|
||||
//!
|
||||
//! // Keep track of the sockets we've opened.
|
||||
//! let mut next_id = epoll::EventData::new_u64(2);
|
||||
//! let mut sockets = HashMap::new();
|
||||
//!
|
||||
//! // Process events.
|
||||
//! let mut event_list = epoll::EventVec::with_capacity(4);
|
||||
//! loop {
|
||||
//! epoll::wait(&epoll, &mut event_list, -1)?;
|
||||
//! for event in &event_list {
|
||||
//! let target = event.data;
|
||||
//! if target.u64() == 1 {
|
||||
//! // 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(&listen_sock)?;
|
||||
//! ioctl_fionbio(&conn_sock, true)?;
|
||||
//! epoll::add(
|
||||
//! &epoll,
|
||||
//! &conn_sock,
|
||||
//! next_id,
|
||||
//! epoll::EventFlags::OUT | epoll::EventFlags::ET,
|
||||
//! )?;
|
||||
//!
|
||||
//! // Keep track of the socket.
|
||||
//! sockets.insert(next_id, conn_sock);
|
||||
//! next_id = epoll::EventData::new_u64(next_id.u64() + 1);
|
||||
//! } else {
|
||||
//! // Write a message to the stream and then unregister it.
|
||||
//! let target = sockets.remove(&target).unwrap();
|
||||
//! write(&target, b"hello\n")?;
|
||||
//! let _ = epoll::delete(&epoll, &target)?;
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! # }
|
||||
//! # #[cfg(not(feature = "net"))]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
use crate::backend::c;
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::backend::conv::ret_u32;
|
||||
use crate::backend::conv::{ret, ret_owned_fd};
|
||||
use crate::fd::{AsFd, AsRawFd, OwnedFd};
|
||||
use crate::io;
|
||||
use crate::utils::as_mut_ptr;
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::vec::Vec;
|
||||
use bitflags::bitflags;
|
||||
use core::ffi::c_void;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::ptr::null_mut;
|
||||
use core::slice;
|
||||
|
||||
bitflags! {
|
||||
/// `EPOLL_*` for use with [`new`].
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct CreateFlags: u32 {
|
||||
/// `EPOLL_CLOEXEC`
|
||||
const CLOEXEC = bitcast!(c::EPOLL_CLOEXEC);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `EPOLL*` for use with [`add`].
|
||||
#[repr(transparent)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct EventFlags: u32 {
|
||||
/// `EPOLLIN`
|
||||
const IN = bitcast!(c::EPOLLIN);
|
||||
|
||||
/// `EPOLLOUT`
|
||||
const OUT = bitcast!(c::EPOLLOUT);
|
||||
|
||||
/// `EPOLLPRI`
|
||||
const PRI = bitcast!(c::EPOLLPRI);
|
||||
|
||||
/// `EPOLLERR`
|
||||
const ERR = bitcast!(c::EPOLLERR);
|
||||
|
||||
/// `EPOLLHUP`
|
||||
const HUP = bitcast!(c::EPOLLHUP);
|
||||
|
||||
/// `EPOLLRDNORM`
|
||||
const RDNORM = bitcast!(c::EPOLLRDNORM);
|
||||
|
||||
/// `EPOLLRDBAND`
|
||||
const RDBAND = bitcast!(c::EPOLLRDBAND);
|
||||
|
||||
/// `EPOLLWRNORM`
|
||||
const WRNORM = bitcast!(c::EPOLLWRNORM);
|
||||
|
||||
/// `EPOLLWRBAND`
|
||||
const WRBAND = bitcast!(c::EPOLLWRBAND);
|
||||
|
||||
/// `EPOLLMSG`
|
||||
const MSG = bitcast!(c::EPOLLMSG);
|
||||
|
||||
/// `EPOLLRDHUP`
|
||||
const RDHUP = bitcast!(c::EPOLLRDHUP);
|
||||
|
||||
/// `EPOLLET`
|
||||
const ET = bitcast!(c::EPOLLET);
|
||||
|
||||
/// `EPOLLONESHOT`
|
||||
const ONESHOT = bitcast!(c::EPOLLONESHOT);
|
||||
|
||||
/// `EPOLLWAKEUP`
|
||||
const WAKEUP = bitcast!(c::EPOLLWAKEUP);
|
||||
|
||||
/// `EPOLLEXCLUSIVE`
|
||||
#[cfg(not(target_os = "android"))]
|
||||
const EXCLUSIVE = bitcast!(c::EPOLLEXCLUSIVE);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_create1(flags)`—Creates a new epoll object.
|
||||
///
|
||||
/// 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 create(flags: CreateFlags) -> io::Result<OwnedFd> {
|
||||
// SAFETY: We're calling `epoll_create1` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe { ret_owned_fd(c::epoll_create1(bitflags_bits!(flags))) }
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an epoll
|
||||
/// object.
|
||||
///
|
||||
/// This registers interest in any of the events set in `events` occurring on
|
||||
/// the file descriptor associated with `data`.
|
||||
///
|
||||
/// If [`delete`] is not called on the I/O source passed into this function
|
||||
/// before the I/O source is `close`d, then the `epoll` will act as if the I/O
|
||||
/// source is still registered with it. This can lead to spurious events being
|
||||
/// returned from [`wait`]. If a file descriptor is an
|
||||
/// `Arc<dyn SystemResource>`, then `epoll` can be thought to maintain a
|
||||
/// `Weak<dyn SystemResource>` to the file descriptor.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
pub fn add(
|
||||
epoll: impl AsFd,
|
||||
source: impl AsFd,
|
||||
data: EventData,
|
||||
event_flags: EventFlags,
|
||||
) -> io::Result<()> {
|
||||
// SAFETY: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves. We use our own `Event` struct instead of libc's because
|
||||
// ours preserves pointer provenance instead of just using a `u64`,
|
||||
// and we have tests elsewhere for layout equivalence.
|
||||
unsafe {
|
||||
let raw_fd = source.as_fd().as_raw_fd();
|
||||
ret(c::epoll_ctl(
|
||||
epoll.as_fd().as_raw_fd(),
|
||||
c::EPOLL_CTL_ADD,
|
||||
raw_fd,
|
||||
as_mut_ptr(&mut Event {
|
||||
flags: event_flags,
|
||||
data,
|
||||
#[cfg(target_os = "redox")]
|
||||
_pad: 0,
|
||||
})
|
||||
.cast(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in a
|
||||
/// given epoll object.
|
||||
///
|
||||
/// This sets the events of interest with `target` to `events`.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
pub fn modify(
|
||||
epoll: impl AsFd,
|
||||
source: impl AsFd,
|
||||
data: EventData,
|
||||
event_flags: EventFlags,
|
||||
) -> io::Result<()> {
|
||||
let raw_fd = source.as_fd().as_raw_fd();
|
||||
|
||||
// SAFETY: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves. We use our own `Event` struct instead of libc's because
|
||||
// ours preserves pointer provenance instead of just using a `u64`,
|
||||
// and we have tests elsewhere for layout equivalence.
|
||||
unsafe {
|
||||
ret(c::epoll_ctl(
|
||||
epoll.as_fd().as_raw_fd(),
|
||||
c::EPOLL_CTL_MOD,
|
||||
raw_fd,
|
||||
as_mut_ptr(&mut Event {
|
||||
flags: event_flags,
|
||||
data,
|
||||
#[cfg(target_os = "redox")]
|
||||
_pad: 0,
|
||||
})
|
||||
.cast(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in a
|
||||
/// given epoll object.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
|
||||
// SAFETY: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
let raw_fd = source.as_fd().as_raw_fd();
|
||||
ret(c::epoll_ctl(
|
||||
epoll.as_fd().as_raw_fd(),
|
||||
c::EPOLL_CTL_DEL,
|
||||
raw_fd,
|
||||
null_mut(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// `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.
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
||||
pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, 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(
|
||||
epoll.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);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// An iterator over the `Event`s in an `EventVec`.
|
||||
pub struct Iter<'a> {
|
||||
/// Use `Copied` to copy the struct, since `Event` is `packed` on some
|
||||
/// platforms, and it's common for users to directly destructure it, which
|
||||
/// would lead to errors about forming references to packed fields.
|
||||
iter: core::iter::Copied<slice::Iter<'a, Event>>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = Event;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
/// A record of an event that occurred.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(
|
||||
all(
|
||||
linux_kernel,
|
||||
any(
|
||||
all(
|
||||
target_arch = "x86",
|
||||
not(target_env = "musl"),
|
||||
not(target_os = "android"),
|
||||
),
|
||||
target_arch = "x86_64",
|
||||
)
|
||||
),
|
||||
repr(packed)
|
||||
)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Event {
|
||||
/// Which specific event(s) occurred.
|
||||
pub flags: EventFlags,
|
||||
/// User data.
|
||||
pub data: EventData,
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
_pad: u64,
|
||||
}
|
||||
|
||||
/// Data associated with an [`Event`]. This can either be a 64-bit integer
|
||||
/// value or a pointer which preserves pointer provenance.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union EventData {
|
||||
/// A 64-bit integer value.
|
||||
as_u64: u64,
|
||||
|
||||
/// A `*mut c_void` which preserves pointer provenance, extended to be
|
||||
/// 64-bit so that if we read the value as a `u64` union field, we don't
|
||||
/// get uninitialized memory.
|
||||
sixty_four_bit_pointer: SixtyFourBitPointer,
|
||||
}
|
||||
|
||||
impl EventData {
|
||||
/// Construct a new value containing a `u64`.
|
||||
#[inline]
|
||||
pub const fn new_u64(value: u64) -> Self {
|
||||
Self { as_u64: value }
|
||||
}
|
||||
|
||||
/// Construct a new value containing a `*mut c_void`.
|
||||
#[inline]
|
||||
pub const fn new_ptr(value: *mut c_void) -> Self {
|
||||
Self {
|
||||
sixty_four_bit_pointer: SixtyFourBitPointer {
|
||||
pointer: value,
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
_padding: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the value as a `u64`.
|
||||
///
|
||||
/// If the stored value was a pointer, the pointer is zero-extended to a
|
||||
/// `u64`.
|
||||
#[inline]
|
||||
pub fn u64(self) -> u64 {
|
||||
unsafe { self.as_u64 }
|
||||
}
|
||||
|
||||
/// Return the value as a `*mut c_void`.
|
||||
///
|
||||
/// If the stored value was a `u64`, the least-significant bits of the
|
||||
/// `u64` are returned as a pointer value.
|
||||
#[inline]
|
||||
pub fn ptr(self) -> *mut c_void {
|
||||
unsafe { self.sixty_four_bit_pointer.pointer }
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for EventData {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.u64() == other.u64()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for EventData {}
|
||||
|
||||
impl Hash for EventData {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.u64().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct SixtyFourBitPointer {
|
||||
#[cfg(target_endian = "big")]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
_padding: u32,
|
||||
|
||||
pointer: *mut c_void,
|
||||
|
||||
#[cfg(target_endian = "little")]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
_padding: u32,
|
||||
}
|
||||
|
||||
/// A vector of `Event`s, plus context for interpreting them.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub struct EventVec {
|
||||
events: Vec<Event>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl EventVec {
|
||||
/// Constructs an `EventVec` from raw pointer, length, and capacity.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function calls [`Vec::from_raw_parts`] with its arguments.
|
||||
///
|
||||
/// [`Vec::from_raw_parts`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.from_raw_parts
|
||||
#[inline]
|
||||
pub unsafe fn from_raw_parts(ptr: *mut Event, len: usize, capacity: usize) -> Self {
|
||||
Self {
|
||||
events: Vec::from_raw_parts(ptr, len, capacity),
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an `EventVec` with memory for `capacity` `Event`s.
|
||||
#[inline]
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
Self {
|
||||
events: Vec::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<'_> {
|
||||
Iter {
|
||||
iter: self.events.iter().copied(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> IntoIterator for &'a EventVec {
|
||||
type IntoIter = Iter<'a>;
|
||||
type Item = Event;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_epoll_layouts() {
|
||||
check_renamed_type!(Event, epoll_event);
|
||||
check_renamed_type!(Event, epoll_event);
|
||||
check_renamed_struct_renamed_field!(Event, epoll_event, flags, events);
|
||||
check_renamed_struct_renamed_field!(Event, epoll_event, data, u64);
|
||||
}
|
||||
9
third-party/vendor/rustix/src/backend/libc/event/mod.rs
vendored
Normal file
9
third-party/vendor/rustix/src/backend/libc/event/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
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(linux_kernel, target_os = "redox"))]
|
||||
pub mod epoll;
|
||||
142
third-party/vendor/rustix/src/backend/libc/event/poll_fd.rs
vendored
Normal file
142
third-party/vendor/rustix/src/backend/libc/event/poll_fd.rs
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
use crate::backend::c;
|
||||
use crate::backend::conv::borrowed_fd;
|
||||
use crate::backend::fd::{AsFd, AsRawFd, BorrowedFd, LibcFd};
|
||||
use bitflags::bitflags;
|
||||
use core::marker::PhantomData;
|
||||
#[cfg(windows)]
|
||||
use {
|
||||
crate::backend::fd::{AsSocket, RawFd},
|
||||
core::fmt,
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
/// `POLL*` flags for use with [`poll`].
|
||||
///
|
||||
/// [`poll`]: crate::event::poll
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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`
|
||||
const RDNORM = c::POLLRDNORM;
|
||||
/// `POLLWRNORM`
|
||||
#[cfg(not(target_os = "l4re"))]
|
||||
const WRNORM = c::POLLWRNORM;
|
||||
/// `POLLRDBAND`
|
||||
#[cfg(not(any(target_os = "l4re", target_os = "wasi")))]
|
||||
const RDBAND = c::POLLRDBAND;
|
||||
/// `POLLWRBAND`
|
||||
#[cfg(not(any(target_os = "l4re", target_os = "wasi")))]
|
||||
const WRBAND = c::POLLWRBAND;
|
||||
/// `POLLERR`
|
||||
const ERR = c::POLLERR;
|
||||
/// `POLLHUP`
|
||||
const HUP = c::POLLHUP;
|
||||
/// `POLLNVAL`
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
const NVAL = c::POLLNVAL;
|
||||
/// `POLLRDHUP`
|
||||
#[cfg(all(
|
||||
linux_kernel,
|
||||
not(any(target_arch = "sparc", target_arch = "sparc64"))),
|
||||
)]
|
||||
const RDHUP = c::POLLRDHUP;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `struct pollfd`—File descriptor and flags for use with [`poll`].
|
||||
///
|
||||
/// [`poll`]: crate::event::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> 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) }
|
||||
}
|
||||
}
|
||||
191
third-party/vendor/rustix/src/backend/libc/event/syscalls.rs
vendored
Normal file
191
third-party/vendor/rustix/src/backend/libc/event/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
//! libc syscalls supporting `rustix::event`.
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::ret_c_int;
|
||||
#[cfg(any(apple, netbsdlike, target_os = "dragonfly", target_os = "solaris"))]
|
||||
use crate::backend::conv::ret_owned_fd;
|
||||
use crate::event::PollFd;
|
||||
#[cfg(any(linux_kernel, bsd, solarish, target_os = "espidf"))]
|
||||
use crate::fd::OwnedFd;
|
||||
use crate::io;
|
||||
#[cfg(any(bsd, solarish))]
|
||||
use {crate::backend::conv::borrowed_fd, crate::fd::BorrowedFd, core::mem::MaybeUninit};
|
||||
#[cfg(solarish)]
|
||||
use {
|
||||
crate::backend::conv::ret, crate::event::port::Event, crate::utils::as_mut_ptr,
|
||||
core::ptr::null_mut,
|
||||
};
|
||||
#[cfg(any(
|
||||
linux_kernel,
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "espidf"
|
||||
))]
|
||||
use {crate::backend::conv::ret_owned_fd, crate::event::EventfdFlags};
|
||||
#[cfg(all(feature = "alloc", bsd))]
|
||||
use {crate::event::kqueue::Event, crate::utils::as_ptr, core::ptr::null};
|
||||
|
||||
#[cfg(any(
|
||||
linux_kernel,
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "espidf"
|
||||
))]
|
||||
pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
|
||||
#[cfg(linux_kernel)]
|
||||
unsafe {
|
||||
syscall! {
|
||||
fn eventfd2(
|
||||
initval: c::c_uint,
|
||||
flags: c::c_int
|
||||
) via SYS_eventfd2 -> c::c_int
|
||||
}
|
||||
ret_owned_fd(eventfd2(initval, bitflags_bits!(flags)))
|
||||
}
|
||||
|
||||
// `eventfd` was added in FreeBSD 13, so it isn't available on FreeBSD 12.
|
||||
#[cfg(target_os = "freebsd")]
|
||||
unsafe {
|
||||
weakcall! {
|
||||
fn eventfd(
|
||||
initval: c::c_uint,
|
||||
flags: c::c_int
|
||||
) -> c::c_int
|
||||
}
|
||||
ret_owned_fd(eventfd(initval, bitflags_bits!(flags)))
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "illumos", target_os = "espidf"))]
|
||||
unsafe {
|
||||
ret_owned_fd(c::eventfd(initval, bitflags_bits!(flags)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "alloc", bsd))]
|
||||
pub(crate) fn kqueue() -> io::Result<OwnedFd> {
|
||||
unsafe { ret_owned_fd(c::kqueue()) }
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "alloc", bsd))]
|
||||
pub(crate) unsafe fn kevent(
|
||||
kq: BorrowedFd<'_>,
|
||||
changelist: &[Event],
|
||||
eventlist: &mut [MaybeUninit<Event>],
|
||||
timeout: Option<&c::timespec>,
|
||||
) -> io::Result<c::c_int> {
|
||||
ret_c_int(c::kevent(
|
||||
borrowed_fd(kq),
|
||||
changelist.as_ptr().cast(),
|
||||
changelist
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
eventlist.as_mut_ptr().cast(),
|
||||
eventlist
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
timeout.map_or(null(), as_ptr),
|
||||
))
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
|
||||
#[cfg(solarish)]
|
||||
pub(crate) fn port_create() -> io::Result<OwnedFd> {
|
||||
unsafe { ret_owned_fd(c::port_create()) }
|
||||
}
|
||||
|
||||
#[cfg(solarish)]
|
||||
pub(crate) unsafe fn port_associate(
|
||||
port: BorrowedFd<'_>,
|
||||
source: c::c_int,
|
||||
object: c::uintptr_t,
|
||||
events: c::c_int,
|
||||
user: *mut c::c_void,
|
||||
) -> io::Result<()> {
|
||||
ret(c::port_associate(
|
||||
borrowed_fd(port),
|
||||
source,
|
||||
object,
|
||||
events,
|
||||
user,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(solarish)]
|
||||
pub(crate) unsafe fn port_dissociate(
|
||||
port: BorrowedFd<'_>,
|
||||
source: c::c_int,
|
||||
object: c::uintptr_t,
|
||||
) -> io::Result<()> {
|
||||
ret(c::port_dissociate(borrowed_fd(port), source, object))
|
||||
}
|
||||
|
||||
#[cfg(solarish)]
|
||||
pub(crate) fn port_get(
|
||||
port: BorrowedFd<'_>,
|
||||
timeout: Option<&mut c::timespec>,
|
||||
) -> io::Result<Event> {
|
||||
let mut event = MaybeUninit::<c::port_event>::uninit();
|
||||
let timeout = timeout.map_or(null_mut(), as_mut_ptr);
|
||||
|
||||
unsafe {
|
||||
ret(c::port_get(borrowed_fd(port), event.as_mut_ptr(), timeout))?;
|
||||
}
|
||||
|
||||
// If we're done, initialize the event and return it.
|
||||
Ok(Event(unsafe { event.assume_init() }))
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "alloc", solarish))]
|
||||
pub(crate) fn port_getn(
|
||||
port: BorrowedFd<'_>,
|
||||
timeout: Option<&mut c::timespec>,
|
||||
events: &mut Vec<Event>,
|
||||
mut nget: u32,
|
||||
) -> io::Result<()> {
|
||||
let timeout = timeout.map_or(null_mut(), as_mut_ptr);
|
||||
unsafe {
|
||||
ret(c::port_getn(
|
||||
borrowed_fd(port),
|
||||
events.as_mut_ptr().cast(),
|
||||
events.len().try_into().unwrap(),
|
||||
&mut nget,
|
||||
timeout,
|
||||
))?;
|
||||
}
|
||||
|
||||
// Update the vector length.
|
||||
unsafe {
|
||||
events.set_len(nget.try_into().unwrap());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(solarish)]
|
||||
pub(crate) fn port_send(
|
||||
port: BorrowedFd<'_>,
|
||||
events: c::c_int,
|
||||
userdata: *mut c::c_void,
|
||||
) -> io::Result<()> {
|
||||
unsafe { ret(c::port_send(borrowed_fd(port), events, userdata)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn pause() {
|
||||
let r = unsafe { libc::pause() };
|
||||
let errno = libc_errno::errno().0;
|
||||
debug_assert_eq!(r, -1);
|
||||
debug_assert_eq!(errno, libc::EINTR);
|
||||
}
|
||||
37
third-party/vendor/rustix/src/backend/libc/event/types.rs
vendored
Normal file
37
third-party/vendor/rustix/src/backend/libc/event/types.rs
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))]
|
||||
use crate::backend::c;
|
||||
#[cfg(any(
|
||||
linux_kernel,
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "espidf"
|
||||
))]
|
||||
use bitflags::bitflags;
|
||||
|
||||
#[cfg(any(
|
||||
linux_kernel,
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "espidf"
|
||||
))]
|
||||
bitflags! {
|
||||
/// `EFD_*` flags for use with [`eventfd`].
|
||||
///
|
||||
/// [`eventfd`]: crate::event::eventfd
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct EventfdFlags: u32 {
|
||||
/// `EFD_CLOEXEC`
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
const CLOEXEC = bitcast!(c::EFD_CLOEXEC);
|
||||
/// `EFD_NONBLOCK`
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
const NONBLOCK = bitcast!(c::EFD_NONBLOCK);
|
||||
/// `EFD_SEMAPHORE`
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
const SEMAPHORE = bitcast!(c::EFD_SEMAPHORE);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
16
third-party/vendor/rustix/src/backend/libc/event/windows_syscalls.rs
vendored
Normal file
16
third-party/vendor/rustix/src/backend/libc/event/windows_syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//! Windows system calls in the `event` module.
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::ret_c_int;
|
||||
use crate::event::PollFd;
|
||||
use crate::io;
|
||||
|
||||
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)
|
||||
}
|
||||
423
third-party/vendor/rustix/src/backend/libc/fs/dir.rs
vendored
Normal file
423
third-party/vendor/rustix/src/backend/libc/fs/dir.rs
vendored
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
#[cfg(not(any(solarish, target_os = "haiku", target_os = "nto", target_os = "vita")))]
|
||||
use super::types::FileType;
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::owned_fd;
|
||||
use crate::fd::{AsFd, BorrowedFd, OwnedFd};
|
||||
use crate::ffi::{CStr, CString};
|
||||
use crate::fs::{fcntl_getfl, openat, Mode, OFlags};
|
||||
#[cfg(not(target_os = "vita"))]
|
||||
use crate::fs::{fstat, Stat};
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "haiku",
|
||||
target_os = "netbsd",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
use crate::fs::{fstatfs, StatFs};
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "haiku",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use crate::fs::{fstatvfs, StatVfs};
|
||||
use crate::io;
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "vita", target_os = "wasi")))]
|
||||
#[cfg(feature = "process")]
|
||||
use crate::process::fchdir;
|
||||
use alloc::borrow::ToOwned;
|
||||
#[cfg(not(any(linux_like, target_os = "hurd")))]
|
||||
use c::readdir as libc_readdir;
|
||||
#[cfg(any(linux_like, target_os = "hurd"))]
|
||||
use c::readdir64 as libc_readdir;
|
||||
use core::fmt;
|
||||
use core::ptr::NonNull;
|
||||
use libc_errno::{errno, set_errno, Errno};
|
||||
|
||||
/// `DIR*`
|
||||
pub struct Dir {
|
||||
/// The `libc` `DIR` pointer.
|
||||
libc_dir: NonNull<c::DIR>,
|
||||
|
||||
/// Have we seen any errors in this iteration?
|
||||
any_errors: bool,
|
||||
}
|
||||
|
||||
impl Dir {
|
||||
/// Take ownership of `fd` and construct a `Dir` that reads entries from
|
||||
/// the given directory file descriptor.
|
||||
#[inline]
|
||||
pub fn new<Fd: Into<OwnedFd>>(fd: Fd) -> io::Result<Self> {
|
||||
Self::_new(fd.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn _new(fd: OwnedFd) -> io::Result<Self> {
|
||||
let raw = owned_fd(fd);
|
||||
unsafe {
|
||||
let libc_dir = c::fdopendir(raw);
|
||||
|
||||
if let Some(libc_dir) = NonNull::new(libc_dir) {
|
||||
Ok(Self {
|
||||
libc_dir,
|
||||
any_errors: false,
|
||||
})
|
||||
} else {
|
||||
let err = io::Errno::last_os_error();
|
||||
let _ = c::close(raw);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Borrow `fd` and 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]
|
||||
#[allow(unused_mut)]
|
||||
fn _read_from(fd: BorrowedFd<'_>) -> io::Result<Self> {
|
||||
let mut any_errors = false;
|
||||
|
||||
// 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 = match openat(fd, cstr!("."), flags | OFlags::CLOEXEC, Mode::empty()) {
|
||||
Ok(fd) => fd,
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
Err(io::Errno::NOENT) => {
|
||||
// If "." doesn't exist, it means the directory was removed.
|
||||
// We treat that as iterating through a directory with no
|
||||
// entries.
|
||||
any_errors = true;
|
||||
crate::io::dup(fd)?
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
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,
|
||||
any_errors,
|
||||
})
|
||||
} else {
|
||||
let err = io::Errno::last_os_error();
|
||||
let _ = c::close(raw);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `rewinddir(self)`
|
||||
#[inline]
|
||||
pub fn rewind(&mut self) {
|
||||
self.any_errors = false;
|
||||
unsafe { c::rewinddir(self.libc_dir.as_ptr()) }
|
||||
}
|
||||
|
||||
/// `readdir(self)`, where `None` means the end of the directory.
|
||||
pub fn read(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
// If we've seen errors, don't continue to try to read anything further.
|
||||
if self.any_errors {
|
||||
return None;
|
||||
}
|
||||
|
||||
set_errno(Errno(0));
|
||||
let dirent_ptr = unsafe { libc_readdir(self.libc_dir.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.
|
||||
self.any_errors = true;
|
||||
Some(Err(io::Errno(curr_errno)))
|
||||
}
|
||||
} else {
|
||||
// We successfully read an entry.
|
||||
unsafe {
|
||||
let dirent = &*dirent_ptr;
|
||||
|
||||
// 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);
|
||||
|
||||
let result = DirEntry {
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
d_type: dirent.d_type,
|
||||
|
||||
#[cfg(not(any(freebsdlike, netbsdlike, target_os = "vita")))]
|
||||
d_ino: dirent.d_ino,
|
||||
|
||||
#[cfg(any(freebsdlike, netbsdlike))]
|
||||
d_fileno: dirent.d_fileno,
|
||||
|
||||
name: CStr::from_ptr(dirent.d_name.as_ptr()).to_owned(),
|
||||
};
|
||||
|
||||
Some(Ok(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `fstat(self)`
|
||||
#[cfg(not(target_os = "vita"))]
|
||||
#[inline]
|
||||
pub fn stat(&self) -> io::Result<Stat> {
|
||||
fstat(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.libc_dir.as_ptr())) })
|
||||
}
|
||||
|
||||
/// `fstatfs(self)`
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "haiku",
|
||||
target_os = "netbsd",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[inline]
|
||||
pub fn statfs(&self) -> io::Result<StatFs> {
|
||||
fstatfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.libc_dir.as_ptr())) })
|
||||
}
|
||||
|
||||
/// `fstatvfs(self)`
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "haiku",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[inline]
|
||||
pub fn statvfs(&self) -> io::Result<StatVfs> {
|
||||
fstatvfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.libc_dir.as_ptr())) })
|
||||
}
|
||||
|
||||
/// `fchdir(self)`
|
||||
#[cfg(feature = "process")]
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "vita", target_os = "wasi")))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "process")))]
|
||||
#[inline]
|
||||
pub fn chdir(&self) -> io::Result<()> {
|
||||
fchdir(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.libc_dir.as_ptr())) })
|
||||
}
|
||||
}
|
||||
|
||||
/// `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.libc_dir.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 {
|
||||
let mut s = f.debug_struct("Dir");
|
||||
#[cfg(not(target_os = "vita"))]
|
||||
s.field("fd", unsafe { &c::dirfd(self.libc_dir.as_ptr()) });
|
||||
s.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// `struct dirent`
|
||||
#[derive(Debug)]
|
||||
pub struct DirEntry {
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
d_type: u8,
|
||||
|
||||
#[cfg(not(any(freebsdlike, netbsdlike, target_os = "vita")))]
|
||||
d_ino: c::ino_t,
|
||||
|
||||
#[cfg(any(freebsdlike, netbsdlike))]
|
||||
d_fileno: c::ino_t,
|
||||
|
||||
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.
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
#[inline]
|
||||
pub fn file_type(&self) -> FileType {
|
||||
FileType::from_dirent_d_type(self.d_type)
|
||||
}
|
||||
|
||||
/// Return the inode number of this directory entry.
|
||||
#[cfg(not(any(freebsdlike, netbsdlike, target_os = "vita")))]
|
||||
#[inline]
|
||||
pub fn ino(&self) -> u64 {
|
||||
self.d_ino as u64
|
||||
}
|
||||
|
||||
/// Return the inode number of this directory entry.
|
||||
#[cfg(any(freebsdlike, netbsdlike))]
|
||||
#[inline]
|
||||
pub fn ino(&self) -> u64 {
|
||||
#[allow(clippy::useless_conversion)]
|
||||
self.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;
|
||||
|
||||
// Check that the basic layouts match.
|
||||
#[cfg(test)]
|
||||
{
|
||||
assert_eq_size!(libc_dirent, c::dirent);
|
||||
assert_eq_size!(libc_dirent, 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,
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir_iterator_handles_io_errors() {
|
||||
// create a dir, keep the FD, then delete the dir
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let fd = crate::fs::openat(
|
||||
crate::fs::CWD,
|
||||
tmp.path(),
|
||||
crate::fs::OFlags::RDONLY | crate::fs::OFlags::CLOEXEC,
|
||||
crate::fs::Mode::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let file_fd = crate::fs::openat(
|
||||
&fd,
|
||||
tmp.path().join("test.txt"),
|
||||
crate::fs::OFlags::WRONLY | crate::fs::OFlags::CREATE,
|
||||
crate::fs::Mode::RWXU,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut dir = Dir::read_from(&fd).unwrap();
|
||||
|
||||
// Reach inside the `Dir` and replace its directory with a file, which
|
||||
// will cause the subsequent `readdir` to fail.
|
||||
unsafe {
|
||||
let raw_fd = c::dirfd(dir.libc_dir.as_ptr());
|
||||
let mut owned_fd: crate::fd::OwnedFd = crate::fd::FromRawFd::from_raw_fd(raw_fd);
|
||||
crate::io::dup2(&file_fd, &mut owned_fd).unwrap();
|
||||
core::mem::forget(owned_fd);
|
||||
}
|
||||
|
||||
// FreeBSD and macOS seem to read some directory entries before we call
|
||||
// `.next()`.
|
||||
#[cfg(any(apple, freebsdlike))]
|
||||
{
|
||||
dir.rewind();
|
||||
}
|
||||
|
||||
assert!(matches!(dir.next(), Some(Err(_))));
|
||||
assert!(dir.next().is_none());
|
||||
}
|
||||
131
third-party/vendor/rustix/src/backend/libc/fs/inotify.rs
vendored
Normal file
131
third-party/vendor/rustix/src/backend/libc/fs/inotify.rs
vendored
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
//! inotify support for working with inotifies
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::{borrowed_fd, c_str, ret, ret_c_int, ret_owned_fd};
|
||||
use crate::fd::{BorrowedFd, OwnedFd};
|
||||
use crate::io;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `IN_*` for use with [`inotify_init`].
|
||||
///
|
||||
/// [`inotify_init`]: crate::fs::inotify::inotify_init
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct CreateFlags: u32 {
|
||||
/// `IN_CLOEXEC`
|
||||
const CLOEXEC = bitcast!(c::IN_CLOEXEC);
|
||||
/// `IN_NONBLOCK`
|
||||
const NONBLOCK = bitcast!(c::IN_NONBLOCK);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `IN*` for use with [`inotify_add_watch`].
|
||||
///
|
||||
/// [`inotify_add_watch`]: crate::fs::inotify::inotify_add_watch
|
||||
#[repr(transparent)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct WatchFlags: u32 {
|
||||
/// `IN_ACCESS`
|
||||
const ACCESS = c::IN_ACCESS;
|
||||
/// `IN_ATTRIB`
|
||||
const ATTRIB = c::IN_ATTRIB;
|
||||
/// `IN_CLOSE_NOWRITE`
|
||||
const CLOSE_NOWRITE = c::IN_CLOSE_NOWRITE;
|
||||
/// `IN_CLOSE_WRITE`
|
||||
const CLOSE_WRITE = c::IN_CLOSE_WRITE;
|
||||
/// `IN_CREATE`
|
||||
const CREATE = c::IN_CREATE;
|
||||
/// `IN_DELETE`
|
||||
const DELETE = c::IN_DELETE;
|
||||
/// `IN_DELETE_SELF`
|
||||
const DELETE_SELF = c::IN_DELETE_SELF;
|
||||
/// `IN_MODIFY`
|
||||
const MODIFY = c::IN_MODIFY;
|
||||
/// `IN_MOVE_SELF`
|
||||
const MOVE_SELF = c::IN_MOVE_SELF;
|
||||
/// `IN_MOVED_FROM`
|
||||
const MOVED_FROM = c::IN_MOVED_FROM;
|
||||
/// `IN_MOVED_TO`
|
||||
const MOVED_TO = c::IN_MOVED_TO;
|
||||
/// `IN_OPEN`
|
||||
const OPEN = c::IN_OPEN;
|
||||
|
||||
/// `IN_CLOSE`
|
||||
const CLOSE = c::IN_CLOSE;
|
||||
/// `IN_MOVE`
|
||||
const MOVE = c::IN_MOVE;
|
||||
/// `IN_ALL_EVENTS`
|
||||
const ALL_EVENTS = c::IN_ALL_EVENTS;
|
||||
|
||||
/// `IN_DONT_FOLLOW`
|
||||
const DONT_FOLLOW = c::IN_DONT_FOLLOW;
|
||||
/// `IN_EXCL_UNLINK`
|
||||
const EXCL_UNLINK = 1;
|
||||
/// `IN_MASK_ADD`
|
||||
const MASK_ADD = 1;
|
||||
/// `IN_MASK_CREATE`
|
||||
const MASK_CREATE = 1;
|
||||
/// `IN_ONESHOT`
|
||||
const ONESHOT = c::IN_ONESHOT;
|
||||
/// `IN_ONLYDIR`
|
||||
const ONLYDIR = c::IN_ONLYDIR;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `inotify_init1(flags)`—Creates a new inotify object.
|
||||
///
|
||||
/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
|
||||
/// descriptor from being implicitly passed across `exec` boundaries.
|
||||
#[doc(alias = "inotify_init1")]
|
||||
pub fn inotify_init(flags: CreateFlags) -> io::Result<OwnedFd> {
|
||||
// SAFETY: `inotify_init1` has no safety preconditions.
|
||||
unsafe { ret_owned_fd(c::inotify_init1(bitflags_bits!(flags))) }
|
||||
}
|
||||
|
||||
/// `inotify_add_watch(self, path, flags)`—Adds a watch to inotify.
|
||||
///
|
||||
/// This registers or updates a watch for the filesystem path `path` and
|
||||
/// returns a watch descriptor corresponding to this watch.
|
||||
///
|
||||
/// Note: Due to the existence of hardlinks, providing two different paths to
|
||||
/// this method may result in it returning the same watch descriptor. An
|
||||
/// application should keep track of this externally to avoid logic errors.
|
||||
pub fn inotify_add_watch<P: crate::path::Arg>(
|
||||
inot: BorrowedFd<'_>,
|
||||
path: P,
|
||||
flags: WatchFlags,
|
||||
) -> io::Result<i32> {
|
||||
path.into_with_c_str(|path| {
|
||||
// SAFETY: The fd and path we are passing is guaranteed valid by the
|
||||
// type system.
|
||||
unsafe {
|
||||
ret_c_int(c::inotify_add_watch(
|
||||
borrowed_fd(inot),
|
||||
c_str(path),
|
||||
flags.bits(),
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// `inotify_rm_watch(self, wd)`—Removes a watch from this inotify.
|
||||
///
|
||||
/// The watch descriptor provided should have previously been returned by
|
||||
/// [`inotify_add_watch`] and not previously have been removed.
|
||||
#[doc(alias = "inotify_rm_watch")]
|
||||
pub fn inotify_remove_watch(inot: BorrowedFd<'_>, wd: i32) -> io::Result<()> {
|
||||
// Android's `inotify_rm_watch` takes `u32` despite that
|
||||
// `inotify_add_watch` expects a `i32`.
|
||||
#[cfg(target_os = "android")]
|
||||
let wd = wd as u32;
|
||||
// SAFETY: The fd is valid and closing an arbitrary wd is valid.
|
||||
unsafe { ret(c::inotify_rm_watch(borrowed_fd(inot), wd)) }
|
||||
}
|
||||
138
third-party/vendor/rustix/src/backend/libc/fs/makedev.rs
vendored
Normal file
138
third-party/vendor/rustix/src/backend/libc/fs/makedev.rs
vendored
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
|
||||
use crate::backend::c;
|
||||
use crate::fs::Dev;
|
||||
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
c::makedev(maj, min)
|
||||
}
|
||||
|
||||
#[cfg(solarish)]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
// SAFETY: Solarish's `makedev` is marked unsafe but it isn't doing
|
||||
// anything unsafe.
|
||||
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 {
|
||||
c::makedev(maj, min)
|
||||
}
|
||||
|
||||
#[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(c::makedev(maj, min))
|
||||
}
|
||||
|
||||
#[cfg(apple)]
|
||||
#[inline]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
// Apple's `makedev` oddly has signed argument types and is `unsafe`.
|
||||
unsafe { c::makedev(maj as i32, min as i32) }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
#[inline]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
// AIX's `makedev` oddly is `unsafe`.
|
||||
unsafe { c::makedev(maj, min) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
freebsdlike,
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "netbsd"
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn major(dev: Dev) -> u32 {
|
||||
unsafe { c::major(dev) }
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
apple,
|
||||
freebsdlike,
|
||||
target_os = "netbsd",
|
||||
all(target_os = "android", not(target_pointer_width = "32")),
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn major(dev: Dev) -> u32 {
|
||||
// On some platforms `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(
|
||||
apple,
|
||||
freebsdlike,
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "netbsd"
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn minor(dev: Dev) -> u32 {
|
||||
unsafe { c::minor(dev) }
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
apple,
|
||||
freebsdlike,
|
||||
target_os = "netbsd",
|
||||
all(target_os = "android", not(target_pointer_width = "32"))
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn minor(dev: Dev) -> u32 {
|
||||
// On some platforms, `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) }
|
||||
}
|
||||
23
third-party/vendor/rustix/src/backend/libc/fs/mod.rs
vendored
Normal file
23
third-party/vendor/rustix/src/backend/libc/fs/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#[cfg(all(feature = "alloc", not(any(target_os = "espidf", target_os = "redox"))))]
|
||||
pub(crate) mod dir;
|
||||
#[cfg(linux_kernel)]
|
||||
pub mod inotify;
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
pub(crate) mod makedev;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
|
||||
// TODO: Fix linux-raw-sys to define ioctl codes for sparc.
|
||||
#[cfg(all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")))]
|
||||
pub(crate) const EXT4_IOC_RESIZE_FS: crate::ioctl::RawOpcode = 0x8008_6610;
|
||||
|
||||
#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))]
|
||||
pub(crate) const EXT4_IOC_RESIZE_FS: crate::ioctl::RawOpcode =
|
||||
linux_raw_sys::ioctl::EXT4_IOC_RESIZE_FS as crate::ioctl::RawOpcode;
|
||||
2524
third-party/vendor/rustix/src/backend/libc/fs/syscalls.rs
vendored
Normal file
2524
third-party/vendor/rustix/src/backend/libc/fs/syscalls.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
1167
third-party/vendor/rustix/src/backend/libc/fs/types.rs
vendored
Normal file
1167
third-party/vendor/rustix/src/backend/libc/fs/types.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
1052
third-party/vendor/rustix/src/backend/libc/io/errno.rs
vendored
Normal file
1052
third-party/vendor/rustix/src/backend/libc/io/errno.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
6
third-party/vendor/rustix/src/backend/libc/io/mod.rs
vendored
Normal file
6
third-party/vendor/rustix/src/backend/libc/io/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
pub(crate) mod errno;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod types;
|
||||
|
||||
#[cfg_attr(windows, path = "windows_syscalls.rs")]
|
||||
pub(crate) mod syscalls;
|
||||
340
third-party/vendor/rustix/src/backend/libc/io/syscalls.rs
vendored
Normal file
340
third-party/vendor/rustix/src/backend/libc/io/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
//! libc syscalls supporting `rustix::io`.
|
||||
|
||||
use crate::backend::c;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::backend::conv::ret_discarded_fd;
|
||||
use crate::backend::conv::{borrowed_fd, ret, ret_c_int, ret_owned_fd, ret_usize};
|
||||
use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use crate::io::DupFlags;
|
||||
#[cfg(linux_kernel)]
|
||||
use crate::io::ReadWriteFlags;
|
||||
use crate::io::{self, FdFlags};
|
||||
use crate::ioctl::{IoctlOutput, RawOpcode};
|
||||
use core::cmp::min;
|
||||
#[cfg(all(feature = "fs", feature = "net"))]
|
||||
use libc_errno::errno;
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
use {
|
||||
crate::backend::MAX_IOV,
|
||||
crate::io::{IoSlice, IoSliceMut},
|
||||
};
|
||||
|
||||
pub(crate) unsafe fn read(fd: BorrowedFd<'_>, buf: *mut u8, len: usize) -> io::Result<usize> {
|
||||
ret_usize(c::read(borrowed_fd(fd), buf.cast(), min(len, READ_LIMIT)))
|
||||
}
|
||||
|
||||
pub(crate) fn write(fd: BorrowedFd<'_>, buf: &[u8]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ret_usize(c::write(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
min(buf.len(), READ_LIMIT),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn pread(
|
||||
fd: BorrowedFd<'_>,
|
||||
buf: *mut u8,
|
||||
len: usize,
|
||||
offset: u64,
|
||||
) -> io::Result<usize> {
|
||||
let len = min(len, READ_LIMIT);
|
||||
|
||||
// Silently cast; we'll get `EINVAL` if the value is negative.
|
||||
let offset = offset as i64;
|
||||
|
||||
// ESP-IDF and Vita don't support 64-bit offsets.
|
||||
#[cfg(any(target_os = "espidf", target_os = "vita"))]
|
||||
let offset: i32 = offset.try_into().map_err(|_| io::Errno::OVERFLOW)?;
|
||||
|
||||
ret_usize(c::pread(borrowed_fd(fd), buf.cast(), len, offset))
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// ESP-IDF and Vita don't support 64-bit offsets.
|
||||
#[cfg(any(target_os = "espidf", target_os = "vita"))]
|
||||
let offset: i32 = offset.try_into().map_err(|_| io::Errno::OVERFLOW)?;
|
||||
|
||||
unsafe { ret_usize(c::pwrite(borrowed_fd(fd), buf.as_ptr().cast(), len, offset)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ret_usize(c::readv(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), MAX_IOV) as c::c_int,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
pub(crate) fn writev(fd: BorrowedFd<'_>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ret_usize(c::writev(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), MAX_IOV) as c::c_int,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
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;
|
||||
unsafe {
|
||||
ret_usize(c::preadv(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), MAX_IOV) as c::c_int,
|
||||
offset,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
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;
|
||||
unsafe {
|
||||
ret_usize(c::pwritev(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), MAX_IOV) as c::c_int,
|
||||
offset,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
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;
|
||||
unsafe {
|
||||
ret_usize(c::preadv2(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), MAX_IOV) as c::c_int,
|
||||
offset,
|
||||
bitflags_bits!(flags),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
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;
|
||||
unsafe {
|
||||
ret_usize(c::pwritev2(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), MAX_IOV) as c::c_int,
|
||||
offset,
|
||||
bitflags_bits!(flags),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// These functions are derived from Rust's library/std/src/sys/unix/fd.rs at
|
||||
// revision 326ef470a8b379a180d6dc4bbef08990698a737a.
|
||||
|
||||
// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, with the
|
||||
// manual 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;
|
||||
|
||||
pub(crate) unsafe fn close(raw_fd: RawFd) {
|
||||
let _ = c::close(raw_fd as c::c_int);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn ioctl(
|
||||
fd: BorrowedFd<'_>,
|
||||
request: RawOpcode,
|
||||
arg: *mut c::c_void,
|
||||
) -> io::Result<IoctlOutput> {
|
||||
ret_c_int(c::ioctl(borrowed_fd(fd), request, arg))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn ioctl_readonly(
|
||||
fd: BorrowedFd<'_>,
|
||||
request: RawOpcode,
|
||||
arg: *mut c::c_void,
|
||||
) -> io::Result<IoctlOutput> {
|
||||
ioctl(fd, request, arg)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
#[cfg(all(feature = "fs", feature = "net"))]
|
||||
pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
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(all(feature = "fs", 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");
|
||||
}
|
||||
|
||||
pub(crate) fn fcntl_getfd(fd: BorrowedFd<'_>) -> io::Result<FdFlags> {
|
||||
let flags = unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFD))? };
|
||||
Ok(FdFlags::from_bits_retain(bitcast!(flags)))
|
||||
}
|
||||
|
||||
pub(crate) fn fcntl_setfd(fd: BorrowedFd<'_>, flags: FdFlags) -> io::Result<()> {
|
||||
unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETFD, flags.bits())) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", 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)) }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "espidf")]
|
||||
pub(crate) fn fcntl_dupfd(fd: BorrowedFd<'_>, min: RawFd) -> io::Result<OwnedFd> {
|
||||
unsafe { ret_owned_fd(c::fcntl(borrowed_fd(fd), c::F_DUPFD, min)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn dup(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
|
||||
unsafe { ret_owned_fd(c::dup(borrowed_fd(fd))) }
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_ref_mut)]
|
||||
#[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()))) }
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_ref_mut)]
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
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()),
|
||||
bitflags_bits!(flags),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
apple,
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
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)
|
||||
}
|
||||
65
third-party/vendor/rustix/src/backend/libc/io/types.rs
vendored
Normal file
65
third-party/vendor/rustix/src/backend/libc/io/types.rs
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
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: u32 {
|
||||
/// `FD_CLOEXEC`
|
||||
const CLOEXEC = bitcast!(c::FD_CLOEXEC);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
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: u32 {
|
||||
/// `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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
bitflags! {
|
||||
/// `O_*` constants for use with [`dup2`].
|
||||
///
|
||||
/// [`dup2`]: crate::io::dup2
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct DupFlags: u32 {
|
||||
/// `O_CLOEXEC`
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "redox",
|
||||
)))] // Android 5.0 has dup3, but libc doesn't have bindings
|
||||
const CLOEXEC = bitcast!(c::O_CLOEXEC);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
30
third-party/vendor/rustix/src/backend/libc/io/windows_syscalls.rs
vendored
Normal file
30
third-party/vendor/rustix/src/backend/libc/io/windows_syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
//! Windows system calls in the `io` module.
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::{borrowed_fd, ret_c_int};
|
||||
use crate::backend::fd::LibcFd;
|
||||
use crate::fd::{BorrowedFd, RawFd};
|
||||
use crate::io;
|
||||
use crate::ioctl::{IoctlOutput, RawOpcode};
|
||||
|
||||
pub(crate) unsafe fn close(raw_fd: RawFd) {
|
||||
let _ = c::close(raw_fd as LibcFd);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn ioctl(
|
||||
fd: BorrowedFd<'_>,
|
||||
request: RawOpcode,
|
||||
arg: *mut c::c_void,
|
||||
) -> io::Result<IoctlOutput> {
|
||||
ret_c_int(c::ioctl(borrowed_fd(fd), request, arg.cast()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn ioctl_readonly(
|
||||
fd: BorrowedFd<'_>,
|
||||
request: RawOpcode,
|
||||
arg: *mut c::c_void,
|
||||
) -> io::Result<IoctlOutput> {
|
||||
ioctl(fd, request, arg)
|
||||
}
|
||||
1
third-party/vendor/rustix/src/backend/libc/io_uring/mod.rs
vendored
Normal file
1
third-party/vendor/rustix/src/backend/libc/io_uring/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod syscalls;
|
||||
70
third-party/vendor/rustix/src/backend/libc/io_uring/syscalls.rs
vendored
Normal file
70
third-party/vendor/rustix/src/backend/libc/io_uring/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//! libc syscalls supporting `rustix::io_uring`.
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::{borrowed_fd, ret_owned_fd, ret_u32};
|
||||
use crate::fd::{BorrowedFd, OwnedFd};
|
||||
use crate::io;
|
||||
use crate::io_uring::{io_uring_params, IoringEnterFlags, IoringRegisterOp};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd> {
|
||||
syscall! {
|
||||
fn io_uring_setup(
|
||||
entries: u32,
|
||||
params: *mut io_uring_params
|
||||
) via SYS_io_uring_setup -> c::c_int
|
||||
}
|
||||
unsafe { ret_owned_fd(io_uring_setup(entries, params)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn io_uring_register(
|
||||
fd: BorrowedFd<'_>,
|
||||
opcode: IoringRegisterOp,
|
||||
arg: *const c::c_void,
|
||||
nr_args: u32,
|
||||
) -> io::Result<u32> {
|
||||
syscall! {
|
||||
fn io_uring_register(
|
||||
fd: c::c_uint,
|
||||
opcode: c::c_uint,
|
||||
arg: *const c::c_void,
|
||||
nr_args: c::c_uint
|
||||
) via SYS_io_uring_register -> c::c_int
|
||||
}
|
||||
ret_u32(io_uring_register(
|
||||
borrowed_fd(fd) as _,
|
||||
opcode as u32,
|
||||
arg,
|
||||
nr_args,
|
||||
))
|
||||
}
|
||||
|
||||
#[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! {
|
||||
fn io_uring_enter2(
|
||||
fd: c::c_uint,
|
||||
to_submit: c::c_uint,
|
||||
min_complete: c::c_uint,
|
||||
flags: c::c_uint,
|
||||
arg: *const c::c_void,
|
||||
size: usize
|
||||
) via SYS_io_uring_enter -> c::c_int
|
||||
}
|
||||
ret_u32(io_uring_enter2(
|
||||
borrowed_fd(fd) as _,
|
||||
to_submit,
|
||||
min_complete,
|
||||
bitflags_bits!(flags),
|
||||
arg,
|
||||
size,
|
||||
))
|
||||
}
|
||||
2
third-party/vendor/rustix/src/backend/libc/mm/mod.rs
vendored
Normal file
2
third-party/vendor/rustix/src/backend/libc/mm/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
244
third-party/vendor/rustix/src/backend/libc/mm/syscalls.rs
vendored
Normal file
244
third-party/vendor/rustix/src/backend/libc/mm/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
//! libc syscalls supporting `rustix::mm`.
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use super::types::Advice;
|
||||
#[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
|
||||
use super::types::MlockAllFlags;
|
||||
#[cfg(any(target_os = "emscripten", target_os = "linux"))]
|
||||
use super::types::MremapFlags;
|
||||
use super::types::{MapFlags, MprotectFlags, MsyncFlags, ProtFlags};
|
||||
#[cfg(linux_kernel)]
|
||||
use super::types::{MlockFlags, UserfaultfdFlags};
|
||||
use crate::backend::c;
|
||||
#[cfg(linux_kernel)]
|
||||
use crate::backend::conv::ret_owned_fd;
|
||||
use crate::backend::conv::{borrowed_fd, no_fd, ret};
|
||||
use crate::fd::BorrowedFd;
|
||||
#[cfg(linux_kernel)]
|
||||
use crate::fd::OwnedFd;
|
||||
use crate::io;
|
||||
|
||||
#[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, bitflags_bits!(flags));
|
||||
|
||||
// `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 = c::mmap(
|
||||
ptr,
|
||||
len,
|
||||
bitflags_bits!(prot),
|
||||
bitflags_bits!(flags),
|
||||
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 = c::mmap(
|
||||
ptr,
|
||||
len,
|
||||
bitflags_bits!(prot),
|
||||
bitflags_bits!(flags | MapFlags::from_bits_retain(bitcast!(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, bitflags_bits!(flags)))
|
||||
}
|
||||
|
||||
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(any(target_os = "emscripten", 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, bitflags_bits!(flags));
|
||||
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(any(target_os = "emscripten", 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,
|
||||
bitflags_bits!(flags | MremapFlags::from_bits_retain(bitcast!(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(linux_kernel)]
|
||||
#[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, bitflags_bits!(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(c::munlock(addr, length))
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> {
|
||||
syscall! {
|
||||
fn userfaultfd(
|
||||
flags: c::c_int
|
||||
) via SYS_userfaultfd -> c::c_int
|
||||
}
|
||||
ret_owned_fd(userfaultfd(bitflags_bits!(flags)))
|
||||
}
|
||||
|
||||
/// Locks all pages mapped into the address space of the calling process.
|
||||
///
|
||||
/// This includes the pages of the code, data, and stack segment, as well as
|
||||
/// shared libraries, user space kernel data, shared memory, and memory-mapped
|
||||
/// files. All mapped pages are guaranteed to be resident in RAM when the call
|
||||
/// returns successfully; the pages are guaranteed to stay in RAM until later
|
||||
/// unlocked.
|
||||
#[inline]
|
||||
#[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
|
||||
pub(crate) fn mlockall(flags: MlockAllFlags) -> io::Result<()> {
|
||||
unsafe { ret(c::mlockall(bitflags_bits!(flags))) }
|
||||
}
|
||||
|
||||
/// Unlocks all pages mapped into the address space of the calling process.
|
||||
#[inline]
|
||||
#[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
|
||||
pub(crate) fn munlockall() -> io::Result<()> {
|
||||
unsafe { ret(c::munlockall()) }
|
||||
}
|
||||
477
third-party/vendor/rustix/src/backend/libc/mm/types.rs
vendored
Normal file
477
third-party/vendor/rustix/src/backend/libc/mm/types.rs
vendored
Normal file
|
|
@ -0,0 +1,477 @@
|
|||
use crate::backend::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `PROT_*` flags for use with [`mmap`].
|
||||
///
|
||||
/// For `PROT_NONE`, use `ProtFlags::empty()`.
|
||||
///
|
||||
/// [`mmap`]: crate::mm::mmap
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct ProtFlags: u32 {
|
||||
/// `PROT_READ`
|
||||
const READ = bitcast!(c::PROT_READ);
|
||||
/// `PROT_WRITE`
|
||||
const WRITE = bitcast!(c::PROT_WRITE);
|
||||
/// `PROT_EXEC`
|
||||
const EXEC = bitcast!(c::PROT_EXEC);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `PROT_*` flags for use with [`mprotect`].
|
||||
///
|
||||
/// For `PROT_NONE`, use `MprotectFlags::empty()`.
|
||||
///
|
||||
/// [`mprotect`]: crate::mm::mprotect
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MprotectFlags: u32 {
|
||||
/// `PROT_READ`
|
||||
const READ = bitcast!(c::PROT_READ);
|
||||
/// `PROT_WRITE`
|
||||
const WRITE = bitcast!(c::PROT_WRITE);
|
||||
/// `PROT_EXEC`
|
||||
const EXEC = bitcast!(c::PROT_EXEC);
|
||||
/// `PROT_GROWSUP`
|
||||
#[cfg(linux_kernel)]
|
||||
const GROWSUP = bitcast!(c::PROT_GROWSUP);
|
||||
/// `PROT_GROWSDOWN`
|
||||
#[cfg(linux_kernel)]
|
||||
const GROWSDOWN = bitcast!(c::PROT_GROWSDOWN);
|
||||
/// `PROT_SEM`
|
||||
#[cfg(linux_kernel)]
|
||||
const SEM = linux_raw_sys::general::PROT_SEM;
|
||||
/// `PROT_BTI`
|
||||
#[cfg(all(linux_kernel, target_arch = "aarch64"))]
|
||||
const BTI = linux_raw_sys::general::PROT_BTI;
|
||||
/// `PROT_MTE`
|
||||
#[cfg(all(linux_kernel, target_arch = "aarch64"))]
|
||||
const MTE = linux_raw_sys::general::PROT_MTE;
|
||||
/// `PROT_SAO`
|
||||
#[cfg(all(linux_kernel, any(target_arch = "powerpc", target_arch = "powerpc64")))]
|
||||
const SAO = linux_raw_sys::general::PROT_SAO;
|
||||
/// `PROT_ADI`
|
||||
#[cfg(all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")))]
|
||||
const ADI = linux_raw_sys::general::PROT_ADI;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `MAP_*` flags for use with [`mmap`].
|
||||
///
|
||||
/// For `MAP_ANONYMOUS` (aka `MAP_ANON`), see [`mmap_anonymous`].
|
||||
///
|
||||
/// [`mmap`]: crate::mm::mmap
|
||||
/// [`mmap_anonymous`]: crates::mm::mmap_anonymous
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MapFlags: u32 {
|
||||
/// `MAP_SHARED`
|
||||
const SHARED = bitcast!(c::MAP_SHARED);
|
||||
/// `MAP_SHARED_VALIDATE`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const SHARED_VALIDATE = bitcast!(c::MAP_SHARED_VALIDATE);
|
||||
/// `MAP_PRIVATE`
|
||||
const PRIVATE = bitcast!(c::MAP_PRIVATE);
|
||||
/// `MAP_DENYWRITE`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const DENYWRITE = bitcast!(c::MAP_DENYWRITE);
|
||||
/// `MAP_FIXED`
|
||||
const FIXED = bitcast!(c::MAP_FIXED);
|
||||
/// `MAP_FIXED_NOREPLACE`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const FIXED_NOREPLACE = bitcast!(c::MAP_FIXED_NOREPLACE);
|
||||
/// `MAP_GROWSDOWN`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const GROWSDOWN = bitcast!(c::MAP_GROWSDOWN);
|
||||
/// `MAP_HUGETLB`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const HUGETLB = bitcast!(c::MAP_HUGETLB);
|
||||
/// `MAP_HUGE_2MB`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const HUGE_2MB = bitcast!(c::MAP_HUGE_2MB);
|
||||
/// `MAP_HUGE_1GB`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const HUGE_1GB = bitcast!(c::MAP_HUGE_1GB);
|
||||
/// `MAP_LOCKED`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const LOCKED = bitcast!(c::MAP_LOCKED);
|
||||
/// `MAP_NOCORE`
|
||||
#[cfg(freebsdlike)]
|
||||
const NOCORE = bitcast!(c::MAP_NOCORE);
|
||||
/// `MAP_NORESERVE`
|
||||
#[cfg(not(any(
|
||||
freebsdlike,
|
||||
target_os = "aix",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const NORESERVE = bitcast!(c::MAP_NORESERVE);
|
||||
/// `MAP_NOSYNC`
|
||||
#[cfg(freebsdlike)]
|
||||
const NOSYNC = bitcast!(c::MAP_NOSYNC);
|
||||
/// `MAP_POPULATE`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const POPULATE = bitcast!(c::MAP_POPULATE);
|
||||
/// `MAP_STACK`
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "netbsd",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
const STACK = bitcast!(c::MAP_STACK);
|
||||
/// `MAP_PREFAULT_READ`
|
||||
#[cfg(target_os = "freebsd")]
|
||||
const PREFAULT_READ = bitcast!(c::MAP_PREFAULT_READ);
|
||||
/// `MAP_SYNC`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
all(
|
||||
linux_kernel,
|
||||
any(target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6"),
|
||||
)
|
||||
)))]
|
||||
const SYNC = bitcast!(c::MAP_SYNC);
|
||||
/// `MAP_UNINITIALIZED`
|
||||
#[cfg(any())]
|
||||
const UNINITIALIZED = bitcast!(c::MAP_UNINITIALIZED);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "emscripten", target_os = "linux"))]
|
||||
bitflags! {
|
||||
/// `MREMAP_*` flags for use with [`mremap`].
|
||||
///
|
||||
/// For `MREMAP_FIXED`, see [`mremap_fixed`].
|
||||
///
|
||||
/// [`mremap`]: crate::mm::mremap
|
||||
/// [`mremap_fixed`]: crate::mm::mremap_fixed
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MremapFlags: u32 {
|
||||
/// `MREMAP_MAYMOVE`
|
||||
const MAYMOVE = bitcast!(c::MREMAP_MAYMOVE);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `MS_*` flags for use with [`msync`].
|
||||
///
|
||||
/// [`msync`]: crate::mm::msync
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MsyncFlags: u32 {
|
||||
/// `MS_SYNC`—Requests an update and waits for it to complete.
|
||||
const SYNC = bitcast!(c::MS_SYNC);
|
||||
/// `MS_ASYNC`—Specifies that an update be scheduled, but the call
|
||||
/// returns immediately.
|
||||
const ASYNC = bitcast!(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 = bitcast!(c::MS_INVALIDATE);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `MLOCK_*` flags for use with [`mlock_with`].
|
||||
///
|
||||
/// [`mlock_with`]: crate::mm::mlock_with
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MlockFlags: u32 {
|
||||
/// `MLOCK_ONFAULT`
|
||||
const ONFAULT = bitcast!(c::MLOCK_ONFAULT);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `POSIX_MADV_*` constants for use with [`madvise`].
|
||||
///
|
||||
/// [`madvise`]: crate::mm::madvise
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[repr(u32)]
|
||||
#[non_exhaustive]
|
||||
pub enum Advice {
|
||||
/// `POSIX_MADV_NORMAL`
|
||||
#[cfg(not(any(target_os = "android", target_os = "haiku")))]
|
||||
Normal = bitcast!(c::POSIX_MADV_NORMAL),
|
||||
|
||||
/// `POSIX_MADV_NORMAL`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
Normal = bitcast!(c::MADV_NORMAL),
|
||||
|
||||
/// `POSIX_MADV_SEQUENTIAL`
|
||||
#[cfg(not(any(target_os = "android", target_os = "haiku")))]
|
||||
Sequential = bitcast!(c::POSIX_MADV_SEQUENTIAL),
|
||||
|
||||
/// `POSIX_MADV_SEQUENTIAL`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
Sequential = bitcast!(c::MADV_SEQUENTIAL),
|
||||
|
||||
/// `POSIX_MADV_RANDOM`
|
||||
#[cfg(not(any(target_os = "android", target_os = "haiku")))]
|
||||
Random = bitcast!(c::POSIX_MADV_RANDOM),
|
||||
|
||||
/// `POSIX_MADV_RANDOM`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
Random = bitcast!(c::MADV_RANDOM),
|
||||
|
||||
/// `POSIX_MADV_WILLNEED`
|
||||
#[cfg(not(any(target_os = "android", target_os = "haiku")))]
|
||||
WillNeed = bitcast!(c::POSIX_MADV_WILLNEED),
|
||||
|
||||
/// `POSIX_MADV_WILLNEED`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
WillNeed = bitcast!(c::MADV_WILLNEED),
|
||||
|
||||
/// `POSIX_MADV_DONTNEED`
|
||||
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "haiku")))]
|
||||
DontNeed = bitcast!(c::POSIX_MADV_DONTNEED),
|
||||
|
||||
/// `POSIX_MADV_DONTNEED`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
DontNeed = bitcast!(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 = bitcast!(i32::MAX),
|
||||
|
||||
/// `MADV_DONTNEED`
|
||||
#[cfg(target_os = "android")]
|
||||
LinuxDontNeed = bitcast!(c::MADV_DONTNEED),
|
||||
/// `MADV_FREE`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxFree = bitcast!(c::MADV_FREE),
|
||||
/// `MADV_REMOVE`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxRemove = bitcast!(c::MADV_REMOVE),
|
||||
/// `MADV_DONTFORK`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxDontFork = bitcast!(c::MADV_DONTFORK),
|
||||
/// `MADV_DOFORK`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxDoFork = bitcast!(c::MADV_DOFORK),
|
||||
/// `MADV_HWPOISON`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxHwPoison = bitcast!(c::MADV_HWPOISON),
|
||||
/// `MADV_SOFT_OFFLINE`
|
||||
#[cfg(all(
|
||||
linux_kernel,
|
||||
not(any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6"
|
||||
))
|
||||
))]
|
||||
LinuxSoftOffline = bitcast!(c::MADV_SOFT_OFFLINE),
|
||||
/// `MADV_MERGEABLE`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxMergeable = bitcast!(c::MADV_MERGEABLE),
|
||||
/// `MADV_UNMERGEABLE`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxUnmergeable = bitcast!(c::MADV_UNMERGEABLE),
|
||||
/// `MADV_HUGEPAGE`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxHugepage = bitcast!(c::MADV_HUGEPAGE),
|
||||
/// `MADV_NOHUGEPAGE`
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxNoHugepage = bitcast!(c::MADV_NOHUGEPAGE),
|
||||
/// `MADV_DONTDUMP` (since Linux 3.4)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxDontDump = bitcast!(c::MADV_DONTDUMP),
|
||||
/// `MADV_DODUMP` (since Linux 3.4)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxDoDump = bitcast!(c::MADV_DODUMP),
|
||||
/// `MADV_WIPEONFORK` (since Linux 4.14)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxWipeOnFork = bitcast!(c::MADV_WIPEONFORK),
|
||||
/// `MADV_KEEPONFORK` (since Linux 4.14)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxKeepOnFork = bitcast!(c::MADV_KEEPONFORK),
|
||||
/// `MADV_COLD` (since Linux 5.4)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxCold = bitcast!(c::MADV_COLD),
|
||||
/// `MADV_PAGEOUT` (since Linux 5.4)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxPageOut = bitcast!(c::MADV_PAGEOUT),
|
||||
/// `MADV_POPULATE_READ` (since Linux 5.14)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxPopulateRead = bitcast!(c::MADV_POPULATE_READ),
|
||||
/// `MADV_POPULATE_WRITE` (since Linux 5.14)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxPopulateWrite = bitcast!(c::MADV_POPULATE_WRITE),
|
||||
/// `MADV_DONTNEED_LOCKED` (since Linux 5.18)
|
||||
#[cfg(linux_kernel)]
|
||||
LinuxDontneedLocked = bitcast!(c::MADV_DONTNEED_LOCKED),
|
||||
}
|
||||
|
||||
#[cfg(target_os = "emscripten")]
|
||||
#[allow(non_upper_case_globals)]
|
||||
impl Advice {
|
||||
/// `POSIX_MADV_DONTNEED`
|
||||
pub const DontNeed: Self = Self::Normal;
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `O_*` flags for use with [`userfaultfd`].
|
||||
///
|
||||
/// [`userfaultfd`]: crate::mm::userfaultfd
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct UserfaultfdFlags: u32 {
|
||||
/// `O_CLOEXEC`
|
||||
const CLOEXEC = bitcast!(c::O_CLOEXEC);
|
||||
/// `O_NONBLOCK`
|
||||
const NONBLOCK = bitcast!(c::O_NONBLOCK);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
|
||||
bitflags! {
|
||||
/// `MCL_*` flags for use with [`mlockall`].
|
||||
///
|
||||
/// [`mlockall`]: crate::mm::mlockall
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MlockAllFlags: u32 {
|
||||
/// Used together with `MCL_CURRENT`, `MCL_FUTURE`, or both. Mark all
|
||||
/// current (with `MCL_CURRENT`) or future (with `MCL_FUTURE`) mappings
|
||||
/// to lock pages when they are faulted in. When used with
|
||||
/// `MCL_CURRENT`, all present pages are locked, but `mlockall` will
|
||||
/// not fault in non-present pages. When used with `MCL_FUTURE`, all
|
||||
/// future mappings will be marked to lock pages when they are faulted
|
||||
/// in, but they will not be populated by the lock when the mapping is
|
||||
/// created. `MCL_ONFAULT` must be used with either `MCL_CURRENT` or
|
||||
/// `MCL_FUTURE` or both.
|
||||
#[cfg(linux_kernel)]
|
||||
const ONFAULT = bitcast!(libc::MCL_ONFAULT);
|
||||
/// Lock all pages which will become mapped into the address space of
|
||||
/// the process in the future. These could be, for instance, new pages
|
||||
/// required by a growing heap and stack as well as new memory-mapped
|
||||
/// files or shared memory regions.
|
||||
const FUTURE = bitcast!(libc::MCL_FUTURE);
|
||||
/// Lock all pages which are currently mapped into the address space of
|
||||
/// the process.
|
||||
const CURRENT = bitcast!(libc::MCL_CURRENT);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
215
third-party/vendor/rustix/src/backend/libc/mod.rs
vendored
Normal file
215
third-party/vendor/rustix/src/backend/libc/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
//! The libc backend.
|
||||
//!
|
||||
//! On most platforms, this uses the `libc` crate to make system calls. On
|
||||
//! Windows, this uses the Winsock 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)]
|
||||
|
||||
mod conv;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub(crate) mod fd {
|
||||
pub use crate::maybe_polyfill::os::windows::io::{
|
||||
AsRawSocket, AsSocket, BorrowedSocket as BorrowedFd, FromRawSocket, IntoRawSocket,
|
||||
OwnedSocket as OwnedFd, RawSocket as RawFd,
|
||||
};
|
||||
pub(crate) use windows_sys::Win32::Networking::WinSock::SOCKET as LibcFd;
|
||||
|
||||
/// A version of [`AsRawFd`] for use with Winsock API.
|
||||
///
|
||||
/// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsRawFd.html
|
||||
pub trait AsRawFd {
|
||||
/// A version of [`as_raw_fd`] for use with Winsock API.
|
||||
///
|
||||
/// [`as_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.as_raw_fd
|
||||
fn as_raw_fd(&self) -> RawFd;
|
||||
}
|
||||
impl<T: AsRawSocket> AsRawFd for T {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of [`IntoRawFd`] for use with Winsock API.
|
||||
///
|
||||
/// [`IntoRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.IntoRawFd.html
|
||||
pub trait IntoRawFd {
|
||||
/// A version of [`into_raw_fd`] for use with Winsock API.
|
||||
///
|
||||
/// [`into_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.into_raw_fd
|
||||
fn into_raw_fd(self) -> RawFd;
|
||||
}
|
||||
impl<T: IntoRawSocket> IntoRawFd for T {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of [`FromRawFd`] for use with Winsock API.
|
||||
///
|
||||
/// [`FromRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html
|
||||
pub trait FromRawFd {
|
||||
/// A version of [`from_raw_fd`] for use with Winsock API.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// See the [safety requirements] for [`from_raw_fd`].
|
||||
///
|
||||
/// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.from_raw_fd
|
||||
/// [safety requirements]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#safety
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self;
|
||||
}
|
||||
impl<T: 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 Winsock API.
|
||||
///
|
||||
/// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html
|
||||
pub trait AsFd {
|
||||
/// An `as_fd` function for Winsock, 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod fd {
|
||||
pub use crate::maybe_polyfill::os::fd::{
|
||||
AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd,
|
||||
};
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use RawFd as LibcFd;
|
||||
}
|
||||
|
||||
// On Windows we emulate selected libc-compatible interfaces. On non-Windows,
|
||||
// we just use libc here, since this is the libc backend.
|
||||
#[cfg_attr(windows, path = "winsock_c.rs")]
|
||||
pub(crate) mod c;
|
||||
|
||||
#[cfg(feature = "event")]
|
||||
pub(crate) mod event;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(crate) mod fs;
|
||||
pub(crate) mod io;
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "io_uring")]
|
||||
pub(crate) mod io_uring;
|
||||
#[cfg(not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")))]
|
||||
#[cfg(feature = "mm")]
|
||||
pub(crate) mod mm;
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) mod mount;
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(all(feature = "fs", not(feature = "mount")))]
|
||||
pub(crate) mod mount; // for deprecated mount functions in "fs"
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) mod net;
|
||||
#[cfg(not(any(windows, target_os = "espidf")))]
|
||||
#[cfg(any(
|
||||
feature = "param",
|
||||
feature = "runtime",
|
||||
feature = "time",
|
||||
target_arch = "x86",
|
||||
))]
|
||||
pub(crate) mod param;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "pipe")]
|
||||
pub(crate) mod pipe;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "process")]
|
||||
pub(crate) mod process;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[cfg(feature = "pty")]
|
||||
pub(crate) mod pty;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "rand")]
|
||||
pub(crate) mod rand;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[cfg(feature = "system")]
|
||||
pub(crate) mod system;
|
||||
#[cfg(not(any(windows, target_os = "vita")))]
|
||||
#[cfg(feature = "termios")]
|
||||
pub(crate) mod termios;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "thread")]
|
||||
pub(crate) mod thread;
|
||||
#[cfg(not(any(windows, target_os = "espidf")))]
|
||||
#[cfg(feature = "time")]
|
||||
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
|
||||
// backend/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()
|
||||
}
|
||||
|
||||
// Private modules used by multiple public modules.
|
||||
#[cfg(any(feature = "procfs", feature = "process", feature = "runtime"))]
|
||||
#[cfg(not(any(windows, target_os = "wasi")))]
|
||||
pub(crate) mod pid;
|
||||
#[cfg(any(feature = "process", feature = "thread"))]
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) mod prctl;
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[cfg(feature = "shm")]
|
||||
pub(crate) mod shm;
|
||||
#[cfg(any(feature = "fs", feature = "thread", feature = "process"))]
|
||||
#[cfg(not(any(windows, target_os = "wasi")))]
|
||||
pub(crate) mod ugid;
|
||||
|
||||
#[cfg(bsd)]
|
||||
const MAX_IOV: usize = c::IOV_MAX as usize;
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "emscripten", target_os = "nto"))]
|
||||
const MAX_IOV: usize = c::UIO_MAXIOV as usize;
|
||||
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
linux_kernel,
|
||||
windows,
|
||||
target_os = "emscripten",
|
||||
target_os = "espidf",
|
||||
target_os = "nto",
|
||||
target_os = "horizon",
|
||||
)))]
|
||||
const MAX_IOV: usize = 16; // The minimum value required by POSIX.
|
||||
2
third-party/vendor/rustix/src/backend/libc/mount/mod.rs
vendored
Normal file
2
third-party/vendor/rustix/src/backend/libc/mount/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
272
third-party/vendor/rustix/src/backend/libc/mount/syscalls.rs
vendored
Normal file
272
third-party/vendor/rustix/src/backend/libc/mount/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
use crate::backend::c;
|
||||
use crate::backend::conv::ret;
|
||||
#[cfg(feature = "mount")]
|
||||
use crate::backend::conv::{borrowed_fd, c_str, ret_owned_fd};
|
||||
#[cfg(feature = "mount")]
|
||||
use crate::fd::{BorrowedFd, OwnedFd};
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use core::ptr::null;
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) fn mount(
|
||||
source: Option<&CStr>,
|
||||
target: &CStr,
|
||||
file_system_type: Option<&CStr>,
|
||||
flags: super::types::MountFlagsArg,
|
||||
data: Option<&CStr>,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::mount(
|
||||
source.map_or_else(null, CStr::as_ptr),
|
||||
target.as_ptr(),
|
||||
file_system_type.map_or_else(null, CStr::as_ptr),
|
||||
flags.0,
|
||||
data.map_or_else(null, CStr::as_ptr).cast(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) fn unmount(target: &CStr, flags: super::types::UnmountFlags) -> io::Result<()> {
|
||||
unsafe { ret(c::umount2(target.as_ptr(), bitflags_bits!(flags))) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsopen(fs_name: &CStr, flags: super::types::FsOpenFlags) -> io::Result<OwnedFd> {
|
||||
syscall! {
|
||||
fn fsopen(
|
||||
fs_name: *const c::c_char,
|
||||
flags: c::c_uint
|
||||
) via SYS_fsopen -> c::c_int
|
||||
}
|
||||
unsafe { ret_owned_fd(fsopen(c_str(fs_name), flags.bits())) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsmount(
|
||||
fs_fd: BorrowedFd<'_>,
|
||||
flags: super::types::FsMountFlags,
|
||||
attr_flags: super::types::MountAttrFlags,
|
||||
) -> io::Result<OwnedFd> {
|
||||
syscall! {
|
||||
fn fsmount(
|
||||
fs_fd: c::c_int,
|
||||
flags: c::c_uint,
|
||||
attr_flags: c::c_uint
|
||||
) via SYS_fsmount -> c::c_int
|
||||
}
|
||||
unsafe { ret_owned_fd(fsmount(borrowed_fd(fs_fd), flags.bits(), attr_flags.bits())) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn move_mount(
|
||||
from_dfd: BorrowedFd<'_>,
|
||||
from_pathname: &CStr,
|
||||
to_dfd: BorrowedFd<'_>,
|
||||
to_pathname: &CStr,
|
||||
flags: super::types::MoveMountFlags,
|
||||
) -> io::Result<()> {
|
||||
syscall! {
|
||||
fn move_mount(
|
||||
from_dfd: c::c_int,
|
||||
from_pathname: *const c::c_char,
|
||||
to_dfd: c::c_int,
|
||||
to_pathname: *const c::c_char,
|
||||
flags: c::c_uint
|
||||
) via SYS_move_mount -> c::c_int
|
||||
}
|
||||
unsafe {
|
||||
ret(move_mount(
|
||||
borrowed_fd(from_dfd),
|
||||
c_str(from_pathname),
|
||||
borrowed_fd(to_dfd),
|
||||
c_str(to_pathname),
|
||||
flags.bits(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn open_tree(
|
||||
dfd: BorrowedFd<'_>,
|
||||
filename: &CStr,
|
||||
flags: super::types::OpenTreeFlags,
|
||||
) -> io::Result<OwnedFd> {
|
||||
syscall! {
|
||||
fn open_tree(
|
||||
dfd: c::c_int,
|
||||
filename: *const c::c_char,
|
||||
flags: c::c_uint
|
||||
) via SYS_open_tree -> c::c_int
|
||||
}
|
||||
|
||||
unsafe { ret_owned_fd(open_tree(borrowed_fd(dfd), c_str(filename), flags.bits())) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fspick(
|
||||
dfd: BorrowedFd<'_>,
|
||||
path: &CStr,
|
||||
flags: super::types::FsPickFlags,
|
||||
) -> io::Result<OwnedFd> {
|
||||
syscall! {
|
||||
fn fspick(
|
||||
dfd: c::c_int,
|
||||
path: *const c::c_char,
|
||||
flags: c::c_uint
|
||||
) via SYS_fspick -> c::c_int
|
||||
}
|
||||
|
||||
unsafe { ret_owned_fd(fspick(borrowed_fd(dfd), c_str(path), flags.bits())) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "mount")]
|
||||
#[cfg(linux_kernel)]
|
||||
syscall! {
|
||||
fn fsconfig(
|
||||
fs_fd: c::c_int,
|
||||
cmd: c::c_uint,
|
||||
key: *const c::c_char,
|
||||
val: *const c::c_char,
|
||||
aux: c::c_int
|
||||
) via SYS_fsconfig -> c::c_int
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsconfig_set_flag(fs_fd: BorrowedFd<'_>, key: &CStr) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(fsconfig(
|
||||
borrowed_fd(fs_fd),
|
||||
super::types::FsConfigCmd::SetFlag as _,
|
||||
c_str(key),
|
||||
null(),
|
||||
0,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsconfig_set_string(
|
||||
fs_fd: BorrowedFd<'_>,
|
||||
key: &CStr,
|
||||
value: &CStr,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(fsconfig(
|
||||
borrowed_fd(fs_fd),
|
||||
super::types::FsConfigCmd::SetString as _,
|
||||
c_str(key),
|
||||
c_str(value),
|
||||
0,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsconfig_set_binary(
|
||||
fs_fd: BorrowedFd<'_>,
|
||||
key: &CStr,
|
||||
value: &[u8],
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(fsconfig(
|
||||
borrowed_fd(fs_fd),
|
||||
super::types::FsConfigCmd::SetBinary as _,
|
||||
c_str(key),
|
||||
value.as_ptr().cast(),
|
||||
value.len().try_into().map_err(|_| io::Errno::OVERFLOW)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsconfig_set_fd(
|
||||
fs_fd: BorrowedFd<'_>,
|
||||
key: &CStr,
|
||||
fd: BorrowedFd<'_>,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(fsconfig(
|
||||
borrowed_fd(fs_fd),
|
||||
super::types::FsConfigCmd::SetFd as _,
|
||||
c_str(key),
|
||||
null(),
|
||||
borrowed_fd(fd),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsconfig_set_path(
|
||||
fs_fd: BorrowedFd<'_>,
|
||||
key: &CStr,
|
||||
path: &CStr,
|
||||
fd: BorrowedFd<'_>,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(fsconfig(
|
||||
borrowed_fd(fs_fd),
|
||||
super::types::FsConfigCmd::SetPath as _,
|
||||
c_str(key),
|
||||
c_str(path),
|
||||
borrowed_fd(fd),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsconfig_set_path_empty(
|
||||
fs_fd: BorrowedFd<'_>,
|
||||
key: &CStr,
|
||||
fd: BorrowedFd<'_>,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(fsconfig(
|
||||
borrowed_fd(fs_fd),
|
||||
super::types::FsConfigCmd::SetPathEmpty as _,
|
||||
c_str(key),
|
||||
c_str(cstr!("")),
|
||||
borrowed_fd(fd),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsconfig_create(fs_fd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(fsconfig(
|
||||
borrowed_fd(fs_fd),
|
||||
super::types::FsConfigCmd::Create as _,
|
||||
null(),
|
||||
null(),
|
||||
0,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(feature = "mount")]
|
||||
pub(crate) fn fsconfig_reconfigure(fs_fd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(fsconfig(
|
||||
borrowed_fd(fs_fd),
|
||||
super::types::FsConfigCmd::Reconfigure as _,
|
||||
null(),
|
||||
null(),
|
||||
0,
|
||||
))
|
||||
}
|
||||
}
|
||||
340
third-party/vendor/rustix/src/backend/libc/mount/types.rs
vendored
Normal file
340
third-party/vendor/rustix/src/backend/libc/mount/types.rs
vendored
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
use crate::backend::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `MS_*` constants for use with [`mount`].
|
||||
///
|
||||
/// [`mount`]: crate::mount::mount
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MountFlags: c::c_ulong {
|
||||
/// `MS_BIND`
|
||||
const BIND = c::MS_BIND;
|
||||
|
||||
/// `MS_DIRSYNC`
|
||||
const DIRSYNC = c::MS_DIRSYNC;
|
||||
|
||||
/// `MS_LAZYTIME`
|
||||
const LAZYTIME = c::MS_LAZYTIME;
|
||||
|
||||
/// `MS_MANDLOCK`
|
||||
#[doc(alias = "MANDLOCK")]
|
||||
const PERMIT_MANDATORY_FILE_LOCKING = c::MS_MANDLOCK;
|
||||
|
||||
/// `MS_NOATIME`
|
||||
const NOATIME = c::MS_NOATIME;
|
||||
|
||||
/// `MS_NODEV`
|
||||
const NODEV = c::MS_NODEV;
|
||||
|
||||
/// `MS_NODIRATIME`
|
||||
const NODIRATIME = c::MS_NODIRATIME;
|
||||
|
||||
/// `MS_NOEXEC`
|
||||
const NOEXEC = c::MS_NOEXEC;
|
||||
|
||||
/// `MS_NOSUID`
|
||||
const NOSUID = c::MS_NOSUID;
|
||||
|
||||
/// `MS_RDONLY`
|
||||
const RDONLY = c::MS_RDONLY;
|
||||
|
||||
/// `MS_REC`
|
||||
const REC = c::MS_REC;
|
||||
|
||||
/// `MS_RELATIME`
|
||||
const RELATIME = c::MS_RELATIME;
|
||||
|
||||
/// `MS_SILENT`
|
||||
const SILENT = c::MS_SILENT;
|
||||
|
||||
/// `MS_STRICTATIME`
|
||||
const STRICTATIME = c::MS_STRICTATIME;
|
||||
|
||||
/// `MS_SYNCHRONOUS`
|
||||
const SYNCHRONOUS = c::MS_SYNCHRONOUS;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `MNT_*` constants for use with [`unmount`].
|
||||
///
|
||||
/// [`unmount`]: crate::mount::unmount
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct UnmountFlags: u32 {
|
||||
/// `MNT_FORCE`
|
||||
const FORCE = bitcast!(c::MNT_FORCE);
|
||||
/// `MNT_DETACH`
|
||||
const DETACH = bitcast!(c::MNT_DETACH);
|
||||
/// `MNT_EXPIRE`
|
||||
const EXPIRE = bitcast!(c::MNT_EXPIRE);
|
||||
/// `UMOUNT_NOFOLLOW`
|
||||
const NOFOLLOW = bitcast!(c::UMOUNT_NOFOLLOW);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mount")]
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `FSOPEN_*` constants for use with [`fsopen`].
|
||||
///
|
||||
/// [`fsopen`]: crate::mount::fsopen
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct FsOpenFlags: c::c_uint {
|
||||
/// `FSOPEN_CLOEXEC`
|
||||
const FSOPEN_CLOEXEC = 0x0000_0001;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mount")]
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `FSMOUNT_*` constants for use with [`fsmount`].
|
||||
///
|
||||
/// [`fsmount`]: crate::mount::fsmount
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct FsMountFlags: c::c_uint {
|
||||
/// `FSMOUNT_CLOEXEC`
|
||||
const FSMOUNT_CLOEXEC = 0x0000_0001;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `FSCONFIG_*` constants for use with the `fsconfig` syscall.
|
||||
#[cfg(feature = "mount")]
|
||||
#[cfg(linux_kernel)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[repr(u32)]
|
||||
pub(crate) enum FsConfigCmd {
|
||||
/// `FSCONFIG_SET_FLAG`
|
||||
SetFlag = 0,
|
||||
|
||||
/// `FSCONFIG_SET_STRING`
|
||||
SetString = 1,
|
||||
|
||||
/// `FSCONFIG_SET_BINARY`
|
||||
SetBinary = 2,
|
||||
|
||||
/// `FSCONFIG_SET_PATH`
|
||||
SetPath = 3,
|
||||
|
||||
/// `FSCONFIG_SET_PATH_EMPTY`
|
||||
SetPathEmpty = 4,
|
||||
|
||||
/// `FSCONFIG_SET_FD`
|
||||
SetFd = 5,
|
||||
|
||||
/// `FSCONFIG_CMD_CREATE`
|
||||
Create = 6,
|
||||
|
||||
/// `FSCONFIG_CMD_RECONFIGURE`
|
||||
Reconfigure = 7,
|
||||
}
|
||||
|
||||
#[cfg(feature = "mount")]
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `MOUNT_ATTR_*` constants for use with [`fsmount`].
|
||||
///
|
||||
/// [`fsmount`]: crate::mount::fsmount
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MountAttrFlags: c::c_uint {
|
||||
/// `MOUNT_ATTR_RDONLY`
|
||||
const MOUNT_ATTR_RDONLY = 0x0000_0001;
|
||||
|
||||
/// `MOUNT_ATTR_NOSUID`
|
||||
const MOUNT_ATTR_NOSUID = 0x0000_0002;
|
||||
|
||||
/// `MOUNT_ATTR_NODEV`
|
||||
const MOUNT_ATTR_NODEV = 0x0000_0004;
|
||||
|
||||
/// `MOUNT_ATTR_NOEXEC`
|
||||
const MOUNT_ATTR_NOEXEC = 0x0000_0008;
|
||||
|
||||
/// `MOUNT_ATTR__ATIME`
|
||||
const MOUNT_ATTR__ATIME = 0x0000_0070;
|
||||
|
||||
/// `MOUNT_ATTR_RELATIME`
|
||||
const MOUNT_ATTR_RELATIME = 0x0000_0000;
|
||||
|
||||
/// `MOUNT_ATTR_NOATIME`
|
||||
const MOUNT_ATTR_NOATIME = 0x0000_0010;
|
||||
|
||||
/// `MOUNT_ATTR_STRICTATIME`
|
||||
const MOUNT_ATTR_STRICTATIME = 0x0000_0020;
|
||||
|
||||
/// `MOUNT_ATTR_NODIRATIME`
|
||||
const MOUNT_ATTR_NODIRATIME = 0x0000_0080;
|
||||
|
||||
/// `MOUNT_ATTR_NOUSER`
|
||||
const MOUNT_ATTR_IDMAP = 0x0010_0000;
|
||||
|
||||
/// `MOUNT_ATTR__ATIME_FLAGS`
|
||||
const MOUNT_ATTR_NOSYMFOLLOW = 0x0020_0000;
|
||||
|
||||
/// `MOUNT_ATTR__ATIME_FLAGS`
|
||||
const MOUNT_ATTR_SIZE_VER0 = 32;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mount")]
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `MOVE_MOUNT_*` constants for use with [`move_mount`].
|
||||
///
|
||||
/// [`move_mount`]: crate::mount::move_mount
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MoveMountFlags: c::c_uint {
|
||||
/// `MOVE_MOUNT_F_EMPTY_PATH`
|
||||
const MOVE_MOUNT_F_SYMLINKS = 0x0000_0001;
|
||||
|
||||
/// `MOVE_MOUNT_F_AUTOMOUNTS`
|
||||
const MOVE_MOUNT_F_AUTOMOUNTS = 0x0000_0002;
|
||||
|
||||
/// `MOVE_MOUNT_F_EMPTY_PATH`
|
||||
const MOVE_MOUNT_F_EMPTY_PATH = 0x0000_0004;
|
||||
|
||||
/// `MOVE_MOUNT_T_SYMLINKS`
|
||||
const MOVE_MOUNT_T_SYMLINKS = 0x0000_0010;
|
||||
|
||||
/// `MOVE_MOUNT_T_AUTOMOUNTS`
|
||||
const MOVE_MOUNT_T_AUTOMOUNTS = 0x0000_0020;
|
||||
|
||||
/// `MOVE_MOUNT_T_EMPTY_PATH`
|
||||
const MOVE_MOUNT_T_EMPTY_PATH = 0x0000_0040;
|
||||
|
||||
/// `MOVE_MOUNT__MASK`
|
||||
const MOVE_MOUNT_SET_GROUP = 0x0000_0100;
|
||||
|
||||
// TODO: add when Linux 6.5 is released
|
||||
// /// `MOVE_MOUNT_BENEATH`
|
||||
// const MOVE_MOUNT_BENEATH = 0x0000_0200;
|
||||
|
||||
/// `MOVE_MOUNT__MASK`
|
||||
const MOVE_MOUNT__MASK = 0x0000_0377;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mount")]
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `OPENTREE_*` constants for use with [`open_tree`].
|
||||
///
|
||||
/// [`open_tree`]: crate::mount::open_tree
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct OpenTreeFlags: c::c_uint {
|
||||
/// `OPENTREE_CLONE`
|
||||
const OPEN_TREE_CLONE = 1;
|
||||
|
||||
/// `OPENTREE_CLOEXEC`
|
||||
const OPEN_TREE_CLOEXEC = c::O_CLOEXEC as c::c_uint;
|
||||
|
||||
/// `AT_EMPTY_PATH`
|
||||
const AT_EMPTY_PATH = c::AT_EMPTY_PATH as c::c_uint;
|
||||
|
||||
/// `AT_NO_AUTOMOUNT`
|
||||
const AT_NO_AUTOMOUNT = c::AT_NO_AUTOMOUNT as c::c_uint;
|
||||
|
||||
/// `AT_RECURSIVE`
|
||||
const AT_RECURSIVE = c::AT_RECURSIVE as c::c_uint;
|
||||
|
||||
/// `AT_SYMLINK_NOFOLLOW`
|
||||
const AT_SYMLINK_NOFOLLOW = c::AT_SYMLINK_NOFOLLOW as c::c_uint;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mount")]
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `FSPICK_*` constants for use with [`fspick`].
|
||||
///
|
||||
/// [`fspick`]: crate::mount::fspick
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct FsPickFlags: c::c_uint {
|
||||
/// `FSPICK_CLOEXEC`
|
||||
const FSPICK_CLOEXEC = 0x0000_0001;
|
||||
|
||||
/// `FSPICK_SYMLINK_NOFOLLOW`
|
||||
const FSPICK_SYMLINK_NOFOLLOW = 0x0000_0002;
|
||||
|
||||
/// `FSPICK_NO_AUTOMOUNT`
|
||||
const FSPICK_NO_AUTOMOUNT = 0x0000_0004;
|
||||
|
||||
/// `FSPICK_EMPTY_PATH`
|
||||
const FSPICK_EMPTY_PATH = 0x0000_0008;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `MS_*` constants for use with [`mount_change`].
|
||||
///
|
||||
/// [`mount_change`]: crate::mount::mount_change
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct MountPropagationFlags: c::c_ulong {
|
||||
/// `MS_SILENT`
|
||||
const SILENT = c::MS_SILENT;
|
||||
/// `MS_SHARED`
|
||||
const SHARED = c::MS_SHARED;
|
||||
/// `MS_PRIVATE`
|
||||
const PRIVATE = c::MS_PRIVATE;
|
||||
/// `MS_SLAVE`
|
||||
const SLAVE = c::MS_SLAVE;
|
||||
/// `MS_UNBINDABLE`
|
||||
const UNBINDABLE = c::MS_UNBINDABLE;
|
||||
/// `MS_REC`
|
||||
const REC = c::MS_REC;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub(crate) struct InternalMountFlags: c::c_ulong {
|
||||
const REMOUNT = c::MS_REMOUNT;
|
||||
const MOVE = c::MS_MOVE;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) struct MountFlagsArg(pub(crate) c::c_ulong);
|
||||
245
third-party/vendor/rustix/src/backend/libc/net/addr.rs
vendored
Normal file
245
third-party/vendor/rustix/src/backend/libc/net/addr.rs
vendored
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
//! Socket address utilities.
|
||||
|
||||
use crate::backend::c;
|
||||
#[cfg(unix)]
|
||||
use {
|
||||
crate::ffi::CStr,
|
||||
crate::io,
|
||||
crate::path,
|
||||
core::cmp::Ordering,
|
||||
core::fmt,
|
||||
core::hash::{Hash, Hasher},
|
||||
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(bsd, target_os = "haiku")))]
|
||||
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(bsd, target_os = "haiku"))]
|
||||
{
|
||||
unix.sun_len = (offsetof_sun_path() + bytes.len()).try_into().unwrap();
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
unix,
|
||||
#[cfg(not(any(bsd, target_os = "haiku")))]
|
||||
len: (offsetof_sun_path() + bytes.len()).try_into().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Construct a new abstract Unix-domain address from a byte slice.
|
||||
#[cfg(linux_kernel)]
|
||||
#[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] = 0;
|
||||
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(bsd, target_os = "haiku")))]
|
||||
len,
|
||||
})
|
||||
}
|
||||
|
||||
fn init() -> c::sockaddr_un {
|
||||
c::sockaddr_un {
|
||||
#[cfg(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto"))]
|
||||
sun_len: 0,
|
||||
#[cfg(target_os = "vita")]
|
||||
ss_len: 0,
|
||||
sun_family: c::AF_UNIX as _,
|
||||
#[cfg(any(bsd, target_os = "nto"))]
|
||||
sun_path: [0; 104],
|
||||
#[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto")))]
|
||||
sun_path: [0; 108],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sun_path: [0; 126],
|
||||
#[cfg(target_os = "aix")]
|
||||
sun_path: [0; 1023],
|
||||
}
|
||||
}
|
||||
|
||||
/// 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] != 0 {
|
||||
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(linux_kernel)]
|
||||
#[inline]
|
||||
pub fn abstract_name(&self) -> Option<&[u8]> {
|
||||
let len = self.len();
|
||||
if len != 0 && self.unix.sun_path[0] == 0 {
|
||||
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(bsd, target_os = "haiku")))]
|
||||
{
|
||||
self.len
|
||||
}
|
||||
#[cfg(any(bsd, target_os = "haiku"))]
|
||||
{
|
||||
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<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl Ord for SocketAddrUnix {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> 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 Hash for SocketAddrUnix {
|
||||
#[inline]
|
||||
fn hash<H: 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(linux_kernel)]
|
||||
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(bsd, target_os = "aix", target_os = "haiku", target_os = "nto"))]
|
||||
sun_len: 0_u8,
|
||||
#[cfg(target_os = "vita")]
|
||||
ss_len: 0,
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
))]
|
||||
sun_family: 0_u8,
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
sun_family: 0_u16,
|
||||
#[cfg(any(bsd, target_os = "nto"))]
|
||||
sun_path: [0; 104],
|
||||
#[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto")))]
|
||||
sun_path: [0; 108],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sun_path: [0; 126],
|
||||
#[cfg(target_os = "aix")]
|
||||
sun_path: [0; 1023],
|
||||
};
|
||||
(crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
|
||||
}
|
||||
135
third-party/vendor/rustix/src/backend/libc/net/ext.rs
vendored
Normal file
135
third-party/vendor/rustix/src/backend/libc/net/ext.rs
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
use crate::backend::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(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) }
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr {
|
||||
c::in_addr { s_addr }
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) const 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(windows)]
|
||||
#[inline]
|
||||
pub(crate) const 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(windows)]
|
||||
#[inline]
|
||||
pub(crate) const 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(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
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) const fn sockaddr_in6_new(
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
))]
|
||||
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(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
))]
|
||||
sin6_len,
|
||||
sin6_family,
|
||||
sin6_port,
|
||||
sin6_flowinfo,
|
||||
sin6_addr,
|
||||
sin6_scope_id,
|
||||
#[cfg(solarish)]
|
||||
__sin6_src_id: 0,
|
||||
#[cfg(target_os = "vita")]
|
||||
sin6_vport: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[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) }
|
||||
}
|
||||
18
third-party/vendor/rustix/src/backend/libc/net/mod.rs
vendored
Normal file
18
third-party/vendor/rustix/src/backend/libc/net/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
pub(crate) mod addr;
|
||||
pub(crate) mod ext;
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
pub(crate) mod msghdr;
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) mod netdevice;
|
||||
pub(crate) mod read_sockaddr;
|
||||
pub(crate) mod send_recv;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) mod sockopt;
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod write_sockaddr;
|
||||
160
third-party/vendor/rustix/src/backend/libc/net/msghdr.rs
vendored
Normal file
160
third-party/vendor/rustix/src/backend/libc/net/msghdr.rs
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
//! Utilities for dealing with message headers.
|
||||
//!
|
||||
//! These take closures rather than returning a `c::msghdr` directly because
|
||||
//! the message headers may reference stack-local data.
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::{msg_control_len, msg_iov_len};
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::backend::net::write_sockaddr::encode_sockaddr_xdp;
|
||||
use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
|
||||
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::net::xdp::SocketAddrXdp;
|
||||
use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6};
|
||||
use crate::utils::as_ptr;
|
||||
|
||||
use core::mem::{size_of, zeroed, MaybeUninit};
|
||||
|
||||
/// Create a message header intended to receive a datagram.
|
||||
pub(crate) fn with_recv_msghdr<R>(
|
||||
name: &mut MaybeUninit<c::sockaddr_storage>,
|
||||
iov: &mut [IoSliceMut<'_>],
|
||||
control: &mut RecvAncillaryBuffer<'_>,
|
||||
f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
|
||||
) -> io::Result<R> {
|
||||
control.clear();
|
||||
|
||||
let namelen = size_of::<c::sockaddr_storage>() as c::socklen_t;
|
||||
let mut msghdr = {
|
||||
let mut h = zero_msghdr();
|
||||
h.msg_name = name.as_mut_ptr().cast();
|
||||
h.msg_namelen = namelen;
|
||||
h.msg_iov = iov.as_mut_ptr().cast();
|
||||
h.msg_iovlen = msg_iov_len(iov.len());
|
||||
h.msg_control = control.as_control_ptr().cast();
|
||||
h.msg_controllen = msg_control_len(control.control_len());
|
||||
h
|
||||
};
|
||||
|
||||
let res = f(&mut msghdr);
|
||||
|
||||
// Reset the control length.
|
||||
if res.is_ok() {
|
||||
unsafe {
|
||||
control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX));
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Create a message header intended to send without an address.
|
||||
pub(crate) fn with_noaddr_msghdr<R>(
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
f: impl FnOnce(c::msghdr) -> R,
|
||||
) -> R {
|
||||
f({
|
||||
let mut h = zero_msghdr();
|
||||
h.msg_iov = iov.as_ptr() as _;
|
||||
h.msg_iovlen = msg_iov_len(iov.len());
|
||||
h.msg_control = control.as_control_ptr().cast();
|
||||
h.msg_controllen = msg_control_len(control.control_len());
|
||||
h
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a message header intended to send with an IPv4 address.
|
||||
pub(crate) fn with_v4_msghdr<R>(
|
||||
addr: &SocketAddrV4,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
f: impl FnOnce(c::msghdr) -> R,
|
||||
) -> R {
|
||||
let encoded = encode_sockaddr_v4(addr);
|
||||
|
||||
f({
|
||||
let mut h = zero_msghdr();
|
||||
h.msg_name = as_ptr(&encoded) as _;
|
||||
h.msg_namelen = size_of::<SocketAddrV4>() as _;
|
||||
h.msg_iov = iov.as_ptr() as _;
|
||||
h.msg_iovlen = msg_iov_len(iov.len());
|
||||
h.msg_control = control.as_control_ptr().cast();
|
||||
h.msg_controllen = msg_control_len(control.control_len());
|
||||
h
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a message header intended to send with an IPv6 address.
|
||||
pub(crate) fn with_v6_msghdr<R>(
|
||||
addr: &SocketAddrV6,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
f: impl FnOnce(c::msghdr) -> R,
|
||||
) -> R {
|
||||
let encoded = encode_sockaddr_v6(addr);
|
||||
|
||||
f({
|
||||
let mut h = zero_msghdr();
|
||||
h.msg_name = as_ptr(&encoded) as _;
|
||||
h.msg_namelen = size_of::<SocketAddrV6>() as _;
|
||||
h.msg_iov = iov.as_ptr() as _;
|
||||
h.msg_iovlen = msg_iov_len(iov.len());
|
||||
h.msg_control = control.as_control_ptr().cast();
|
||||
h.msg_controllen = msg_control_len(control.control_len());
|
||||
h
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a message header intended to send with a Unix address.
|
||||
#[cfg(all(unix, not(target_os = "redox")))]
|
||||
pub(crate) fn with_unix_msghdr<R>(
|
||||
addr: &crate::net::SocketAddrUnix,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
f: impl FnOnce(c::msghdr) -> R,
|
||||
) -> R {
|
||||
f({
|
||||
let mut h = zero_msghdr();
|
||||
h.msg_name = as_ptr(&addr.unix) as _;
|
||||
h.msg_namelen = addr.addr_len();
|
||||
h.msg_iov = iov.as_ptr() as _;
|
||||
h.msg_iovlen = msg_iov_len(iov.len());
|
||||
h.msg_control = control.as_control_ptr().cast();
|
||||
h.msg_controllen = msg_control_len(control.control_len());
|
||||
h
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a message header intended to send with an IPv6 address.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn with_xdp_msghdr<R>(
|
||||
addr: &SocketAddrXdp,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
f: impl FnOnce(c::msghdr) -> R,
|
||||
) -> R {
|
||||
let encoded = encode_sockaddr_xdp(addr);
|
||||
|
||||
f({
|
||||
let mut h = zero_msghdr();
|
||||
h.msg_name = as_ptr(&encoded) as _;
|
||||
h.msg_namelen = size_of::<SocketAddrXdp>() as _;
|
||||
h.msg_iov = iov.as_ptr() as _;
|
||||
h.msg_iovlen = msg_iov_len(iov.len());
|
||||
h.msg_control = control.as_control_ptr().cast();
|
||||
h.msg_controllen = msg_control_len(control.control_len());
|
||||
h
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a zero-initialized message header struct value.
|
||||
#[cfg(all(unix, not(target_os = "redox")))]
|
||||
pub(crate) fn zero_msghdr() -> c::msghdr {
|
||||
// SAFETY: We can't initialize all the fields by value because on some
|
||||
// platforms the `msghdr` struct in the libc crate contains private padding
|
||||
// fields. But it is still a C type that's meant to be zero-initializable.
|
||||
unsafe { zeroed() }
|
||||
}
|
||||
52
third-party/vendor/rustix/src/backend/libc/net/netdevice.rs
vendored
Normal file
52
third-party/vendor/rustix/src/backend/libc/net/netdevice.rs
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#![allow(unsafe_code)]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::alloc::string::String;
|
||||
use crate::backend::io::syscalls::ioctl;
|
||||
use crate::fd::AsFd;
|
||||
use crate::io;
|
||||
#[cfg(feature = "alloc")]
|
||||
use libc::SIOCGIFNAME;
|
||||
use libc::{__c_anonymous_ifr_ifru, c_char, ifreq, IFNAMSIZ, SIOCGIFINDEX};
|
||||
|
||||
pub(crate) fn name_to_index(fd: impl AsFd, if_name: &str) -> io::Result<u32> {
|
||||
let if_name_bytes = if_name.as_bytes();
|
||||
if if_name_bytes.len() >= IFNAMSIZ as usize {
|
||||
return Err(io::Errno::NODEV);
|
||||
}
|
||||
|
||||
let mut ifreq = ifreq {
|
||||
ifr_name: [0; 16],
|
||||
ifr_ifru: __c_anonymous_ifr_ifru { ifru_ifindex: 0 },
|
||||
};
|
||||
|
||||
let mut if_name_c_char_iter = if_name_bytes.iter().map(|byte| *byte as c_char);
|
||||
ifreq.ifr_name[..if_name_bytes.len()].fill_with(|| if_name_c_char_iter.next().unwrap());
|
||||
|
||||
unsafe { ioctl(fd.as_fd(), SIOCGIFINDEX as _, &mut ifreq as *mut ifreq as _) }?;
|
||||
let index = unsafe { ifreq.ifr_ifru.ifru_ifindex };
|
||||
Ok(index as u32)
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
pub(crate) fn index_to_name(fd: impl AsFd, index: u32) -> io::Result<String> {
|
||||
let mut ifreq = ifreq {
|
||||
ifr_name: [0; 16],
|
||||
ifr_ifru: __c_anonymous_ifr_ifru {
|
||||
ifru_ifindex: index as _,
|
||||
},
|
||||
};
|
||||
|
||||
unsafe { ioctl(fd.as_fd(), SIOCGIFNAME as _, &mut ifreq as *mut ifreq as _) }?;
|
||||
|
||||
if let Some(nul_byte) = ifreq.ifr_name.iter().position(|char| *char == 0) {
|
||||
let name: String = ifreq.ifr_name[..nul_byte]
|
||||
.iter()
|
||||
.map(|v| *v as u8 as char)
|
||||
.collect();
|
||||
|
||||
Ok(name)
|
||||
} else {
|
||||
Err(io::Errno::INVAL)
|
||||
}
|
||||
}
|
||||
332
third-party/vendor/rustix/src/backend/libc/net/read_sockaddr.rs
vendored
Normal file
332
third-party/vendor/rustix/src/backend/libc/net/read_sockaddr.rs
vendored
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
//! 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.
|
||||
|
||||
#[cfg(unix)]
|
||||
use super::addr::SocketAddrUnix;
|
||||
use super::ext::{in6_addr_s6_addr, in_addr_s_addr, sockaddr_in6_sin6_scope_id};
|
||||
use crate::backend::c;
|
||||
#[cfg(not(windows))]
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp};
|
||||
use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
|
||||
use core::mem::size_of;
|
||||
|
||||
// This must match the header of `sockaddr`.
|
||||
#[repr(C)]
|
||||
struct sockaddr_header {
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
))]
|
||||
sa_len: u8,
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
))]
|
||||
ss_family: u8,
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
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_storage) -> u16 {
|
||||
// Assert that we know the layout of `sockaddr`.
|
||||
let _ = c::sockaddr {
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
))]
|
||||
sa_len: 0_u8,
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
))]
|
||||
sa_family: 0_u8,
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
sa_family: 0_u16,
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
sa_data: [0; 14],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sa_data: [0; 30],
|
||||
};
|
||||
|
||||
(*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 _;
|
||||
}
|
||||
|
||||
/// 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_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 {
|
||||
SocketAddrUnix::new(&[][..]).map(SocketAddrAny::Unix)
|
||||
} else {
|
||||
let decode = &*storage.cast::<c::sockaddr_un>();
|
||||
|
||||
// On Linux check for Linux's [abstract namespace].
|
||||
//
|
||||
// [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html
|
||||
#[cfg(linux_kernel)]
|
||||
if decode.sun_path[0] == 0 {
|
||||
return SocketAddrUnix::new_abstract_name(core::mem::transmute::<
|
||||
&[c::c_char],
|
||||
&[u8],
|
||||
>(
|
||||
&decode.sun_path[1..len - offsetof_sun_path],
|
||||
))
|
||||
.map(SocketAddrAny::Unix);
|
||||
}
|
||||
|
||||
// Otherwise we expect a NUL-terminated filesystem path.
|
||||
|
||||
// Trim off unused bytes from the end of `path_bytes`.
|
||||
let path_bytes = if cfg!(any(solarish, target_os = "freebsd")) {
|
||||
// FreeBSD and illumos sometimes set 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)
|
||||
.ok_or(io::Errno::INVAL)?]
|
||||
} else {
|
||||
// Otherwise, use the provided length.
|
||||
let provided_len = len - 1 - offsetof_sun_path;
|
||||
if decode.sun_path[provided_len] != 0 {
|
||||
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]
|
||||
};
|
||||
|
||||
SocketAddrUnix::new(core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes))
|
||||
.map(SocketAddrAny::Unix)
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
c::AF_XDP => {
|
||||
if len < size_of::<c::sockaddr_xdp>() {
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
let decode = &*storage.cast::<c::sockaddr_xdp>();
|
||||
Ok(SocketAddrAny::Xdp(SocketAddrXdp::new(
|
||||
SockaddrXdpFlags::from_bits_retain(decode.sxdp_flags),
|
||||
u32::from_be(decode.sxdp_ifindex),
|
||||
u32::from_be(decode.sxdp_queue_id),
|
||||
u32::from_be(decode.sxdp_shared_umem_fd),
|
||||
)))
|
||||
}
|
||||
_ => Err(io::Errno::INVAL),
|
||||
}
|
||||
}
|
||||
|
||||
/// Read an optional 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_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))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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_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>();
|
||||
|
||||
// On Linux check for Linux's [abstract namespace].
|
||||
//
|
||||
// [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html
|
||||
#[cfg(linux_kernel)]
|
||||
if decode.sun_path[0] == 0 {
|
||||
return SocketAddrAny::Unix(
|
||||
SocketAddrUnix::new_abstract_name(core::mem::transmute::<
|
||||
&[c::c_char],
|
||||
&[u8],
|
||||
>(
|
||||
&decode.sun_path[1..len - offsetof_sun_path],
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
// Otherwise we expect a NUL-terminated filesystem path.
|
||||
assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0);
|
||||
let path_bytes = &decode.sun_path[..len - 1 - offsetof_sun_path];
|
||||
|
||||
// FreeBSD and illumos sometimes set the length to longer than
|
||||
// the length of the NUL-terminated string. Find the NUL and
|
||||
// truncate the string accordingly.
|
||||
#[cfg(any(solarish, target_os = "freebsd"))]
|
||||
let path_bytes = &path_bytes[..path_bytes.iter().position(|b| *b == 0).unwrap()];
|
||||
|
||||
SocketAddrAny::Unix(
|
||||
SocketAddrUnix::new(core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes))
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
c::AF_XDP => {
|
||||
assert!(len >= size_of::<c::sockaddr_xdp>());
|
||||
let decode = &*storage.cast::<c::sockaddr_xdp>();
|
||||
SocketAddrAny::Xdp(SocketAddrXdp::new(
|
||||
SockaddrXdpFlags::from_bits_retain(decode.sxdp_flags),
|
||||
u32::from_be(decode.sxdp_ifindex),
|
||||
u32::from_be(decode.sxdp_queue_id),
|
||||
u32::from_be(decode.sxdp_shared_umem_fd),
|
||||
))
|
||||
}
|
||||
other => unimplemented!("{:?}", other),
|
||||
}
|
||||
}
|
||||
103
third-party/vendor/rustix/src/backend/libc/net/send_recv.rs
vendored
Normal file
103
third-party/vendor/rustix/src/backend/libc/net/send_recv.rs
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
use crate::backend::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `MSG_*` flags for use with [`send`], [`send_to`], and related
|
||||
/// functions.
|
||||
///
|
||||
/// [`send`]: crate::net::send
|
||||
/// [`sendto`]: crate::net::sendto
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct SendFlags: u32 {
|
||||
/// `MSG_CONFIRM`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "nto",
|
||||
target_os = "haiku",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
const CONFIRM = bitcast!(c::MSG_CONFIRM);
|
||||
/// `MSG_DONTROUTE`
|
||||
const DONTROUTE = bitcast!(c::MSG_DONTROUTE);
|
||||
/// `MSG_DONTWAIT`
|
||||
#[cfg(not(windows))]
|
||||
const DONTWAIT = bitcast!(c::MSG_DONTWAIT);
|
||||
/// `MSG_EOR`
|
||||
#[cfg(not(windows))]
|
||||
const EOT = bitcast!(c::MSG_EOR);
|
||||
/// `MSG_MORE`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
const MORE = bitcast!(c::MSG_MORE);
|
||||
#[cfg(not(any(apple, windows, target_os = "vita")))]
|
||||
/// `MSG_NOSIGNAL`
|
||||
const NOSIGNAL = bitcast!(c::MSG_NOSIGNAL);
|
||||
/// `MSG_OOB`
|
||||
const OOB = bitcast!(c::MSG_OOB);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `MSG_*` flags for use with [`recv`], [`recvfrom`], and related
|
||||
/// functions.
|
||||
///
|
||||
/// [`recv`]: crate::net::recv
|
||||
/// [`recvfrom`]: crate::net::recvfrom
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct RecvFlags: u32 {
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
solarish,
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
/// `MSG_CMSG_CLOEXEC`
|
||||
const CMSG_CLOEXEC = bitcast!(c::MSG_CMSG_CLOEXEC);
|
||||
/// `MSG_DONTWAIT`
|
||||
#[cfg(not(windows))]
|
||||
const DONTWAIT = bitcast!(c::MSG_DONTWAIT);
|
||||
/// `MSG_ERRQUEUE`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
const ERRQUEUE = bitcast!(c::MSG_ERRQUEUE);
|
||||
/// `MSG_OOB`
|
||||
const OOB = bitcast!(c::MSG_OOB);
|
||||
/// `MSG_PEEK`
|
||||
const PEEK = bitcast!(c::MSG_PEEK);
|
||||
/// `MSG_TRUNC`
|
||||
const TRUNC = bitcast!(c::MSG_TRUNC);
|
||||
/// `MSG_WAITALL`
|
||||
const WAITALL = bitcast!(c::MSG_WAITALL);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
1233
third-party/vendor/rustix/src/backend/libc/net/sockopt.rs
vendored
Normal file
1233
third-party/vendor/rustix/src/backend/libc/net/sockopt.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
621
third-party/vendor/rustix/src/backend/libc/net/syscalls.rs
vendored
Normal file
621
third-party/vendor/rustix/src/backend/libc/net/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,621 @@
|
|||
//! libc syscalls supporting `rustix::net`.
|
||||
|
||||
#[cfg(unix)]
|
||||
use super::addr::SocketAddrUnix;
|
||||
#[cfg(target_os = "linux")]
|
||||
use super::msghdr::with_xdp_msghdr;
|
||||
#[cfg(target_os = "linux")]
|
||||
use super::write_sockaddr::encode_sockaddr_xdp;
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::{borrowed_fd, ret, ret_owned_fd, ret_send_recv, send_recv_len};
|
||||
use crate::fd::{BorrowedFd, OwnedFd};
|
||||
use crate::io;
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::net::xdp::SocketAddrXdp;
|
||||
use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6};
|
||||
use crate::utils::as_ptr;
|
||||
use core::mem::{size_of, MaybeUninit};
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use {
|
||||
super::msghdr::{with_noaddr_msghdr, with_recv_msghdr, with_v4_msghdr, with_v6_msghdr},
|
||||
crate::io::{IoSlice, IoSliceMut},
|
||||
crate::net::{RecvAncillaryBuffer, RecvMsgReturn, SendAncillaryBuffer},
|
||||
};
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
use {
|
||||
super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os},
|
||||
super::send_recv::{RecvFlags, SendFlags},
|
||||
super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6},
|
||||
crate::net::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType},
|
||||
core::ptr::null_mut,
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) unsafe fn recv(
|
||||
fd: BorrowedFd<'_>,
|
||||
buf: *mut u8,
|
||||
len: usize,
|
||||
flags: RecvFlags,
|
||||
) -> io::Result<usize> {
|
||||
ret_send_recv(c::recv(
|
||||
borrowed_fd(fd),
|
||||
buf.cast(),
|
||||
send_recv_len(len),
|
||||
bitflags_bits!(flags),
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ret_send_recv(c::send(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
bitflags_bits!(flags),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) unsafe fn recvfrom(
|
||||
fd: BorrowedFd<'_>,
|
||||
buf: *mut u8,
|
||||
buf_len: usize,
|
||||
flags: RecvFlags,
|
||||
) -> io::Result<(usize, Option<SocketAddrAny>)> {
|
||||
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());
|
||||
|
||||
ret_send_recv(c::recvfrom(
|
||||
borrowed_fd(fd),
|
||||
buf.cast(),
|
||||
send_recv_len(buf_len),
|
||||
bitflags_bits!(flags),
|
||||
storage.as_mut_ptr().cast(),
|
||||
&mut len,
|
||||
))
|
||||
.map(|nread| {
|
||||
(
|
||||
nread,
|
||||
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> {
|
||||
unsafe {
|
||||
ret_send_recv(c::sendto(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
bitflags_bits!(flags),
|
||||
as_ptr(&encode_sockaddr_v4(addr)).cast::<c::sockaddr>(),
|
||||
size_of::<c::sockaddr_in>() as c::socklen_t,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[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> {
|
||||
unsafe {
|
||||
ret_send_recv(c::sendto(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
bitflags_bits!(flags),
|
||||
as_ptr(&encode_sockaddr_v6(addr)).cast::<c::sockaddr>(),
|
||||
size_of::<c::sockaddr_in6>() as c::socklen_t,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[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> {
|
||||
unsafe {
|
||||
ret_send_recv(c::sendto(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
bitflags_bits!(flags),
|
||||
as_ptr(&addr.unix).cast(),
|
||||
addr.addr_len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn sendto_xdp(
|
||||
fd: BorrowedFd<'_>,
|
||||
buf: &[u8],
|
||||
flags: SendFlags,
|
||||
addr: &SocketAddrXdp,
|
||||
) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ret_send_recv(c::sendto(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
bitflags_bits!(flags),
|
||||
as_ptr(&encode_sockaddr_xdp(addr)).cast::<c::sockaddr>(),
|
||||
size_of::<c::sockaddr_xdp>() as _,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn socket(
|
||||
domain: AddressFamily,
|
||||
type_: SocketType,
|
||||
protocol: Option<Protocol>,
|
||||
) -> io::Result<OwnedFd> {
|
||||
let raw_protocol = match protocol {
|
||||
Some(p) => p.0.get(),
|
||||
None => 0,
|
||||
};
|
||||
unsafe {
|
||||
ret_owned_fd(c::socket(
|
||||
domain.0 as c::c_int,
|
||||
type_.0 as c::c_int,
|
||||
raw_protocol as c::c_int,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn socket_with(
|
||||
domain: AddressFamily,
|
||||
type_: SocketType,
|
||||
flags: SocketFlags,
|
||||
protocol: Option<Protocol>,
|
||||
) -> io::Result<OwnedFd> {
|
||||
let raw_protocol = match protocol {
|
||||
Some(p) => p.0.get(),
|
||||
None => 0,
|
||||
};
|
||||
unsafe {
|
||||
ret_owned_fd(c::socket(
|
||||
domain.0 as c::c_int,
|
||||
(type_.0 | flags.bits()) as c::c_int,
|
||||
raw_protocol as c::c_int,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[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(target_os = "linux")]
|
||||
pub(crate) fn bind_xdp(sockfd: BorrowedFd<'_>, addr: &SocketAddrXdp) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::bind(
|
||||
borrowed_fd(sockfd),
|
||||
as_ptr(&encode_sockaddr_xdp(addr)).cast(),
|
||||
size_of::<c::sockaddr_xdp>() as c::socklen_t,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[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 connect_unspec(sockfd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
debug_assert_eq!(c::AF_UNSPEC, 0);
|
||||
let addr = MaybeUninit::<c::sockaddr_storage>::zeroed();
|
||||
unsafe {
|
||||
ret(c::connect(
|
||||
borrowed_fd(sockfd),
|
||||
as_ptr(&addr).cast(),
|
||||
size_of::<c::sockaddr_storage>() as c::socklen_t,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[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 = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
pub(crate) fn recvmsg(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
iov: &mut [IoSliceMut<'_>],
|
||||
control: &mut RecvAncillaryBuffer<'_>,
|
||||
msg_flags: RecvFlags,
|
||||
) -> io::Result<RecvMsgReturn> {
|
||||
let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
|
||||
|
||||
with_recv_msghdr(&mut storage, iov, control, |msghdr| {
|
||||
let result = unsafe {
|
||||
ret_send_recv(c::recvmsg(
|
||||
borrowed_fd(sockfd),
|
||||
msghdr,
|
||||
bitflags_bits!(msg_flags),
|
||||
))
|
||||
};
|
||||
|
||||
result.map(|bytes| {
|
||||
// Get the address of the sender, if any.
|
||||
let addr =
|
||||
unsafe { maybe_read_sockaddr_os(msghdr.msg_name as _, msghdr.msg_namelen as _) };
|
||||
|
||||
RecvMsgReturn {
|
||||
bytes,
|
||||
address: addr,
|
||||
flags: RecvFlags::from_bits_retain(bitcast!(msghdr.msg_flags)),
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
pub(crate) fn sendmsg(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
msg_flags: SendFlags,
|
||||
) -> io::Result<usize> {
|
||||
with_noaddr_msghdr(iov, control, |msghdr| unsafe {
|
||||
ret_send_recv(c::sendmsg(
|
||||
borrowed_fd(sockfd),
|
||||
&msghdr,
|
||||
bitflags_bits!(msg_flags),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
pub(crate) fn sendmsg_v4(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
addr: &SocketAddrV4,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
msg_flags: SendFlags,
|
||||
) -> io::Result<usize> {
|
||||
with_v4_msghdr(addr, iov, control, |msghdr| unsafe {
|
||||
ret_send_recv(c::sendmsg(
|
||||
borrowed_fd(sockfd),
|
||||
&msghdr,
|
||||
bitflags_bits!(msg_flags),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
pub(crate) fn sendmsg_v6(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
addr: &SocketAddrV6,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
msg_flags: SendFlags,
|
||||
) -> io::Result<usize> {
|
||||
with_v6_msghdr(addr, iov, control, |msghdr| unsafe {
|
||||
ret_send_recv(c::sendmsg(
|
||||
borrowed_fd(sockfd),
|
||||
&msghdr,
|
||||
bitflags_bits!(msg_flags),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
unix,
|
||||
not(any(target_os = "espidf", target_os = "redox", target_os = "vita"))
|
||||
))]
|
||||
pub(crate) fn sendmsg_unix(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
addr: &SocketAddrUnix,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
msg_flags: SendFlags,
|
||||
) -> io::Result<usize> {
|
||||
super::msghdr::with_unix_msghdr(addr, iov, control, |msghdr| unsafe {
|
||||
ret_send_recv(c::sendmsg(
|
||||
borrowed_fd(sockfd),
|
||||
&msghdr,
|
||||
bitflags_bits!(msg_flags),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn sendmsg_xdp(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
addr: &SocketAddrXdp,
|
||||
iov: &[IoSlice<'_>],
|
||||
control: &mut SendAncillaryBuffer<'_, '_, '_>,
|
||||
msg_flags: SendFlags,
|
||||
) -> io::Result<usize> {
|
||||
with_xdp_msghdr(addr, iov, control, |msghdr| unsafe {
|
||||
ret_send_recv(c::sendmsg(
|
||||
borrowed_fd(sockfd),
|
||||
&msghdr,
|
||||
bitflags_bits!(msg_flags),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "redox",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result<OwnedFd> {
|
||||
unsafe {
|
||||
let owned_fd = ret_owned_fd(c::accept4(
|
||||
borrowed_fd(sockfd),
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
flags.bits() as c::c_int,
|
||||
))?;
|
||||
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(
|
||||
apple,
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub(crate) fn acceptfrom_with(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
flags: SocketFlags,
|
||||
) -> 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() as c::c_int,
|
||||
))?;
|
||||
Ok((
|
||||
owned_fd,
|
||||
maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Darwin lacks `accept4`, but does have `accept`. We define
|
||||
/// `SocketFlags` to have no flags, so we can discard it here.
|
||||
#[cfg(any(
|
||||
apple,
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
))]
|
||||
pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, _flags: SocketFlags) -> io::Result<OwnedFd> {
|
||||
accept(sockfd)
|
||||
}
|
||||
|
||||
/// Darwin lacks `accept4`, but does have `accept`. We define
|
||||
/// `SocketFlags` to have no flags, so we can discard it here.
|
||||
#[cfg(any(
|
||||
apple,
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
))]
|
||||
pub(crate) fn acceptfrom_with(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
_flags: SocketFlags,
|
||||
) -> 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: Option<Protocol>,
|
||||
) -> io::Result<(OwnedFd, OwnedFd)> {
|
||||
let raw_protocol = match protocol {
|
||||
Some(p) => p.0.get(),
|
||||
None => 0,
|
||||
};
|
||||
unsafe {
|
||||
let mut fds = MaybeUninit::<[OwnedFd; 2]>::uninit();
|
||||
ret(c::socketpair(
|
||||
c::c_int::from(domain.0),
|
||||
(type_.0 | flags.bits()) as c::c_int,
|
||||
raw_protocol as c::c_int,
|
||||
fds.as_mut_ptr().cast::<c::c_int>(),
|
||||
))?;
|
||||
|
||||
let [fd0, fd1] = fds.assume_init();
|
||||
Ok((fd0, fd1))
|
||||
}
|
||||
}
|
||||
125
third-party/vendor/rustix/src/backend/libc/net/write_sockaddr.rs
vendored
Normal file
125
third-party/vendor/rustix/src/backend/libc/net/write_sockaddr.rs
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
//! 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::addr::SocketAddrStorage;
|
||||
#[cfg(unix)]
|
||||
use super::addr::SocketAddrUnix;
|
||||
use super::ext::{in6_addr_new, in_addr_new, sockaddr_in6_new};
|
||||
use crate::backend::c;
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::net::xdp::SocketAddrXdp;
|
||||
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),
|
||||
#[cfg(target_os = "linux")]
|
||||
SocketAddrAny::Xdp(xdp) => write_sockaddr_xdp(xdp, storage),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in {
|
||||
c::sockaddr_in {
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
))]
|
||||
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())),
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "vita")))]
|
||||
sin_zero: [0; 8_usize],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sin_zero: [0; 24_usize],
|
||||
#[cfg(target_os = "vita")]
|
||||
sin_zero: [0; 6_usize],
|
||||
#[cfg(target_os = "vita")]
|
||||
sin_vport: 0,
|
||||
}
|
||||
}
|
||||
|
||||
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) fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 {
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
))]
|
||||
{
|
||||
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(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "vita"
|
||||
)))]
|
||||
{
|
||||
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()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn encode_sockaddr_xdp(xdp: &SocketAddrXdp) -> c::sockaddr_xdp {
|
||||
c::sockaddr_xdp {
|
||||
sxdp_family: c::AF_XDP as _,
|
||||
sxdp_flags: xdp.flags().bits(),
|
||||
sxdp_ifindex: xdp.interface_index(),
|
||||
sxdp_queue_id: xdp.queue_id(),
|
||||
sxdp_shared_umem_fd: xdp.shared_umem_fd(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe fn write_sockaddr_xdp(xdp: &SocketAddrXdp, storage: *mut SocketAddrStorage) -> usize {
|
||||
let encoded = encode_sockaddr_xdp(xdp);
|
||||
core::ptr::write(storage.cast(), encoded);
|
||||
size_of::<c::sockaddr_xdp>()
|
||||
}
|
||||
54
third-party/vendor/rustix/src/backend/libc/param/auxv.rs
vendored
Normal file
54
third-party/vendor/rustix/src/backend/libc/param/auxv.rs
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use crate::backend::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(any(target_os = "vita", 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!("")
|
||||
}
|
||||
}
|
||||
1
third-party/vendor/rustix/src/backend/libc/param/mod.rs
vendored
Normal file
1
third-party/vendor/rustix/src/backend/libc/param/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod auxv;
|
||||
1
third-party/vendor/rustix/src/backend/libc/pid/mod.rs
vendored
Normal file
1
third-party/vendor/rustix/src/backend/libc/pid/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod syscalls;
|
||||
14
third-party/vendor/rustix/src/backend/libc/pid/syscalls.rs
vendored
Normal file
14
third-party/vendor/rustix/src/backend/libc/pid/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
//! libc syscalls for PIDs
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::pid::Pid;
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn getpid() -> Pid {
|
||||
unsafe {
|
||||
let pid = c::getpid();
|
||||
Pid::from_raw_unchecked(pid)
|
||||
}
|
||||
}
|
||||
2
third-party/vendor/rustix/src/backend/libc/pipe/mod.rs
vendored
Normal file
2
third-party/vendor/rustix/src/backend/libc/pipe/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
125
third-party/vendor/rustix/src/backend/libc/pipe/syscalls.rs
vendored
Normal file
125
third-party/vendor/rustix/src/backend/libc/pipe/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
use crate::backend::c;
|
||||
use crate::backend::conv::ret;
|
||||
use crate::fd::OwnedFd;
|
||||
use crate::io;
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use crate::pipe::PipeFlags;
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(linux_kernel)]
|
||||
use {
|
||||
crate::backend::conv::{borrowed_fd, ret_c_int, ret_usize},
|
||||
crate::backend::MAX_IOV,
|
||||
crate::fd::BorrowedFd,
|
||||
crate::pipe::{IoSliceRaw, SpliceFlags},
|
||||
crate::utils::option_as_mut_ptr,
|
||||
core::cmp::min,
|
||||
};
|
||||
|
||||
#[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(
|
||||
apple,
|
||||
target_os = "aix",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
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>(),
|
||||
bitflags_bits!(flags),
|
||||
))?;
|
||||
let [p0, p1] = result.assume_init();
|
||||
Ok((p0, p1))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub fn splice(
|
||||
fd_in: BorrowedFd<'_>,
|
||||
off_in: Option<&mut u64>,
|
||||
fd_out: BorrowedFd<'_>,
|
||||
off_out: Option<&mut u64>,
|
||||
len: usize,
|
||||
flags: SpliceFlags,
|
||||
) -> io::Result<usize> {
|
||||
let off_in = option_as_mut_ptr(off_in).cast();
|
||||
let off_out = option_as_mut_ptr(off_out).cast();
|
||||
|
||||
unsafe {
|
||||
ret_usize(c::splice(
|
||||
borrowed_fd(fd_in),
|
||||
off_in,
|
||||
borrowed_fd(fd_out),
|
||||
off_out,
|
||||
len,
|
||||
flags.bits(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub unsafe fn vmsplice(
|
||||
fd: BorrowedFd<'_>,
|
||||
bufs: &[IoSliceRaw<'_>],
|
||||
flags: SpliceFlags,
|
||||
) -> io::Result<usize> {
|
||||
ret_usize(c::vmsplice(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), MAX_IOV),
|
||||
flags.bits(),
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub fn tee(
|
||||
fd_in: BorrowedFd<'_>,
|
||||
fd_out: BorrowedFd<'_>,
|
||||
len: usize,
|
||||
flags: SpliceFlags,
|
||||
) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ret_usize(c::tee(
|
||||
borrowed_fd(fd_in),
|
||||
borrowed_fd(fd_out),
|
||||
len,
|
||||
flags.bits(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result<usize> {
|
||||
unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETPIPE_SZ)).map(|size| size as usize) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn fcntl_setpipe_sz(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
|
||||
let size: c::c_int = size.try_into().map_err(|_| io::Errno::PERM)?;
|
||||
|
||||
unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETPIPE_SZ, size)) }
|
||||
}
|
||||
103
third-party/vendor/rustix/src/backend/libc/pipe/types.rs
vendored
Normal file
103
third-party/vendor/rustix/src/backend/libc/pipe/types.rs
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#[cfg(linux_kernel)]
|
||||
use core::marker::PhantomData;
|
||||
#[cfg(not(any(apple, target_os = "wasi")))]
|
||||
use {crate::backend::c, bitflags::bitflags};
|
||||
|
||||
#[cfg(not(any(apple, target_os = "wasi")))]
|
||||
bitflags! {
|
||||
/// `O_*` constants for use with [`pipe_with`].
|
||||
///
|
||||
/// [`pipe_with`]: crate::pipe::pipe_with
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct PipeFlags: u32 {
|
||||
/// `O_CLOEXEC`
|
||||
const CLOEXEC = bitcast!(c::O_CLOEXEC);
|
||||
/// `O_DIRECT`
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
const DIRECT = bitcast!(c::O_DIRECT);
|
||||
/// `O_NONBLOCK`
|
||||
const NONBLOCK = bitcast!(c::O_NONBLOCK);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `SPLICE_F_*` constants for use with [`splice`], [`vmsplice`], and
|
||||
/// [`tee`].
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct SpliceFlags: c::c_uint {
|
||||
/// `SPLICE_F_MOVE`
|
||||
const MOVE = c::SPLICE_F_MOVE;
|
||||
/// `SPLICE_F_NONBLOCK`
|
||||
const NONBLOCK = c::SPLICE_F_NONBLOCK;
|
||||
/// `SPLICE_F_MORE`
|
||||
const MORE = c::SPLICE_F_MORE;
|
||||
/// `SPLICE_F_GIFT`
|
||||
const GIFT = c::SPLICE_F_GIFT;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// A buffer type for use with [`vmsplice`].
|
||||
///
|
||||
/// It is guaranteed to be ABI compatible with the iovec type on Unix platforms
|
||||
/// and `WSABUF` on Windows. Unlike `IoSlice` and `IoSliceMut` it is
|
||||
/// semantically like a raw pointer, and therefore can be shared or mutated as
|
||||
/// needed.
|
||||
///
|
||||
/// [`vmsplice`]: crate::pipe::vmsplice
|
||||
#[cfg(linux_kernel)]
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceRaw<'a> {
|
||||
_buf: c::iovec,
|
||||
_lifetime: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
impl<'a> IoSliceRaw<'a> {
|
||||
/// Creates a new `IoSlice` wrapping a byte slice.
|
||||
pub fn from_slice(buf: &'a [u8]) -> Self {
|
||||
IoSliceRaw {
|
||||
_buf: c::iovec {
|
||||
iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void,
|
||||
iov_len: buf.len() as _,
|
||||
},
|
||||
_lifetime: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `IoSlice` wrapping a mutable byte slice.
|
||||
pub fn from_slice_mut(buf: &'a mut [u8]) -> Self {
|
||||
IoSliceRaw {
|
||||
_buf: c::iovec {
|
||||
iov_base: buf.as_mut_ptr() as *mut c::c_void,
|
||||
iov_len: buf.len() as _,
|
||||
},
|
||||
_lifetime: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(apple, target_os = "wasi")))]
|
||||
#[test]
|
||||
fn test_types() {
|
||||
assert_eq_size!(PipeFlags, c::c_int);
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
assert_eq_size!(SpliceFlags, c::c_int);
|
||||
}
|
||||
1
third-party/vendor/rustix/src/backend/libc/prctl/mod.rs
vendored
Normal file
1
third-party/vendor/rustix/src/backend/libc/prctl/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod syscalls;
|
||||
14
third-party/vendor/rustix/src/backend/libc/prctl/syscalls.rs
vendored
Normal file
14
third-party/vendor/rustix/src/backend/libc/prctl/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
use crate::backend::c;
|
||||
use crate::backend::conv::ret_c_int;
|
||||
use crate::io;
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn prctl(
|
||||
option: c::c_int,
|
||||
arg2: *mut c::c_void,
|
||||
arg3: *mut c::c_void,
|
||||
arg4: *mut c::c_void,
|
||||
arg5: *mut c::c_void,
|
||||
) -> io::Result<c::c_int> {
|
||||
ret_c_int(c::prctl(option, arg2, arg3, arg4, arg5))
|
||||
}
|
||||
50
third-party/vendor/rustix/src/backend/libc/process/cpu_set.rs
vendored
Normal file
50
third-party/vendor/rustix/src/backend/libc/process/cpu_set.rs
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//! Rust implementation of the `CPU_*` macro API.
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use super::types::{RawCpuSet, CPU_SETSIZE};
|
||||
use crate::backend::c;
|
||||
|
||||
#[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(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn CPU_COUNT(cpuset: &RawCpuSet) -> u32 {
|
||||
unsafe { c::CPU_COUNT(cpuset).try_into().unwrap() }
|
||||
}
|
||||
7
third-party/vendor/rustix/src/backend/libc/process/mod.rs
vendored
Normal file
7
third-party/vendor/rustix/src/backend/libc/process/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
|
||||
pub(crate) mod cpu_set;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "wasi")))]
|
||||
pub(crate) mod wait;
|
||||
713
third-party/vendor/rustix/src/backend/libc/process/syscalls.rs
vendored
Normal file
713
third-party/vendor/rustix/src/backend/libc/process/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,713 @@
|
|||
//! libc syscalls supporting `rustix::process`.
|
||||
|
||||
#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
|
||||
use super::types::RawCpuSet;
|
||||
use crate::backend::c;
|
||||
#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
|
||||
use crate::backend::conv::borrowed_fd;
|
||||
#[cfg(feature = "fs")]
|
||||
use crate::backend::conv::c_str;
|
||||
#[cfg(all(feature = "alloc", feature = "fs", not(target_os = "wasi")))]
|
||||
use crate::backend::conv::ret_discarded_char_ptr;
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use crate::backend::conv::ret_infallible;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::backend::conv::ret_pid_t;
|
||||
#[cfg(linux_kernel)]
|
||||
use crate::backend::conv::ret_u32;
|
||||
#[cfg(all(feature = "alloc", not(target_os = "wasi")))]
|
||||
use crate::backend::conv::ret_usize;
|
||||
use crate::backend::conv::{ret, ret_c_int};
|
||||
#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
|
||||
use crate::fd::BorrowedFd;
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::fd::{AsRawFd, OwnedFd, RawFd};
|
||||
#[cfg(feature = "fs")]
|
||||
use crate::ffi::CStr;
|
||||
#[cfg(feature = "fs")]
|
||||
use crate::fs::Mode;
|
||||
use crate::io;
|
||||
#[cfg(all(feature = "alloc", not(target_os = "wasi")))]
|
||||
use crate::process::Gid;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::process::Pid;
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
use crate::process::Signal;
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use crate::process::Uid;
|
||||
#[cfg(linux_kernel)]
|
||||
use crate::process::{Cpuid, MembarrierCommand, MembarrierQuery};
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "wasi")))]
|
||||
use crate::process::{RawPid, WaitOptions, WaitStatus};
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use crate::process::{Resource, Rlimit};
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "openbsd",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use crate::process::{WaitId, WaitidOptions, WaitidStatus};
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(target_os = "linux")]
|
||||
use {
|
||||
super::super::conv::ret_owned_fd, crate::process::PidfdFlags, crate::process::PidfdGetfdFlags,
|
||||
};
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "dragonfly"))]
|
||||
#[inline]
|
||||
pub(crate) fn sched_getcpu() -> usize {
|
||||
let r = unsafe { libc::sched_getcpu() };
|
||||
debug_assert!(r >= 0);
|
||||
r as usize
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
#[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 = "fuchsia", target_os = "wasi")))]
|
||||
pub(crate) fn fchdir(dirfd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe { ret(c::fchdir(borrowed_fd(dirfd))) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
pub(crate) fn chroot(path: &CStr) -> io::Result<()> {
|
||||
unsafe { ret(c::chroot(c_str(path))) }
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "alloc", feature = "fs"))]
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn getcwd(buf: &mut [MaybeUninit<u8>]) -> io::Result<()> {
|
||||
unsafe { ret_discarded_char_ptr(c::getcwd(buf.as_mut_ptr().cast(), buf.len())) }
|
||||
}
|
||||
|
||||
// The `membarrier` syscall has a third argument, but it's only used when
|
||||
// the `flags` argument is `MEMBARRIER_CMD_FLAG_CPU`.
|
||||
#[cfg(linux_kernel)]
|
||||
syscall! {
|
||||
fn membarrier_all(
|
||||
cmd: c::c_int,
|
||||
flags: c::c_uint
|
||||
) via SYS_membarrier -> c::c_int
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
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 ret_u32(membarrier_all(MEMBARRIER_CMD_QUERY as i32, 0)) {
|
||||
Ok(query) => MembarrierQuery::from_bits_retain(query),
|
||||
Err(_) => MembarrierQuery::empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) fn membarrier(cmd: MembarrierCommand) -> io::Result<()> {
|
||||
unsafe { ret(membarrier_all(cmd as i32, 0)) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
|
||||
const MEMBARRIER_CMD_FLAG_CPU: u32 = 1;
|
||||
|
||||
syscall! {
|
||||
fn membarrier_cpu(
|
||||
cmd: c::c_int,
|
||||
flags: c::c_uint,
|
||||
cpu_id: c::c_int
|
||||
) via SYS_membarrier -> c::c_int
|
||||
}
|
||||
|
||||
unsafe {
|
||||
ret(membarrier_cpu(
|
||||
cmd as i32,
|
||||
MEMBARRIER_CMD_FLAG_CPU,
|
||||
bitcast!(cpu.as_raw()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[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(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn getpgid(pid: Option<Pid>) -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pgid = ret_pid_t(c::getpgid(Pid::as_raw(pid) as _))?;
|
||||
Ok(Pid::from_raw_unchecked(pgid))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn setpgid(pid: Option<Pid>, pgid: Option<Pid>) -> io::Result<()> {
|
||||
unsafe { ret(c::setpgid(Pid::as_raw(pid) as _, Pid::as_raw(pgid) as _)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn getpgrp() -> Pid {
|
||||
unsafe {
|
||||
let pgid = c::getpgrp();
|
||||
Pid::from_raw_unchecked(pgid)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
|
||||
#[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(freebsdlike, linux_kernel, target_os = "fuchsia"))]
|
||||
#[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"))]
|
||||
#[cfg(feature = "fs")]
|
||||
#[inline]
|
||||
pub(crate) fn umask(mask: Mode) -> Mode {
|
||||
unsafe { Mode::from_bits_retain(c::umask(mask.bits() as c::mode_t).into()) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "vita", 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 = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "vita",
|
||||
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 = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "vita",
|
||||
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 = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "vita",
|
||||
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 = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "vita",
|
||||
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 = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "vita",
|
||||
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 = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "vita",
|
||||
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 = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn getrlimit(limit: Resource) -> Rlimit {
|
||||
let mut result = MaybeUninit::<c::rlimit>::uninit();
|
||||
unsafe {
|
||||
ret_infallible(c::getrlimit(limit as _, result.as_mut_ptr()));
|
||||
rlimit_from_libc(result.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn setrlimit(limit: Resource, new: Rlimit) -> io::Result<()> {
|
||||
let lim = rlimit_to_libc(new)?;
|
||||
unsafe { ret(c::setrlimit(limit as _, &lim)) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[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::<c::rlimit>::uninit();
|
||||
unsafe {
|
||||
ret(c::prlimit(
|
||||
Pid::as_raw(pid),
|
||||
limit as _,
|
||||
&lim,
|
||||
result.as_mut_ptr(),
|
||||
))?;
|
||||
Ok(rlimit_from_libc(result.assume_init()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a Rust [`Rlimit`] to a C `c::rlimit`.
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
fn rlimit_from_libc(lim: c::rlimit) -> Rlimit {
|
||||
let current = if lim.rlim_cur == c::RLIM_INFINITY {
|
||||
None
|
||||
} else {
|
||||
Some(lim.rlim_cur.try_into().unwrap())
|
||||
};
|
||||
let maximum = if lim.rlim_max == c::RLIM_INFINITY {
|
||||
None
|
||||
} else {
|
||||
Some(lim.rlim_max.try_into().unwrap())
|
||||
};
|
||||
Rlimit { current, maximum }
|
||||
}
|
||||
|
||||
/// Convert a C `c::rlimit` to a Rust `Rlimit`.
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
fn rlimit_to_libc(lim: Rlimit) -> io::Result<c::rlimit> {
|
||||
let Rlimit { current, maximum } = lim;
|
||||
let rlim_cur = match current {
|
||||
Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?,
|
||||
None => c::RLIM_INFINITY as _,
|
||||
};
|
||||
let rlim_max = match maximum {
|
||||
Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?,
|
||||
None => c::RLIM_INFINITY as _,
|
||||
};
|
||||
Ok(c::rlimit { rlim_cur, rlim_max })
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn wait(waitopts: WaitOptions) -> io::Result<Option<(Pid, WaitStatus)>> {
|
||||
_waitpid(!0, waitopts)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita", 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(any(target_os = "espidf", target_os = "vita", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn waitpgid(pgid: Pid, waitopts: WaitOptions) -> io::Result<Option<(Pid, WaitStatus)>> {
|
||||
_waitpid(-pgid.as_raw_nonzero().get(), waitopts)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita", 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(Pid::from_raw(pid).map(|pid| (pid, WaitStatus::new(status as _))))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "openbsd",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn waitid(id: WaitId<'_>, options: WaitidOptions) -> io::Result<Option<WaitidStatus>> {
|
||||
// Get the id to wait on.
|
||||
match id {
|
||||
WaitId::All => _waitid_all(options),
|
||||
WaitId::Pid(pid) => _waitid_pid(pid, options),
|
||||
WaitId::Pgid(pgid) => _waitid_pgid(pgid, options),
|
||||
#[cfg(target_os = "linux")]
|
||||
WaitId::PidFd(fd) => _waitid_pidfd(fd, options),
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
WaitId::__EatLifetime(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "openbsd",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[inline]
|
||||
fn _waitid_all(options: WaitidOptions) -> io::Result<Option<WaitidStatus>> {
|
||||
// `waitid` can return successfully without initializing the struct (no
|
||||
// children found when using `WNOHANG`)
|
||||
let mut status = MaybeUninit::<c::siginfo_t>::zeroed();
|
||||
unsafe {
|
||||
ret(c::waitid(
|
||||
c::P_ALL,
|
||||
0,
|
||||
status.as_mut_ptr(),
|
||||
options.bits() as _,
|
||||
))?
|
||||
};
|
||||
|
||||
Ok(unsafe { cvt_waitid_status(status) })
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "openbsd",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[inline]
|
||||
fn _waitid_pid(pid: Pid, options: WaitidOptions) -> io::Result<Option<WaitidStatus>> {
|
||||
// `waitid` can return successfully without initializing the struct (no
|
||||
// children found when using `WNOHANG`)
|
||||
let mut status = MaybeUninit::<c::siginfo_t>::zeroed();
|
||||
unsafe {
|
||||
ret(c::waitid(
|
||||
c::P_PID,
|
||||
Pid::as_raw(Some(pid)) as _,
|
||||
status.as_mut_ptr(),
|
||||
options.bits() as _,
|
||||
))?
|
||||
};
|
||||
|
||||
Ok(unsafe { cvt_waitid_status(status) })
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "openbsd",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[inline]
|
||||
fn _waitid_pgid(pgid: Option<Pid>, options: WaitidOptions) -> io::Result<Option<WaitidStatus>> {
|
||||
// `waitid` can return successfully without initializing the struct (no
|
||||
// children found when using `WNOHANG`)
|
||||
let mut status = MaybeUninit::<c::siginfo_t>::zeroed();
|
||||
unsafe {
|
||||
ret(c::waitid(
|
||||
c::P_PGID,
|
||||
Pid::as_raw(pgid) as _,
|
||||
status.as_mut_ptr(),
|
||||
options.bits() as _,
|
||||
))?
|
||||
};
|
||||
|
||||
Ok(unsafe { cvt_waitid_status(status) })
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[inline]
|
||||
fn _waitid_pidfd(fd: BorrowedFd<'_>, options: WaitidOptions) -> io::Result<Option<WaitidStatus>> {
|
||||
// `waitid` can return successfully without initializing the struct (no
|
||||
// children found when using `WNOHANG`)
|
||||
let mut status = MaybeUninit::<c::siginfo_t>::zeroed();
|
||||
unsafe {
|
||||
ret(c::waitid(
|
||||
c::P_PIDFD,
|
||||
fd.as_raw_fd() as _,
|
||||
status.as_mut_ptr(),
|
||||
options.bits() as _,
|
||||
))?
|
||||
};
|
||||
|
||||
Ok(unsafe { cvt_waitid_status(status) })
|
||||
}
|
||||
|
||||
/// Convert a `siginfo_t` to a `WaitidStatus`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that `status` is initialized and that `waitid`
|
||||
/// returned successfully.
|
||||
#[cfg(not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[inline]
|
||||
unsafe fn cvt_waitid_status(status: MaybeUninit<c::siginfo_t>) -> Option<WaitidStatus> {
|
||||
let status = status.assume_init();
|
||||
// `si_pid` is supposedly the better way to check that the struct has been
|
||||
// filled, e.g. the Linux manpage says about the `WNOHANG` case “zero out
|
||||
// the si_pid field before the call and check for a nonzero value”.
|
||||
// But e.g. NetBSD/OpenBSD don't have it exposed in the libc crate for now,
|
||||
// and some platforms don't have it at all. For simplicity, always check
|
||||
// `si_signo`. We have zero-initialized the whole struct, and all kernels
|
||||
// should set `SIGCHLD` here.
|
||||
if status.si_signo == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(WaitidStatus(status))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn getsid(pid: Option<Pid>) -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pid = ret_pid_t(c::getsid(Pid::as_raw(pid) as _))?;
|
||||
Ok(Pid::from_raw_unchecked(pid))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn setsid() -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pid = ret_c_int(c::setsid())?;
|
||||
Ok(Pid::from_raw_unchecked(pid))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", 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(any(target_os = "espidf", 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(any(target_os = "espidf", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn kill_current_process_group(sig: Signal) -> io::Result<()> {
|
||||
unsafe { ret(c::kill(0, sig as i32)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
pub(crate) fn test_kill_process(pid: Pid) -> io::Result<()> {
|
||||
unsafe { ret(c::kill(pid.as_raw_nonzero().get(), 0)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn test_kill_process_group(pid: Pid) -> io::Result<()> {
|
||||
unsafe { ret(c::kill(pid.as_raw_nonzero().get().wrapping_neg(), 0)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn test_kill_current_process_group() -> io::Result<()> {
|
||||
unsafe { ret(c::kill(0, 0)) }
|
||||
}
|
||||
|
||||
#[cfg(freebsdlike)]
|
||||
#[inline]
|
||||
pub(crate) unsafe fn procctl(
|
||||
idtype: c::idtype_t,
|
||||
id: c::id_t,
|
||||
option: c::c_int,
|
||||
data: *mut c::c_void,
|
||||
) -> io::Result<()> {
|
||||
ret(c::procctl(idtype, id, option, data))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn pidfd_open(pid: Pid, flags: PidfdFlags) -> io::Result<OwnedFd> {
|
||||
syscall! {
|
||||
fn pidfd_open(
|
||||
pid: c::pid_t,
|
||||
flags: c::c_uint
|
||||
) via SYS_pidfd_open -> c::c_int
|
||||
}
|
||||
unsafe {
|
||||
ret_owned_fd(pidfd_open(
|
||||
pid.as_raw_nonzero().get(),
|
||||
bitflags_bits!(flags),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn pidfd_getfd(
|
||||
pidfd: BorrowedFd<'_>,
|
||||
targetfd: RawFd,
|
||||
flags: PidfdGetfdFlags,
|
||||
) -> io::Result<OwnedFd> {
|
||||
syscall! {
|
||||
fn pidfd_getfd(
|
||||
pidfd: c::c_int,
|
||||
targetfd: c::c_int,
|
||||
flags: c::c_uint
|
||||
) via SYS_pidfd_getfd -> c::c_int
|
||||
}
|
||||
unsafe {
|
||||
ret_owned_fd(pidfd_getfd(
|
||||
borrowed_fd(pidfd),
|
||||
targetfd,
|
||||
bitflags_bits!(flags),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "alloc", not(target_os = "wasi")))]
|
||||
pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result<usize> {
|
||||
let len = buf.len().try_into().map_err(|_| io::Errno::NOMEM)?;
|
||||
|
||||
unsafe { ret_usize(c::getgroups(len, buf.as_mut_ptr().cast()) as isize) }
|
||||
}
|
||||
172
third-party/vendor/rustix/src/backend/libc/process/types.rs
vendored
Normal file
172
third-party/vendor/rustix/src/backend/libc/process/types.rs
vendored
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#[cfg(not(any(target_os = "espidf", target_os = "vita")))]
|
||||
use crate::backend::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
|
||||
#[cfg(linux_kernel)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum MembarrierCommand {
|
||||
/// `MEMBARRIER_CMD_GLOBAL`
|
||||
#[doc(alias = "Shared")]
|
||||
#[doc(alias = "MEMBARRIER_CMD_SHARED")]
|
||||
Global = c::MEMBARRIER_CMD_GLOBAL as u32,
|
||||
/// `MEMBARRIER_CMD_GLOBAL_EXPEDITED`
|
||||
GlobalExpedited = c::MEMBARRIER_CMD_GLOBAL_EXPEDITED as u32,
|
||||
/// `MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED`
|
||||
RegisterGlobalExpedited = c::MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED as u32,
|
||||
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED`
|
||||
PrivateExpedited = c::MEMBARRIER_CMD_PRIVATE_EXPEDITED as u32,
|
||||
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED`
|
||||
RegisterPrivateExpedited = c::MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED as u32,
|
||||
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE`
|
||||
PrivateExpeditedSyncCore = c::MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE as u32,
|
||||
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE`
|
||||
RegisterPrivateExpeditedSyncCore =
|
||||
c::MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE as u32,
|
||||
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
|
||||
PrivateExpeditedRseq = c::MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ as u32,
|
||||
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
|
||||
RegisterPrivateExpeditedRseq = c::MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ as u32,
|
||||
}
|
||||
|
||||
/// 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 = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(not(target_os = "l4re"), repr(u32))]
|
||||
#[cfg_attr(target_os = "l4re", repr(u64))]
|
||||
pub enum Resource {
|
||||
/// `RLIMIT_CPU`
|
||||
Cpu = bitcast!(c::RLIMIT_CPU),
|
||||
/// `RLIMIT_FSIZE`
|
||||
Fsize = bitcast!(c::RLIMIT_FSIZE),
|
||||
/// `RLIMIT_DATA`
|
||||
Data = bitcast!(c::RLIMIT_DATA),
|
||||
/// `RLIMIT_STACK`
|
||||
Stack = bitcast!(c::RLIMIT_STACK),
|
||||
/// `RLIMIT_CORE`
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
Core = bitcast!(c::RLIMIT_CORE),
|
||||
/// `RLIMIT_RSS`
|
||||
// "nto" has `RLIMIT_RSS`, but it has the same value as `RLIMIT_AS`.
|
||||
#[cfg(not(any(apple, solarish, target_os = "nto", target_os = "haiku")))]
|
||||
Rss = bitcast!(c::RLIMIT_RSS),
|
||||
/// `RLIMIT_NPROC`
|
||||
#[cfg(not(any(solarish, target_os = "haiku")))]
|
||||
Nproc = bitcast!(c::RLIMIT_NPROC),
|
||||
/// `RLIMIT_NOFILE`
|
||||
Nofile = bitcast!(c::RLIMIT_NOFILE),
|
||||
/// `RLIMIT_MEMLOCK`
|
||||
#[cfg(not(any(solarish, target_os = "aix", target_os = "haiku")))]
|
||||
Memlock = bitcast!(c::RLIMIT_MEMLOCK),
|
||||
/// `RLIMIT_AS`
|
||||
#[cfg(not(target_os = "openbsd"))]
|
||||
As = bitcast!(c::RLIMIT_AS),
|
||||
/// `RLIMIT_LOCKS`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "nto"
|
||||
)))]
|
||||
Locks = bitcast!(c::RLIMIT_LOCKS),
|
||||
/// `RLIMIT_SIGPENDING`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "nto"
|
||||
)))]
|
||||
Sigpending = bitcast!(c::RLIMIT_SIGPENDING),
|
||||
/// `RLIMIT_MSGQUEUE`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "nto"
|
||||
)))]
|
||||
Msgqueue = bitcast!(c::RLIMIT_MSGQUEUE),
|
||||
/// `RLIMIT_NICE`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "nto"
|
||||
)))]
|
||||
Nice = bitcast!(c::RLIMIT_NICE),
|
||||
/// `RLIMIT_RTPRIO`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "nto"
|
||||
)))]
|
||||
Rtprio = bitcast!(c::RLIMIT_RTPRIO),
|
||||
/// `RLIMIT_RTTIME`
|
||||
#[cfg(not(any(
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
Rttime = bitcast!(c::RLIMIT_RTTIME),
|
||||
}
|
||||
|
||||
#[cfg(apple)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
impl Resource {
|
||||
/// `RLIMIT_RSS`
|
||||
pub const Rss: Self = Self::As;
|
||||
}
|
||||
|
||||
/// A CPU identifier as a raw integer.
|
||||
#[cfg(linux_kernel)]
|
||||
pub type RawCpuid = u32;
|
||||
#[cfg(freebsdlike)]
|
||||
pub type RawId = c::id_t;
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
pub(crate) type RawCpuSet = c::cpu_set_t;
|
||||
#[cfg(freebsdlike)]
|
||||
pub(crate) type RawCpuSet = c::cpuset_t;
|
||||
|
||||
#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
|
||||
#[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(freebsdlike, linux_kernel, target_os = "fuchsia"))]
|
||||
pub(crate) const CPU_SETSIZE: usize = c::CPU_SETSIZE as usize;
|
||||
9
third-party/vendor/rustix/src/backend/libc/process/wait.rs
vendored
Normal file
9
third-party/vendor/rustix/src/backend/libc/process/wait.rs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
use crate::backend::c;
|
||||
|
||||
pub(crate) use c::{
|
||||
WCONTINUED, WEXITSTATUS, WIFCONTINUED, WIFEXITED, WIFSIGNALED, WIFSTOPPED, WNOHANG, WSTOPSIG,
|
||||
WTERMSIG, WUNTRACED,
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) use c::{WEXITED, WNOWAIT, WSTOPPED};
|
||||
1
third-party/vendor/rustix/src/backend/libc/pty/mod.rs
vendored
Normal file
1
third-party/vendor/rustix/src/backend/libc/pty/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod syscalls;
|
||||
106
third-party/vendor/rustix/src/backend/libc/pty/syscalls.rs
vendored
Normal file
106
third-party/vendor/rustix/src/backend/libc/pty/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
//! libc syscalls supporting `rustix::pty`.
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::{borrowed_fd, ret};
|
||||
use crate::fd::BorrowedFd;
|
||||
use crate::io;
|
||||
#[cfg(all(
|
||||
feature = "alloc",
|
||||
any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia")
|
||||
))]
|
||||
use {
|
||||
crate::ffi::{CStr, CString},
|
||||
crate::path::SMALL_PATH_BUFFER_SIZE,
|
||||
alloc::borrow::ToOwned,
|
||||
alloc::vec::Vec,
|
||||
};
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
use crate::{backend::conv::ret_owned_fd, fd::OwnedFd, pty::OpenptFlags};
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
#[inline]
|
||||
pub(crate) fn openpt(flags: OpenptFlags) -> io::Result<OwnedFd> {
|
||||
unsafe { ret_owned_fd(c::posix_openpt(flags.bits() as _)) }
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "alloc",
|
||||
any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia")
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn ptsname(fd: 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 {
|
||||
// On platforms with `ptsname_r`, use it.
|
||||
#[cfg(any(linux_like, target_os = "fuchsia"))]
|
||||
let r = unsafe { c::ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len()) };
|
||||
|
||||
// FreeBSD 12 doesn't have `ptsname_r`.
|
||||
#[cfg(target_os = "freebsd")]
|
||||
let r = unsafe {
|
||||
weak! {
|
||||
fn ptsname_r(
|
||||
c::c_int,
|
||||
*mut c::c_char,
|
||||
c::size_t
|
||||
) -> c::c_int
|
||||
}
|
||||
if let Some(func) = ptsname_r.get() {
|
||||
func(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len())
|
||||
} else {
|
||||
libc::ENOSYS
|
||||
}
|
||||
};
|
||||
|
||||
// macOS 10.13.4 has `ptsname_r`; use it if we have it, otherwise fall
|
||||
// back to calling the underlying ioctl directly.
|
||||
#[cfg(apple)]
|
||||
let r = unsafe {
|
||||
weak! { fn ptsname_r(c::c_int, *mut c::c_char, c::size_t) -> c::c_int }
|
||||
|
||||
if let Some(libc_ptsname_r) = ptsname_r.get() {
|
||||
libc_ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len())
|
||||
} else {
|
||||
// The size declared in the `TIOCPTYGNAME` macro in
|
||||
// sys/ttycom.h is 128.
|
||||
let mut name: [u8; 128] = [0_u8; 128];
|
||||
match c::ioctl(borrowed_fd(fd), c::TIOCPTYGNAME as _, &mut name) {
|
||||
0 => {
|
||||
let len = CStr::from_ptr(name.as_ptr().cast()).to_bytes().len();
|
||||
std::ptr::copy_nonoverlapping(name.as_ptr(), buffer.as_mut_ptr(), len + 1);
|
||||
0
|
||||
}
|
||||
_ => libc_errno::errno().0,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if r == 0 {
|
||||
return Ok(unsafe { CStr::from_ptr(buffer.as_ptr().cast()).to_owned() });
|
||||
}
|
||||
if r != c::ERANGE {
|
||||
return Err(io::Errno::from_raw_os_error(r));
|
||||
}
|
||||
|
||||
// Use `Vec` reallocation strategy to grow capacity exponentially.
|
||||
buffer.reserve(1);
|
||||
buffer.resize(buffer.capacity(), 0_u8);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn unlockpt(fd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe { ret(c::unlockpt(borrowed_fd(fd))) }
|
||||
}
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
#[inline]
|
||||
pub(crate) fn grantpt(fd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe { ret(c::grantpt(borrowed_fd(fd))) }
|
||||
}
|
||||
2
third-party/vendor/rustix/src/backend/libc/rand/mod.rs
vendored
Normal file
2
third-party/vendor/rustix/src/backend/libc/rand/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
18
third-party/vendor/rustix/src/backend/libc/rand/syscalls.rs
vendored
Normal file
18
third-party/vendor/rustix/src/backend/libc/rand/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
//! libc syscalls supporting `rustix::rand`.
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
use {crate::backend::c, crate::backend::conv::ret_usize, crate::io, crate::rand::GetRandomFlags};
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) unsafe fn getrandom(
|
||||
buf: *mut u8,
|
||||
cap: usize,
|
||||
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
|
||||
}
|
||||
|
||||
ret_usize(getrandom(buf.cast(), cap, flags.bits()))
|
||||
}
|
||||
24
third-party/vendor/rustix/src/backend/libc/rand/types.rs
vendored
Normal file
24
third-party/vendor/rustix/src/backend/libc/rand/types.rs
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#[cfg(linux_kernel)]
|
||||
use crate::backend::c;
|
||||
#[cfg(linux_kernel)]
|
||||
use bitflags::bitflags;
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
bitflags! {
|
||||
/// `GRND_*` flags for use with [`getrandom`].
|
||||
///
|
||||
/// [`getrandom`]: crate::rand::getrandom
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
2
third-party/vendor/rustix/src/backend/libc/shm/mod.rs
vendored
Normal file
2
third-party/vendor/rustix/src/backend/libc/shm/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
25
third-party/vendor/rustix/src/backend/libc/shm/syscalls.rs
vendored
Normal file
25
third-party/vendor/rustix/src/backend/libc/shm/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
use crate::ffi::CStr;
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::{c_str, ret, ret_owned_fd};
|
||||
use crate::fd::OwnedFd;
|
||||
use crate::fs::Mode;
|
||||
use crate::io;
|
||||
use crate::shm::ShmOFlags;
|
||||
|
||||
pub(crate) fn shm_open(name: &CStr, oflags: ShmOFlags, mode: Mode) -> io::Result<OwnedFd> {
|
||||
// On this platforms, `mode_t` is `u16` and can't be passed directly to a
|
||||
// variadic function.
|
||||
#[cfg(apple)]
|
||||
let mode: c::c_uint = mode.bits().into();
|
||||
|
||||
// Otherwise, cast to `mode_t` as that's what `open` is documented to take.
|
||||
#[cfg(not(apple))]
|
||||
let mode: c::mode_t = mode.bits() as _;
|
||||
|
||||
unsafe { ret_owned_fd(c::shm_open(c_str(name), bitflags_bits!(oflags), mode)) }
|
||||
}
|
||||
|
||||
pub(crate) fn shm_unlink(name: &CStr) -> io::Result<()> {
|
||||
unsafe { ret(c::shm_unlink(c_str(name))) }
|
||||
}
|
||||
30
third-party/vendor/rustix/src/backend/libc/shm/types.rs
vendored
Normal file
30
third-party/vendor/rustix/src/backend/libc/shm/types.rs
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
use crate::backend::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `O_*` constants for use with [`shm_open`].
|
||||
///
|
||||
/// [`shm_open`]: crate:shm::shm_open
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct ShmOFlags: u32 {
|
||||
/// `O_CREAT`
|
||||
#[doc(alias = "CREAT")]
|
||||
const CREATE = bitcast!(c::O_CREAT);
|
||||
|
||||
/// `O_EXCL`
|
||||
const EXCL = bitcast!(c::O_EXCL);
|
||||
|
||||
/// `O_RDONLY`
|
||||
const RDONLY = bitcast!(c::O_RDONLY);
|
||||
|
||||
/// `O_RDWR`
|
||||
const RDWR = bitcast!(c::O_RDWR);
|
||||
|
||||
/// `O_TRUNC`
|
||||
const TRUNC = bitcast!(c::O_TRUNC);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
3
third-party/vendor/rustix/src/backend/libc/system/mod.rs
vendored
Normal file
3
third-party/vendor/rustix/src/backend/libc/system/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
67
third-party/vendor/rustix/src/backend/libc/system/syscalls.rs
vendored
Normal file
67
third-party/vendor/rustix/src/backend/libc/system/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//! libc syscalls supporting `rustix::process`.
|
||||
|
||||
use super::types::RawUname;
|
||||
use crate::backend::c;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::backend::conv::ret_infallible;
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::system::RebootCommand;
|
||||
#[cfg(linux_kernel)]
|
||||
use crate::system::Sysinfo;
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(not(any(
|
||||
target_os = "emscripten",
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use {crate::backend::conv::ret, crate::io};
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn uname() -> RawUname {
|
||||
let mut uname = MaybeUninit::<RawUname>::uninit();
|
||||
unsafe {
|
||||
let r = c::uname(uname.as_mut_ptr());
|
||||
|
||||
// On POSIX, `uname` is documented to return non-negative on success
|
||||
// instead of the usual 0, though some specific systems do document
|
||||
// that they always use zero allowing us to skip this check.
|
||||
#[cfg(not(any(apple, freebsdlike, linux_like, target_os = "netbsd")))]
|
||||
let r = core::cmp::min(r, 0);
|
||||
|
||||
ret_infallible(r);
|
||||
uname.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
pub(crate) fn sysinfo() -> Sysinfo {
|
||||
let mut info = MaybeUninit::<Sysinfo>::uninit();
|
||||
unsafe {
|
||||
ret_infallible(c::sysinfo(info.as_mut_ptr()));
|
||||
info.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "emscripten",
|
||||
target_os = "espidf",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
pub(crate) fn sethostname(name: &[u8]) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::sethostname(
|
||||
name.as_ptr().cast(),
|
||||
name.len().try_into().map_err(|_| io::Errno::INVAL)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn reboot(cmd: RebootCommand) -> io::Result<()> {
|
||||
unsafe { ret(c::reboot(cmd as i32)) }
|
||||
}
|
||||
8
third-party/vendor/rustix/src/backend/libc/system/types.rs
vendored
Normal file
8
third-party/vendor/rustix/src/backend/libc/system/types.rs
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
use crate::backend::c;
|
||||
|
||||
/// `sysinfo`
|
||||
#[cfg(linux_kernel)]
|
||||
pub type Sysinfo = c::sysinfo;
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) type RawUname = c::utsname;
|
||||
1
third-party/vendor/rustix/src/backend/libc/termios/mod.rs
vendored
Normal file
1
third-party/vendor/rustix/src/backend/libc/termios/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod syscalls;
|
||||
403
third-party/vendor/rustix/src/backend/libc/termios/syscalls.rs
vendored
Normal file
403
third-party/vendor/rustix/src/backend/libc/termios/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
//! libc syscalls supporting `rustix::termios`.
|
||||
//!
|
||||
//! # Safety
|
||||
//!
|
||||
//! See the `rustix::backend::syscalls` module documentation for details.
|
||||
|
||||
use crate::backend::c;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::backend::conv::ret_pid_t;
|
||||
use crate::backend::conv::{borrowed_fd, ret};
|
||||
use crate::fd::BorrowedFd;
|
||||
#[cfg(all(feature = "alloc", feature = "procfs"))]
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
use crate::ffi::CStr;
|
||||
#[cfg(any(
|
||||
not(target_os = "espidf"),
|
||||
all(
|
||||
feature = "procfs",
|
||||
not(any(target_os = "fuchsia", target_os = "wasi"))
|
||||
)
|
||||
))]
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use {crate::io, crate::pid::Pid};
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
use {
|
||||
crate::termios::{Action, OptionalActions, QueueSelector, Termios, Winsize},
|
||||
crate::utils::as_mut_ptr,
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
|
||||
// If we have `TCGETS2`, use it, so that we fill in the `c_ispeed` and
|
||||
// `c_ospeed` fields.
|
||||
#[cfg(linux_kernel)]
|
||||
{
|
||||
use crate::termios::{ControlModes, InputModes, LocalModes, OutputModes, SpecialCodes};
|
||||
use crate::utils::default_array;
|
||||
|
||||
let termios2 = unsafe {
|
||||
let mut termios2 = MaybeUninit::<c::termios2>::uninit();
|
||||
|
||||
// QEMU's `TCGETS2` doesn't currently set `input_speed` or
|
||||
// `output_speed` on PowerPC, so zero out the fields ourselves.
|
||||
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
|
||||
{
|
||||
termios2.write(core::mem::zeroed());
|
||||
}
|
||||
|
||||
ret(c::ioctl(
|
||||
borrowed_fd(fd),
|
||||
c::TCGETS2 as _,
|
||||
termios2.as_mut_ptr(),
|
||||
))?;
|
||||
|
||||
termios2.assume_init()
|
||||
};
|
||||
|
||||
// Convert from the Linux `termios2` to our `Termios`.
|
||||
let mut result = Termios {
|
||||
input_modes: InputModes::from_bits_retain(termios2.c_iflag),
|
||||
output_modes: OutputModes::from_bits_retain(termios2.c_oflag),
|
||||
control_modes: ControlModes::from_bits_retain(termios2.c_cflag),
|
||||
local_modes: LocalModes::from_bits_retain(termios2.c_lflag),
|
||||
line_discipline: termios2.c_line,
|
||||
special_codes: SpecialCodes(default_array()),
|
||||
input_speed: termios2.c_ispeed,
|
||||
output_speed: termios2.c_ospeed,
|
||||
};
|
||||
|
||||
// QEMU's `TCGETS2` doesn't currently set `input_speed` or
|
||||
// `output_speed` on PowerPC, so set them manually if we can.
|
||||
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
|
||||
{
|
||||
use crate::termios::speed;
|
||||
|
||||
if result.output_speed == 0 && (termios2.c_cflag & c::CBAUD) != c::BOTHER {
|
||||
if let Some(output_speed) = speed::decode(termios2.c_cflag & c::CBAUD) {
|
||||
result.output_speed = output_speed;
|
||||
}
|
||||
}
|
||||
if result.input_speed == 0
|
||||
&& ((termios2.c_cflag & c::CIBAUD) >> c::IBSHIFT) != c::BOTHER
|
||||
{
|
||||
// For input speeds, `B0` is special-cased to mean the input
|
||||
// speed is the same as the output speed.
|
||||
if ((termios2.c_cflag & c::CIBAUD) >> c::IBSHIFT) == c::B0 {
|
||||
result.input_speed = result.output_speed;
|
||||
} else if let Some(input_speed) =
|
||||
speed::decode((termios2.c_cflag & c::CIBAUD) >> c::IBSHIFT)
|
||||
{
|
||||
result.input_speed = input_speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.special_codes.0[..termios2.c_cc.len()].copy_from_slice(&termios2.c_cc);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
unsafe {
|
||||
let mut result = MaybeUninit::<Termios>::uninit();
|
||||
|
||||
// `result` is a `Termios` which starts with the same layout as
|
||||
// `libc::termios`, so we can cast the pointer.
|
||||
ret(c::tcgetattr(borrowed_fd(fd), result.as_mut_ptr().cast()))?;
|
||||
|
||||
Ok(result.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pid = ret_pid_t(c::tcgetpgrp(borrowed_fd(fd)))?;
|
||||
|
||||
// This doesn't appear to be documented, but on Linux, it appears
|
||||
// `tcsetpgrp` can succceed and set the pid to 0 if we pass it a
|
||||
// pseudo-terminal device fd. For now, translate it into `OPNOTSUPP`.
|
||||
#[cfg(linux_kernel)]
|
||||
if pid == 0 {
|
||||
return Err(io::Errno::OPNOTSUPP);
|
||||
}
|
||||
|
||||
Ok(Pid::from_raw_unchecked(pid))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcsetpgrp(fd: BorrowedFd<'_>, pid: Pid) -> io::Result<()> {
|
||||
unsafe { ret(c::tcsetpgrp(borrowed_fd(fd), pid.as_raw_nonzero().get())) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
pub(crate) fn tcsetattr(
|
||||
fd: BorrowedFd<'_>,
|
||||
optional_actions: OptionalActions,
|
||||
termios: &Termios,
|
||||
) -> io::Result<()> {
|
||||
// If we have `TCSETS2`, use it, so that we use the `c_ispeed` and
|
||||
// `c_ospeed` fields.
|
||||
#[cfg(linux_kernel)]
|
||||
{
|
||||
use crate::termios::speed;
|
||||
use crate::utils::default_array;
|
||||
use linux_raw_sys::general::{termios2, BOTHER, CBAUD, IBSHIFT};
|
||||
|
||||
#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))]
|
||||
use linux_raw_sys::ioctl::{TCSETS, TCSETS2};
|
||||
|
||||
// linux-raw-sys' ioctl-generation script for sparc isn't working yet,
|
||||
// so as a temporary workaround, declare these manually.
|
||||
#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
|
||||
const TCSETS: u32 = 0x8024_5409;
|
||||
#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
|
||||
const TCSETS2: u32 = 0x802c_540d;
|
||||
|
||||
// Translate from `optional_actions` into an ioctl request code. On
|
||||
// MIPS, `optional_actions` already has `TCGETS` added to it.
|
||||
let request = TCSETS2
|
||||
+ if cfg!(any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6"
|
||||
)) {
|
||||
optional_actions as u32 - TCSETS
|
||||
} else {
|
||||
optional_actions as u32
|
||||
};
|
||||
|
||||
let input_speed = termios.input_speed();
|
||||
let output_speed = termios.output_speed();
|
||||
let mut termios2 = termios2 {
|
||||
c_iflag: termios.input_modes.bits(),
|
||||
c_oflag: termios.output_modes.bits(),
|
||||
c_cflag: termios.control_modes.bits(),
|
||||
c_lflag: termios.local_modes.bits(),
|
||||
c_line: termios.line_discipline,
|
||||
c_cc: default_array(),
|
||||
c_ispeed: input_speed,
|
||||
c_ospeed: output_speed,
|
||||
};
|
||||
// Ensure that our input and output speeds are set, as `libc`
|
||||
// routines don't always support setting these separately.
|
||||
termios2.c_cflag &= !CBAUD;
|
||||
termios2.c_cflag |= speed::encode(output_speed).unwrap_or(BOTHER);
|
||||
termios2.c_cflag &= !(CBAUD << IBSHIFT);
|
||||
termios2.c_cflag |= speed::encode(input_speed).unwrap_or(BOTHER) << IBSHIFT;
|
||||
let nccs = termios2.c_cc.len();
|
||||
termios2
|
||||
.c_cc
|
||||
.copy_from_slice(&termios.special_codes.0[..nccs]);
|
||||
|
||||
unsafe { ret(c::ioctl(borrowed_fd(fd), request as _, &termios2)) }
|
||||
}
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
unsafe {
|
||||
ret(c::tcsetattr(
|
||||
borrowed_fd(fd),
|
||||
optional_actions as _,
|
||||
crate::utils::as_ptr(termios).cast(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcsendbreak(fd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe { ret(c::tcsendbreak(borrowed_fd(fd), 0)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
pub(crate) fn tcdrain(fd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe { ret(c::tcdrain(borrowed_fd(fd))) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
pub(crate) fn tcflush(fd: BorrowedFd<'_>, queue_selector: QueueSelector) -> io::Result<()> {
|
||||
unsafe { ret(c::tcflush(borrowed_fd(fd), queue_selector as _)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
pub(crate) fn tcflow(fd: BorrowedFd<'_>, action: Action) -> io::Result<()> {
|
||||
unsafe { ret(c::tcflow(borrowed_fd(fd), action as _)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcgetsid(fd: BorrowedFd<'_>) -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pid = ret_pid_t(c::tcgetsid(borrowed_fd(fd)))?;
|
||||
Ok(Pid::from_raw_unchecked(pid))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
pub(crate) fn tcsetwinsize(fd: BorrowedFd<'_>, winsize: Winsize) -> io::Result<()> {
|
||||
unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCSWINSZ, &winsize)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "nto", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn set_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> {
|
||||
#[cfg(bsd)]
|
||||
let encoded_speed = arbitrary_speed;
|
||||
|
||||
#[cfg(not(bsd))]
|
||||
let encoded_speed = match crate::termios::speed::encode(arbitrary_speed) {
|
||||
Some(encoded_speed) => encoded_speed,
|
||||
#[cfg(linux_kernel)]
|
||||
None => c::BOTHER,
|
||||
#[cfg(not(linux_kernel))]
|
||||
None => return Err(io::Errno::INVAL),
|
||||
};
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
unsafe {
|
||||
ret(c::cfsetspeed(
|
||||
as_mut_ptr(termios).cast(),
|
||||
encoded_speed.into(),
|
||||
))
|
||||
}
|
||||
|
||||
// Linux libc implementations don't support arbitrary speeds, so we encode
|
||||
// the speed manually.
|
||||
#[cfg(linux_kernel)]
|
||||
{
|
||||
use crate::termios::ControlModes;
|
||||
|
||||
debug_assert_eq!(encoded_speed & !c::CBAUD, 0);
|
||||
|
||||
termios.control_modes -= ControlModes::from_bits_retain(c::CBAUD | c::CIBAUD);
|
||||
termios.control_modes |=
|
||||
ControlModes::from_bits_retain(encoded_speed | (encoded_speed << c::IBSHIFT));
|
||||
|
||||
termios.input_speed = arbitrary_speed;
|
||||
termios.output_speed = arbitrary_speed;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn set_output_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> {
|
||||
#[cfg(bsd)]
|
||||
let encoded_speed = arbitrary_speed;
|
||||
|
||||
#[cfg(not(bsd))]
|
||||
let encoded_speed = match crate::termios::speed::encode(arbitrary_speed) {
|
||||
Some(encoded_speed) => encoded_speed,
|
||||
#[cfg(linux_kernel)]
|
||||
None => c::BOTHER,
|
||||
#[cfg(not(linux_kernel))]
|
||||
None => return Err(io::Errno::INVAL),
|
||||
};
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
unsafe {
|
||||
ret(c::cfsetospeed(
|
||||
as_mut_ptr(termios).cast(),
|
||||
encoded_speed.into(),
|
||||
))
|
||||
}
|
||||
|
||||
// Linux libc implementations don't support arbitrary speeds or setting the
|
||||
// input and output speeds separately, so we encode the speed manually.
|
||||
#[cfg(linux_kernel)]
|
||||
{
|
||||
use crate::termios::ControlModes;
|
||||
|
||||
debug_assert_eq!(encoded_speed & !c::CBAUD, 0);
|
||||
|
||||
termios.control_modes -= ControlModes::from_bits_retain(c::CBAUD);
|
||||
termios.control_modes |= ControlModes::from_bits_retain(encoded_speed);
|
||||
|
||||
termios.output_speed = arbitrary_speed;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn set_input_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> {
|
||||
#[cfg(bsd)]
|
||||
let encoded_speed = arbitrary_speed;
|
||||
|
||||
#[cfg(not(bsd))]
|
||||
let encoded_speed = match crate::termios::speed::encode(arbitrary_speed) {
|
||||
Some(encoded_speed) => encoded_speed,
|
||||
#[cfg(linux_kernel)]
|
||||
None => c::BOTHER,
|
||||
#[cfg(not(linux_kernel))]
|
||||
None => return Err(io::Errno::INVAL),
|
||||
};
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
unsafe {
|
||||
ret(c::cfsetispeed(
|
||||
as_mut_ptr(termios).cast(),
|
||||
encoded_speed.into(),
|
||||
))
|
||||
}
|
||||
|
||||
// Linux libc implementations don't support arbitrary speeds or setting the
|
||||
// input and output speeds separately, so we encode the speed manually.
|
||||
#[cfg(linux_kernel)]
|
||||
{
|
||||
use crate::termios::ControlModes;
|
||||
|
||||
debug_assert_eq!(encoded_speed & !c::CBAUD, 0);
|
||||
|
||||
termios.control_modes -= ControlModes::from_bits_retain(c::CIBAUD);
|
||||
termios.control_modes |= ControlModes::from_bits_retain(encoded_speed << c::IBSHIFT);
|
||||
|
||||
termios.input_speed = arbitrary_speed;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "nto", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn cfmakeraw(termios: &mut Termios) {
|
||||
unsafe { c::cfmakeraw(as_mut_ptr(termios).cast()) }
|
||||
}
|
||||
|
||||
pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool {
|
||||
// Use the return value of `isatty` alone. We don't check `errno` because
|
||||
// we return `bool` rather than `io::Result<bool>`, because we assume
|
||||
// `BorrowedFd` protects us from `EBADF`, and any other reasonably
|
||||
// anticipated `errno` value would end up interpreted as “assume it's not a
|
||||
// terminal” anyway.
|
||||
unsafe { c::isatty(borrowed_fd(fd)) != 0 }
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "alloc", feature = "procfs"))]
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
pub(crate) fn ttyname(dirfd: BorrowedFd<'_>, buf: &mut [MaybeUninit<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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
43
third-party/vendor/rustix/src/backend/libc/thread/futex.rs
vendored
Normal file
43
third-party/vendor/rustix/src/backend/libc/thread/futex.rs
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
use crate::backend::c;
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// `FUTEX_*` flags for use with [`futex`].
|
||||
///
|
||||
/// [`futex`]: crate::thread::futex
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct FutexFlags: u32 {
|
||||
/// `FUTEX_PRIVATE_FLAG`
|
||||
const PRIVATE = bitcast!(c::FUTEX_PRIVATE_FLAG);
|
||||
/// `FUTEX_CLOCK_REALTIME`
|
||||
const CLOCK_REALTIME = bitcast!(c::FUTEX_CLOCK_REALTIME);
|
||||
}
|
||||
}
|
||||
|
||||
/// `FUTEX_*` operations for use with [`futex`].
|
||||
///
|
||||
/// [`futex`]: crate::thread::futex
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[repr(u32)]
|
||||
pub enum FutexOperation {
|
||||
/// `FUTEX_WAIT`
|
||||
Wait = bitcast!(c::FUTEX_WAIT),
|
||||
/// `FUTEX_WAKE`
|
||||
Wake = bitcast!(c::FUTEX_WAKE),
|
||||
/// `FUTEX_FD`
|
||||
Fd = bitcast!(c::FUTEX_FD),
|
||||
/// `FUTEX_REQUEUE`
|
||||
Requeue = bitcast!(c::FUTEX_REQUEUE),
|
||||
/// `FUTEX_CMP_REQUEUE`
|
||||
CmpRequeue = bitcast!(c::FUTEX_CMP_REQUEUE),
|
||||
/// `FUTEX_WAKE_OP`
|
||||
WakeOp = bitcast!(c::FUTEX_WAKE_OP),
|
||||
/// `FUTEX_LOCK_PI`
|
||||
LockPi = bitcast!(c::FUTEX_LOCK_PI),
|
||||
/// `FUTEX_UNLOCK_PI`
|
||||
UnlockPi = bitcast!(c::FUTEX_UNLOCK_PI),
|
||||
/// `FUTEX_TRYLOCK_PI`
|
||||
TrylockPi = bitcast!(c::FUTEX_TRYLOCK_PI),
|
||||
/// `FUTEX_WAIT_BITSET`
|
||||
WaitBitset = bitcast!(c::FUTEX_WAIT_BITSET),
|
||||
}
|
||||
4
third-party/vendor/rustix/src/backend/libc/thread/mod.rs
vendored
Normal file
4
third-party/vendor/rustix/src/backend/libc/thread/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#[cfg(linux_kernel)]
|
||||
pub(crate) mod futex;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
523
third-party/vendor/rustix/src/backend/libc/thread/syscalls.rs
vendored
Normal file
523
third-party/vendor/rustix/src/backend/libc/thread/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,523 @@
|
|||
//! libc syscalls supporting `rustix::thread`.
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::ret;
|
||||
use crate::io;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use crate::thread::{NanosleepRelativeResult, Timespec};
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
use crate::timespec::LibcTimespec;
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(linux_kernel)]
|
||||
use {
|
||||
crate::backend::conv::{borrowed_fd, ret_c_int, ret_usize},
|
||||
crate::fd::BorrowedFd,
|
||||
crate::pid::Pid,
|
||||
crate::thread::{FutexFlags, FutexOperation},
|
||||
crate::utils::as_mut_ptr,
|
||||
};
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
freebsdlike,
|
||||
target_os = "emscripten",
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
use {crate::thread::ClockId, core::ptr::null_mut};
|
||||
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
weak!(fn __clock_nanosleep_time64(c::clockid_t, c::c_int, *const LibcTimespec, *mut LibcTimespec) -> c::c_int);
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
weak!(fn __nanosleep64(*const LibcTimespec, *mut LibcTimespec) -> c::c_int);
|
||||
|
||||
#[cfg(not(any(
|
||||
apple,
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "espidf",
|
||||
target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
|
||||
target_os = "haiku",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
|
||||
// Old 32-bit version: libc has `clock_nanosleep` but it is not y2038 safe
|
||||
// by default. But there may be a `__clock_nanosleep_time64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
|
||||
let flags = 0;
|
||||
let mut remain = MaybeUninit::<LibcTimespec>::uninit();
|
||||
|
||||
unsafe {
|
||||
return 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)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
clock_nanosleep_relative_old(id, request)
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `clock_nanosleep`.
|
||||
#[cfg(not(fix_y2038))]
|
||||
unsafe {
|
||||
let flags = 0;
|
||||
let mut remain = MaybeUninit::<Timespec>::uninit();
|
||||
|
||||
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(
|
||||
fix_y2038,
|
||||
not(any(
|
||||
apple,
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku",
|
||||
target_os = "vita"
|
||||
))
|
||||
))]
|
||||
fn clock_nanosleep_relative_old(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
|
||||
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;
|
||||
|
||||
unsafe {
|
||||
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(
|
||||
apple,
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "espidf",
|
||||
target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
|
||||
target_os = "haiku",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "vita",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::Result<()> {
|
||||
// Old 32-bit version: libc has `clock_nanosleep` but it is not y2038 safe
|
||||
// by default. But there may be a `__clock_nanosleep_time64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
|
||||
let flags = c::TIMER_ABSTIME;
|
||||
unsafe {
|
||||
return match {
|
||||
libc_clock_nanosleep(
|
||||
id as c::clockid_t,
|
||||
flags,
|
||||
&request.clone().into(),
|
||||
null_mut(),
|
||||
)
|
||||
} {
|
||||
0 => Ok(()),
|
||||
err => Err(io::Errno(err)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
clock_nanosleep_absolute_old(id, request)
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `clock_nanosleep`.
|
||||
#[cfg(not(fix_y2038))]
|
||||
{
|
||||
let flags = c::TIMER_ABSTIME;
|
||||
|
||||
match unsafe { c::clock_nanosleep(id as c::clockid_t, flags as _, request, null_mut()) } {
|
||||
0 => Ok(()),
|
||||
err => Err(io::Errno(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
fix_y2038,
|
||||
not(any(
|
||||
apple,
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku",
|
||||
target_os = "vita"
|
||||
))
|
||||
))]
|
||||
fn clock_nanosleep_absolute_old(id: ClockId, request: &Timespec) -> io::Result<()> {
|
||||
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 {
|
||||
// Old 32-bit version: libc has `nanosleep` but it is not y2038 safe by
|
||||
// default. But there may be a `__nanosleep64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_nanosleep) = __nanosleep64.get() {
|
||||
let mut remain = MaybeUninit::<LibcTimespec>::uninit();
|
||||
unsafe {
|
||||
return 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),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
nanosleep_old(request)
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `nanosleep`.
|
||||
#[cfg(not(fix_y2038))]
|
||||
unsafe {
|
||||
let mut remain = MaybeUninit::<Timespec>::uninit();
|
||||
|
||||
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(fix_y2038)]
|
||||
fn nanosleep_old(request: &Timespec) -> NanosleepRelativeResult {
|
||||
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();
|
||||
|
||||
unsafe {
|
||||
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(linux_kernel)]
|
||||
#[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();
|
||||
Pid::from_raw_unchecked(tid)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn setns(fd: BorrowedFd<'_>, nstype: c::c_int) -> io::Result<c::c_int> {
|
||||
// `setns` wasn't supported in glibc until 2.14, and musl until 0.9.5,
|
||||
// so use `syscall`.
|
||||
weak_or_syscall! {
|
||||
fn setns(fd: c::c_int, nstype: c::c_int) via SYS_setns -> c::c_int
|
||||
}
|
||||
|
||||
unsafe { ret_c_int(setns(borrowed_fd(fd), nstype)) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
|
||||
unsafe { ret(c::unshare(flags.bits() as i32)) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn capget(
|
||||
header: &mut linux_raw_sys::general::__user_cap_header_struct,
|
||||
data: &mut [MaybeUninit<linux_raw_sys::general::__user_cap_data_struct>],
|
||||
) -> io::Result<()> {
|
||||
syscall! {
|
||||
fn capget(
|
||||
hdrp: *mut linux_raw_sys::general::__user_cap_header_struct,
|
||||
data: *mut linux_raw_sys::general::__user_cap_data_struct
|
||||
) via SYS_capget -> c::c_int
|
||||
}
|
||||
|
||||
unsafe {
|
||||
ret(capget(
|
||||
as_mut_ptr(header),
|
||||
data.as_mut_ptr()
|
||||
.cast::<linux_raw_sys::general::__user_cap_data_struct>(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn capset(
|
||||
header: &mut linux_raw_sys::general::__user_cap_header_struct,
|
||||
data: &[linux_raw_sys::general::__user_cap_data_struct],
|
||||
) -> io::Result<()> {
|
||||
syscall! {
|
||||
fn capset(
|
||||
hdrp: *mut linux_raw_sys::general::__user_cap_header_struct,
|
||||
data: *const linux_raw_sys::general::__user_cap_data_struct
|
||||
) via SYS_capset -> c::c_int
|
||||
}
|
||||
|
||||
unsafe { ret(capset(as_mut_ptr(header), data.as_ptr())) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn setuid_thread(uid: crate::ugid::Uid) -> io::Result<()> {
|
||||
syscall! {
|
||||
fn setuid(uid: c::uid_t) via SYS_setuid -> c::c_int
|
||||
}
|
||||
|
||||
unsafe { ret(setuid(uid.as_raw())) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn setresuid_thread(
|
||||
ruid: crate::ugid::Uid,
|
||||
euid: crate::ugid::Uid,
|
||||
suid: crate::ugid::Uid,
|
||||
) -> io::Result<()> {
|
||||
#[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))]
|
||||
const SYS: c::c_long = c::SYS_setresuid32 as c::c_long;
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))]
|
||||
const SYS: c::c_long = c::SYS_setresuid as c::c_long;
|
||||
|
||||
syscall! {
|
||||
fn setresuid(ruid: c::uid_t, euid: c::uid_t, suid: c::uid_t) via SYS -> c::c_int
|
||||
}
|
||||
|
||||
unsafe { ret(setresuid(ruid.as_raw(), euid.as_raw(), suid.as_raw())) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn setgid_thread(gid: crate::ugid::Gid) -> io::Result<()> {
|
||||
syscall! {
|
||||
fn setgid(gid: c::gid_t) via SYS_setgid -> c::c_int
|
||||
}
|
||||
|
||||
unsafe { ret(setgid(gid.as_raw())) }
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[inline]
|
||||
pub(crate) fn setresgid_thread(
|
||||
rgid: crate::ugid::Gid,
|
||||
egid: crate::ugid::Gid,
|
||||
sgid: crate::ugid::Gid,
|
||||
) -> io::Result<()> {
|
||||
#[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))]
|
||||
const SYS: c::c_long = c::SYS_setresgid32 as c::c_long;
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))]
|
||||
const SYS: c::c_long = c::SYS_setresgid as c::c_long;
|
||||
|
||||
syscall! {
|
||||
fn setresgid(rgid: c::gid_t, egid: c::gid_t, sgid: c::gid_t) via SYS -> c::c_int
|
||||
}
|
||||
|
||||
unsafe { ret(setresgid(rgid.as_raw(), egid.as_raw(), sgid.as_raw())) }
|
||||
}
|
||||
|
||||
// TODO: This could be de-multiplexed.
|
||||
#[cfg(linux_kernel)]
|
||||
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(all(
|
||||
target_pointer_width = "32",
|
||||
not(any(target_arch = "aarch64", target_arch = "x86_64"))
|
||||
))]
|
||||
{
|
||||
// TODO: Upstream this to the libc crate.
|
||||
#[allow(non_upper_case_globals)]
|
||||
const SYS_futex_time64: i32 = linux_raw_sys::general::__NR_futex_time64 as i32;
|
||||
|
||||
syscall! {
|
||||
fn futex_time64(
|
||||
uaddr: *mut u32,
|
||||
futex_op: c::c_int,
|
||||
val: u32,
|
||||
timeout: *const Timespec,
|
||||
uaddr2: *mut u32,
|
||||
val3: u32
|
||||
) via SYS_futex_time64 -> c::ssize_t
|
||||
}
|
||||
|
||||
ret_usize(futex_time64(
|
||||
uaddr,
|
||||
op as i32 | flags.bits() as i32,
|
||||
val,
|
||||
utime,
|
||||
uaddr2,
|
||||
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(any(
|
||||
target_pointer_width = "64",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "x86_64"
|
||||
))]
|
||||
{
|
||||
syscall! {
|
||||
fn futex(
|
||||
uaddr: *mut u32,
|
||||
futex_op: c::c_int,
|
||||
val: u32,
|
||||
timeout: *const linux_raw_sys::general::__kernel_timespec,
|
||||
uaddr2: *mut u32,
|
||||
val3: u32
|
||||
) via SYS_futex -> c::c_long
|
||||
}
|
||||
|
||||
ret_usize(futex(
|
||||
uaddr,
|
||||
op as i32 | flags.bits() as i32,
|
||||
val,
|
||||
utime.cast(),
|
||||
uaddr2,
|
||||
val3,
|
||||
) as isize)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
#[cfg(all(
|
||||
target_pointer_width = "32",
|
||||
not(any(target_arch = "aarch64", target_arch = "x86_64"))
|
||||
))]
|
||||
unsafe fn futex_old(
|
||||
uaddr: *mut u32,
|
||||
op: FutexOperation,
|
||||
flags: FutexFlags,
|
||||
val: u32,
|
||||
utime: *const Timespec,
|
||||
uaddr2: *mut u32,
|
||||
val3: u32,
|
||||
) -> io::Result<usize> {
|
||||
syscall! {
|
||||
fn futex(
|
||||
uaddr: *mut u32,
|
||||
futex_op: c::c_int,
|
||||
val: u32,
|
||||
timeout: *const linux_raw_sys::general::__kernel_old_timespec,
|
||||
uaddr2: *mut u32,
|
||||
val3: u32
|
||||
) via SYS_futex -> c::c_long
|
||||
}
|
||||
|
||||
let old_utime = linux_raw_sys::general::__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(futex(
|
||||
uaddr,
|
||||
op as i32 | flags.bits() as i32,
|
||||
val,
|
||||
&old_utime,
|
||||
uaddr2,
|
||||
val3,
|
||||
) as isize)
|
||||
}
|
||||
3
third-party/vendor/rustix/src/backend/libc/time/mod.rs
vendored
Normal file
3
third-party/vendor/rustix/src/backend/libc/time/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
452
third-party/vendor/rustix/src/backend/libc/time/syscalls.rs
vendored
Normal file
452
third-party/vendor/rustix/src/backend/libc/time/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,452 @@
|
|||
//! libc syscalls supporting `rustix::time`.
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::conv::ret;
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(feature = "time")]
|
||||
#[cfg(any(all(target_env = "gnu", fix_y2038), not(fix_y2038)))]
|
||||
use crate::backend::time::types::LibcItimerspec;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::clockid::{ClockId, DynamicClockId};
|
||||
use crate::io;
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
use crate::timespec::LibcTimespec;
|
||||
use crate::timespec::Timespec;
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(feature = "time")]
|
||||
use {
|
||||
crate::backend::conv::{borrowed_fd, ret_owned_fd},
|
||||
crate::fd::{BorrowedFd, OwnedFd},
|
||||
crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags},
|
||||
};
|
||||
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
weak!(fn __clock_gettime64(c::clockid_t, *mut LibcTimespec) -> c::c_int);
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
weak!(fn __clock_settime64(c::clockid_t, *const LibcTimespec) -> c::c_int);
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
weak!(fn __clock_getres64(c::clockid_t, *mut LibcTimespec) -> c::c_int);
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
#[cfg(feature = "time")]
|
||||
weak!(fn __timerfd_gettime64(c::c_int, *mut LibcItimerspec) -> c::c_int);
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(all(target_env = "gnu", fix_y2038))]
|
||||
#[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 {
|
||||
// Old 32-bit version: libc has `clock_getres` but it is not y2038 safe by
|
||||
// default. But there may be a `__clock_getres64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_clock_getres) = __clock_getres64.get() {
|
||||
let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
|
||||
unsafe {
|
||||
ret(libc_clock_getres(id as c::clockid_t, timespec.as_mut_ptr())).unwrap();
|
||||
return timespec.assume_init().into();
|
||||
}
|
||||
}
|
||||
|
||||
clock_getres_old(id)
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `clock_getres`.
|
||||
#[cfg(not(fix_y2038))]
|
||||
unsafe {
|
||||
let mut timespec = MaybeUninit::<Timespec>::uninit();
|
||||
let _ = c::clock_getres(id as c::clockid_t, timespec.as_mut_ptr());
|
||||
timespec.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(fix_y2038)]
|
||||
#[must_use]
|
||||
fn clock_getres_old(id: ClockId) -> Timespec {
|
||||
let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
|
||||
|
||||
let old_timespec = unsafe {
|
||||
ret(c::clock_getres(
|
||||
id as c::clockid_t,
|
||||
old_timespec.as_mut_ptr(),
|
||||
))
|
||||
.unwrap();
|
||||
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 {
|
||||
// Old 32-bit version: libc has `clock_gettime` but it is not y2038 safe by
|
||||
// default. But there may be a `__clock_gettime64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_clock_gettime) = __clock_gettime64.get() {
|
||||
let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
|
||||
unsafe {
|
||||
ret(libc_clock_gettime(
|
||||
id as c::clockid_t,
|
||||
timespec.as_mut_ptr(),
|
||||
))
|
||||
.unwrap();
|
||||
return timespec.assume_init().into();
|
||||
}
|
||||
}
|
||||
|
||||
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(fix_y2038))]
|
||||
unsafe {
|
||||
let mut timespec = MaybeUninit::<Timespec>::uninit();
|
||||
ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr())).unwrap();
|
||||
timespec.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(fix_y2038)]
|
||||
#[must_use]
|
||||
fn clock_gettime_old(id: ClockId) -> Timespec {
|
||||
let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
|
||||
|
||||
let old_timespec = unsafe {
|
||||
ret(c::clock_gettime(
|
||||
id as c::clockid_t,
|
||||
old_timespec.as_mut_ptr(),
|
||||
))
|
||||
.unwrap();
|
||||
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 id: c::clockid_t = match id {
|
||||
DynamicClockId::Known(id) => id as c::clockid_t,
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
DynamicClockId::Dynamic(fd) => {
|
||||
use crate::fd::AsRawFd;
|
||||
const CLOCKFD: i32 = 3;
|
||||
(!fd.as_raw_fd() << 3) | CLOCKFD
|
||||
}
|
||||
|
||||
#[cfg(not(linux_kernel))]
|
||||
DynamicClockId::Dynamic(_fd) => {
|
||||
// Dynamic clocks are not supported on this platform.
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
DynamicClockId::RealtimeAlarm => c::CLOCK_REALTIME_ALARM,
|
||||
|
||||
#[cfg(linux_kernel)]
|
||||
DynamicClockId::Tai => c::CLOCK_TAI,
|
||||
|
||||
#[cfg(any(
|
||||
linux_kernel,
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
DynamicClockId::Boottime => c::CLOCK_BOOTTIME,
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
DynamicClockId::BoottimeAlarm => c::CLOCK_BOOTTIME_ALARM,
|
||||
};
|
||||
|
||||
// Old 32-bit version: libc has `clock_gettime` but it is not y2038
|
||||
// safe by default. But there may be a `__clock_gettime64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_clock_gettime) = __clock_gettime64.get() {
|
||||
let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
|
||||
unsafe {
|
||||
ret(libc_clock_gettime(
|
||||
id as c::clockid_t,
|
||||
timespec.as_mut_ptr(),
|
||||
))?;
|
||||
|
||||
return Ok(timespec.assume_init().into());
|
||||
}
|
||||
}
|
||||
|
||||
clock_gettime_dynamic_old(id)
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `clock_gettime`.
|
||||
#[cfg(not(fix_y2038))]
|
||||
unsafe {
|
||||
let mut timespec = MaybeUninit::<Timespec>::uninit();
|
||||
|
||||
ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr()))?;
|
||||
|
||||
Ok(timespec.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(fix_y2038)]
|
||||
#[inline]
|
||||
fn clock_gettime_dynamic_old(id: c::clockid_t) -> io::Result<Timespec> {
|
||||
let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
|
||||
|
||||
let old_timespec = unsafe {
|
||||
ret(c::clock_gettime(
|
||||
id as c::clockid_t,
|
||||
old_timespec.as_mut_ptr(),
|
||||
))?;
|
||||
|
||||
old_timespec.assume_init()
|
||||
};
|
||||
|
||||
Ok(Timespec {
|
||||
tv_sec: old_timespec.tv_sec.into(),
|
||||
tv_nsec: old_timespec.tv_nsec.into(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
all(apple, not(target_os = "macos"))
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn clock_settime(id: ClockId, timespec: Timespec) -> io::Result<()> {
|
||||
// Old 32-bit version: libc has `clock_gettime` but it is not y2038 safe by
|
||||
// default. But there may be a `__clock_settime64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_clock_settime) = __clock_settime64.get() {
|
||||
unsafe {
|
||||
let mut new_timespec = core::mem::zeroed::<LibcTimespec>();
|
||||
new_timespec.tv_sec = timespec.tv_sec;
|
||||
new_timespec.tv_nsec = timespec.tv_nsec as _;
|
||||
return ret(libc_clock_settime(id as c::clockid_t, &new_timespec));
|
||||
}
|
||||
}
|
||||
|
||||
clock_settime_old(id, timespec)
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `clock_settime`.
|
||||
#[cfg(not(fix_y2038))]
|
||||
unsafe {
|
||||
ret(c::clock_settime(id as c::clockid_t, ×pec))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
all(apple, not(target_os = "macos"))
|
||||
)))]
|
||||
#[cfg(fix_y2038)]
|
||||
fn clock_settime_old(id: ClockId, timespec: Timespec) -> io::Result<()> {
|
||||
let old_timespec = c::timespec {
|
||||
tv_sec: timespec
|
||||
.tv_sec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
tv_nsec: timespec.tv_nsec as _,
|
||||
};
|
||||
|
||||
unsafe { ret(c::clock_settime(id as c::clockid_t, &old_timespec)) }
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[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, bitflags_bits!(flags))) }
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(feature = "time")]
|
||||
pub(crate) fn timerfd_settime(
|
||||
fd: BorrowedFd<'_>,
|
||||
flags: TimerfdTimerFlags,
|
||||
new_value: &Itimerspec,
|
||||
) -> io::Result<Itimerspec> {
|
||||
// Old 32-bit version: libc has `timerfd_settime` but it is not y2038 safe
|
||||
// by default. But there may be a `__timerfd_settime64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_timerfd_settime) = __timerfd_settime64.get() {
|
||||
let mut result = MaybeUninit::<LibcItimerspec>::uninit();
|
||||
unsafe {
|
||||
ret(libc_timerfd_settime(
|
||||
borrowed_fd(fd),
|
||||
bitflags_bits!(flags),
|
||||
&new_value.clone().into(),
|
||||
result.as_mut_ptr(),
|
||||
))?;
|
||||
return Ok(result.assume_init().into());
|
||||
}
|
||||
}
|
||||
|
||||
timerfd_settime_old(fd, flags, new_value)
|
||||
}
|
||||
|
||||
#[cfg(not(fix_y2038))]
|
||||
unsafe {
|
||||
let mut result = MaybeUninit::<LibcItimerspec>::uninit();
|
||||
ret(c::timerfd_settime(
|
||||
borrowed_fd(fd),
|
||||
bitflags_bits!(flags),
|
||||
new_value,
|
||||
result.as_mut_ptr(),
|
||||
))?;
|
||||
Ok(result.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(fix_y2038)]
|
||||
#[cfg(feature = "time")]
|
||||
fn timerfd_settime_old(
|
||||
fd: BorrowedFd<'_>,
|
||||
flags: TimerfdTimerFlags,
|
||||
new_value: &Itimerspec,
|
||||
) -> io::Result<Itimerspec> {
|
||||
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)?,
|
||||
},
|
||||
};
|
||||
|
||||
let old_result = unsafe {
|
||||
ret(c::timerfd_settime(
|
||||
borrowed_fd(fd),
|
||||
bitflags_bits!(flags),
|
||||
&old_new_value,
|
||||
old_result.as_mut_ptr(),
|
||||
))?;
|
||||
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(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(feature = "time")]
|
||||
pub(crate) fn timerfd_gettime(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
|
||||
// Old 32-bit version: libc has `timerfd_gettime` but it is not y2038 safe
|
||||
// by default. But there may be a `__timerfd_gettime64` we can use.
|
||||
#[cfg(fix_y2038)]
|
||||
{
|
||||
#[cfg(target_env = "gnu")]
|
||||
if let Some(libc_timerfd_gettime) = __timerfd_gettime64.get() {
|
||||
let mut result = MaybeUninit::<LibcItimerspec>::uninit();
|
||||
unsafe {
|
||||
ret(libc_timerfd_gettime(borrowed_fd(fd), result.as_mut_ptr()))?;
|
||||
return Ok(result.assume_init().into());
|
||||
}
|
||||
}
|
||||
|
||||
timerfd_gettime_old(fd)
|
||||
}
|
||||
|
||||
#[cfg(not(fix_y2038))]
|
||||
unsafe {
|
||||
let mut result = MaybeUninit::<LibcItimerspec>::uninit();
|
||||
ret(c::timerfd_gettime(borrowed_fd(fd), result.as_mut_ptr()))?;
|
||||
Ok(result.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(fix_y2038)]
|
||||
#[cfg(feature = "time")]
|
||||
fn timerfd_gettime_old(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
|
||||
let mut old_result = MaybeUninit::<c::itimerspec>::uninit();
|
||||
|
||||
let old_result = unsafe {
|
||||
ret(c::timerfd_gettime(borrowed_fd(fd), old_result.as_mut_ptr()))?;
|
||||
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 _,
|
||||
},
|
||||
})
|
||||
}
|
||||
177
third-party/vendor/rustix/src/backend/libc/time/types.rs
vendored
Normal file
177
third-party/vendor/rustix/src/backend/libc/time/types.rs
vendored
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
use crate::backend::c;
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(fix_y2038)]
|
||||
use crate::timespec::LibcTimespec;
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(fix_y2038)]
|
||||
use crate::timespec::Timespec;
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// `struct itimerspec` for use with [`timerfd_gettime`] and
|
||||
/// [`timerfd_settime`].
|
||||
///
|
||||
/// [`timerfd_gettime`]: crate::time::timerfd_gettime
|
||||
/// [`timerfd_settime`]: crate::time::timerfd_settime
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(not(fix_y2038))]
|
||||
pub type Itimerspec = c::itimerspec;
|
||||
|
||||
/// `struct itimerspec` for use with [`timerfd_gettime`] and
|
||||
/// [`timerfd_settime`].
|
||||
///
|
||||
/// [`timerfd_gettime`]: crate::time::timerfd_gettime
|
||||
/// [`timerfd_settime`]: crate::time::timerfd_settime
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(fix_y2038)]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Itimerspec {
|
||||
/// The interval of an interval timer.
|
||||
pub it_interval: Timespec,
|
||||
/// Time remaining in the current interval.
|
||||
pub it_value: Timespec,
|
||||
}
|
||||
|
||||
/// On most platforms, `LibcItimerspec` is just `Itimerspec`.
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(not(fix_y2038))]
|
||||
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(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(fix_y2038)]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct LibcItimerspec {
|
||||
pub it_interval: LibcTimespec,
|
||||
pub it_value: LibcTimespec,
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(fix_y2038)]
|
||||
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(linux_kernel, target_os = "fuchsia"))]
|
||||
#[cfg(fix_y2038)]
|
||||
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(linux_kernel, target_os = "fuchsia"))]
|
||||
bitflags! {
|
||||
/// `TFD_*` flags for use with [`timerfd_create`].
|
||||
///
|
||||
/// [`timerfd_create`]: crate::time::timerfd_create
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct TimerfdFlags: u32 {
|
||||
/// `TFD_NONBLOCK`
|
||||
#[doc(alias = "TFD_NONBLOCK")]
|
||||
const NONBLOCK = bitcast!(c::TFD_NONBLOCK);
|
||||
|
||||
/// `TFD_CLOEXEC`
|
||||
#[doc(alias = "TFD_CLOEXEC")]
|
||||
const CLOEXEC = bitcast!(c::TFD_CLOEXEC);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
bitflags! {
|
||||
/// `TFD_TIMER_*` flags for use with [`timerfd_settime`].
|
||||
///
|
||||
/// [`timerfd_settime`]: crate::time::timerfd_settime
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct TimerfdTimerFlags: u32 {
|
||||
/// `TFD_TIMER_ABSTIME`
|
||||
#[doc(alias = "TFD_TIMER_ABSTIME")]
|
||||
const ABSTIME = bitcast!(c::TFD_TIMER_ABSTIME);
|
||||
|
||||
/// `TFD_TIMER_CANCEL_ON_SET`
|
||||
#[cfg(linux_kernel)]
|
||||
#[doc(alias = "TFD_TIMER_CANCEL_ON_SET")]
|
||||
const CANCEL_ON_SET = bitcast!(c::TFD_TIMER_CANCEL_ON_SET);
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `CLOCK_*` constants for use with [`timerfd_create`].
|
||||
///
|
||||
/// [`timerfd_create`]: crate::time::timerfd_create
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[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.
|
||||
#[doc(alias = "CLOCK_REALTIME")]
|
||||
Realtime = bitcast!(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.
|
||||
#[doc(alias = "CLOCK_MONOTONIC")]
|
||||
Monotonic = bitcast!(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.
|
||||
#[doc(alias = "CLOCK_BOOTTIME")]
|
||||
Boottime = bitcast!(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.
|
||||
#[doc(alias = "CLOCK_REALTIME_ALARM")]
|
||||
RealtimeAlarm = bitcast!(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.
|
||||
#[doc(alias = "CLOCK_BOOTTIME_ALARM")]
|
||||
BoottimeAlarm = bitcast!(c::CLOCK_BOOTTIME_ALARM),
|
||||
}
|
||||
|
||||
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
|
||||
#[test]
|
||||
fn test_types() {
|
||||
assert_eq_size!(TimerfdFlags, c::c_int);
|
||||
assert_eq_size!(TimerfdTimerFlags, c::c_int);
|
||||
}
|
||||
1
third-party/vendor/rustix/src/backend/libc/ugid/mod.rs
vendored
Normal file
1
third-party/vendor/rustix/src/backend/libc/ugid/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod syscalls;
|
||||
42
third-party/vendor/rustix/src/backend/libc/ugid/syscalls.rs
vendored
Normal file
42
third-party/vendor/rustix/src/backend/libc/ugid/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use crate::backend::c;
|
||||
use crate::ugid::{Gid, Uid};
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
59
third-party/vendor/rustix/src/backend/libc/winsock_c.rs
vendored
Normal file
59
third-party/vendor/rustix/src/backend/libc/winsock_c.rs
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//! Adapt the Winsock API to resemble a POSIX-style libc API.
|
||||
|
||||
#![allow(unused_imports)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use windows_sys::Win32::Networking::WinSock;
|
||||
|
||||
// Define the basic C types. With Rust 1.64, we can use these from `core::ffi`.
|
||||
pub(crate) type c_schar = i8;
|
||||
pub(crate) type c_uchar = u8;
|
||||
pub(crate) type c_short = i16;
|
||||
pub(crate) type c_ushort = u16;
|
||||
pub(crate) type c_int = i32;
|
||||
pub(crate) type c_uint = u32;
|
||||
pub(crate) type c_longlong = i64;
|
||||
pub(crate) type c_ulonglong = u64;
|
||||
pub(crate) type ssize_t = isize;
|
||||
pub(crate) type c_char = i8;
|
||||
pub(crate) type c_long = i32;
|
||||
pub(crate) type c_ulong = u32;
|
||||
pub(crate) use core::ffi::c_void;
|
||||
|
||||
// windows-sys declares these constants as u16. For better compatibility
|
||||
// with Unix-family APIs, redeclare them as u32.
|
||||
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 _;
|
||||
|
||||
// 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, LINGER as linger, SD_BOTH as SHUT_RDWR, SD_RECEIVE as SHUT_RD,
|
||||
SD_SEND as SHUT_WR, 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, *,
|
||||
};
|
||||
268
third-party/vendor/rustix/src/backend/linux_raw/arch/aarch64.rs
vendored
Normal file
268
third-party/vendor/rustix/src/backend/linux_raw/arch/aarch64.rs
vendored
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
//! aarch64 Linux system calls.
|
||||
|
||||
use crate::backend::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::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
in("x0") a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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)
|
||||
}
|
||||
265
third-party/vendor/rustix/src/backend/linux_raw/arch/arm.rs
vendored
Normal file
265
third-party/vendor/rustix/src/backend/linux_raw/arch/arm.rs
vendored
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
//! arm Linux system calls.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
in("r0") a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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)
|
||||
}
|
||||
543
third-party/vendor/rustix/src/backend/linux_raw/arch/mips.rs
vendored
Normal file
543
third-party/vendor/rustix/src/backend/linux_raw/arch/mips.rs
vendored
Normal file
|
|
@ -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::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, A6, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("$2" /*$v0*/) nr.to_asm(),
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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
|
||||
})
|
||||
}
|
||||
543
third-party/vendor/rustix/src/backend/linux_raw/arch/mips32r6.rs
vendored
Normal file
543
third-party/vendor/rustix/src/backend/linux_raw/arch/mips32r6.rs
vendored
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
//! mipsisa32r6el Linux system calls.
|
||||
//!
|
||||
//! On mipsisa32r6el, 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::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, A6, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("$2" /*$v0*/) nr.to_asm(),
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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
|
||||
})
|
||||
}
|
||||
466
third-party/vendor/rustix/src/backend/linux_raw/arch/mips64.rs
vendored
Normal file
466
third-party/vendor/rustix/src/backend/linux_raw/arch/mips64.rs
vendored
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
//! 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::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("$2" /*$v0*/) nr.to_asm(),
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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
|
||||
})
|
||||
}
|
||||
470
third-party/vendor/rustix/src/backend/linux_raw/arch/mips64r6.rs
vendored
Normal file
470
third-party/vendor/rustix/src/backend/linux_raw/arch/mips64r6.rs
vendored
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
//! mipsisa64r6el Linux system calls.
|
||||
//!
|
||||
//! On mipsisa64r6el, 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.
|
||||
//!
|
||||
//! Note that MIPS R6 inline assembly currently doesn't differ from MIPS,
|
||||
//! because no explicit call of R6-only or R2-only instructions exist here.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("$2" /*$v0*/) nr.to_asm(),
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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
|
||||
})
|
||||
}
|
||||
317
third-party/vendor/rustix/src/backend/linux_raw/arch/mod.rs
vendored
Normal file
317
third-party/vendor/rustix/src/backend/linux_raw/arch/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
//! Architecture-specific syscall code.
|
||||
//!
|
||||
//! This module also has a `choose` submodule which chooses a scheme and is
|
||||
//! what most of the `rustix` syscalls use.
|
||||
//!
|
||||
//! 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.
|
||||
//!
|
||||
//! The calling conventions for Linux syscalls are [documented here].
|
||||
//!
|
||||
//! [documented here]: https://man7.org/linux/man-pages/man2/syscall.2.html
|
||||
//!
|
||||
//! # Safety
|
||||
//!
|
||||
//! This contains the inline `asm` statements performing the syscall
|
||||
//! instructions.
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
#![cfg_attr(not(feature = "all-apis"), allow(unused_imports))]
|
||||
// We'll use as many arguments as syscalls need.
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
// These functions always use the machine's syscall instruction, even when it
|
||||
// isn't the fastest option available.
|
||||
#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
|
||||
#[cfg_attr(all(target_arch = "arm", not(thumb_mode)), path = "arm.rs")]
|
||||
#[cfg_attr(all(target_arch = "arm", thumb_mode), path = "thumb.rs")]
|
||||
#[cfg_attr(target_arch = "mips", path = "mips.rs")]
|
||||
#[cfg_attr(target_arch = "mips32r6", path = "mips32r6.rs")]
|
||||
#[cfg_attr(target_arch = "mips64", path = "mips64.rs")]
|
||||
#[cfg_attr(target_arch = "mips64r6", path = "mips64r6.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")]
|
||||
pub(in crate::backend) 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 = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "powerpc64",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "x86_64",
|
||||
))]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend::arch::choose::syscall0($crate::backend::reg::nr(
|
||||
linux_raw_sys::general::$nr,
|
||||
))
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr) => {
|
||||
$crate::backend::arch::choose::syscall1(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr) => {
|
||||
$crate::backend::arch::choose::syscall2(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
|
||||
$crate::backend::arch::choose::syscall3(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
|
||||
$crate::backend::arch::choose::syscall4(
|
||||
$crate::backend::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::backend::arch::choose::syscall5(
|
||||
$crate::backend::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::backend::arch::choose::syscall6(
|
||||
$crate::backend::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::backend::arch::choose::syscall7(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
$a5.into(),
|
||||
$a6.into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
// Macro to invoke a syscall that always uses direct assembly, rather than the
|
||||
// vDSO. Useful when still finding the vDSO.
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! syscall_always_asm {
|
||||
($nr:ident) => {
|
||||
$crate::backend::arch::asm::syscall0($crate::backend::reg::nr(linux_raw_sys::general::$nr))
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr) => {
|
||||
$crate::backend::arch::asm::syscall1(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr) => {
|
||||
$crate::backend::arch::asm::syscall2(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
|
||||
$crate::backend::arch::asm::syscall3(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
|
||||
$crate::backend::arch::asm::syscall4(
|
||||
$crate::backend::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::backend::arch::asm::syscall5(
|
||||
$crate::backend::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::backend::arch::asm::syscall6(
|
||||
$crate::backend::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::backend::arch::asm::syscall7(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
$a5.into(),
|
||||
$a6.into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
/// Like `syscall`, but adds the `readonly` attribute to the inline asm, which
|
||||
/// indicates that the syscall does not mutate any memory.
|
||||
macro_rules! syscall_readonly {
|
||||
($nr:ident) => {
|
||||
$crate::backend::arch::choose::syscall0_readonly($crate::backend::reg::nr(
|
||||
linux_raw_sys::general::$nr,
|
||||
))
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr) => {
|
||||
$crate::backend::arch::choose::syscall1_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr) => {
|
||||
$crate::backend::arch::choose::syscall2_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
|
||||
$crate::backend::arch::choose::syscall3_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
|
||||
$crate::backend::arch::choose::syscall4_readonly(
|
||||
$crate::backend::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::backend::arch::choose::syscall5_readonly(
|
||||
$crate::backend::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::backend::arch::choose::syscall6_readonly(
|
||||
$crate::backend::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::backend::arch::choose::syscall7_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
$a5.into(),
|
||||
$a6.into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
/// Like `syscall`, but indicates that the syscall does not return.
|
||||
#[cfg(feature = "runtime")]
|
||||
macro_rules! syscall_noreturn {
|
||||
($nr:ident, $a0:expr) => {
|
||||
$crate::backend::arch::choose::syscall1_noreturn(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
413
third-party/vendor/rustix/src/backend/linux_raw/arch/powerpc64.rs
vendored
Normal file
413
third-party/vendor/rustix/src/backend/linux_raw/arch/powerpc64.rs
vendored
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
//! 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::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"sc",
|
||||
in("r0") nr.to_asm(),
|
||||
in("r3") a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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)
|
||||
}
|
||||
265
third-party/vendor/rustix/src/backend/linux_raw/arch/riscv64.rs
vendored
Normal file
265
third-party/vendor/rustix/src/backend/linux_raw/arch/riscv64.rs
vendored
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
//! riscv64 Linux system calls.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
in("a0") a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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)
|
||||
}
|
||||
322
third-party/vendor/rustix/src/backend/linux_raw/arch/thumb.rs
vendored
Normal file
322
third-party/vendor/rustix/src/backend/linux_raw/arch/thumb.rs
vendored
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
//! arm Linux system calls, using thumb-mode.
|
||||
//!
|
||||
//! In thumb-mode, r7 is the frame pointer and is not permitted to be used in
|
||||
//! an inline asm operand, so we have to use a different register and copy it
|
||||
//! into r7 inside the inline asm.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
lateout("r0") r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
in("r0") a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
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::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
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::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
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::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
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::backend) 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!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
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::backend) 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!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
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::backend) 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!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
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::backend) 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!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
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)
|
||||
}
|
||||
489
third-party/vendor/rustix/src/backend/linux_raw/arch/x86.rs
vendored
Normal file
489
third-party/vendor/rustix/src/backend/linux_raw/arch/x86.rs
vendored
Normal file
|
|
@ -0,0 +1,489 @@
|
|||
//! 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, as vsyscall is much faster.
|
||||
//!
|
||||
//! Syscalls made with `int 0x80` preserve the flags register, while syscalls
|
||||
//! made using vsyscall do not.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use crate::backend::vdso_wrappers::SyscallType;
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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,
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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(),
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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(),
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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(),
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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(),
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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 [eax + 0]",
|
||||
"mov esi, [eax + 4]",
|
||||
"mov eax, [eax + 8]",
|
||||
"call [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(),
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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 [eax + 0]",
|
||||
"mov esi, [eax + 4]",
|
||||
"mov ebp, [eax + 8]",
|
||||
"mov eax, [eax + 12]",
|
||||
"call [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(),
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
in("eax") nr.to_asm(),
|
||||
in("ebx") a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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, [eax + 0]",
|
||||
"mov ebp, [eax + 4]",
|
||||
"mov eax, [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::backend) 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, [eax + 0]",
|
||||
"mov ebp, [eax + 4]",
|
||||
"mov eax, [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)
|
||||
}
|
||||
293
third-party/vendor/rustix/src/backend/linux_raw/arch/x86_64.rs
vendored
Normal file
293
third-party/vendor/rustix/src/backend/linux_raw/arch/x86_64.rs
vendored
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
//! x86-64 Linux system calls.
|
||||
|
||||
use crate::backend::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::backend) 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::backend) 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::backend) 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::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("rax") nr.to_asm(),
|
||||
in("rdi") a0.to_asm(),
|
||||
options(nostack, noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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)
|
||||
}
|
||||
319
third-party/vendor/rustix/src/backend/linux_raw/c.rs
vendored
Normal file
319
third-party/vendor/rustix/src/backend/linux_raw/c.rs
vendored
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
//! 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)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
pub(crate) type size_t = usize;
|
||||
pub(crate) use linux_raw_sys::ctypes::*;
|
||||
pub(crate) use linux_raw_sys::errno::EINVAL;
|
||||
pub(crate) use linux_raw_sys::ioctl::{FIONBIO, FIONREAD};
|
||||
// Import the kernel's `uid_t` and `gid_t` if they're 32-bit.
|
||||
#[cfg(not(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86")))]
|
||||
pub(crate) use linux_raw_sys::general::{__kernel_gid_t as gid_t, __kernel_uid_t as uid_t};
|
||||
pub(crate) use linux_raw_sys::general::{
|
||||
__kernel_pid_t as pid_t, __kernel_time64_t as time_t, __kernel_timespec as timespec, iovec,
|
||||
O_CLOEXEC, O_NOCTTY, O_NONBLOCK, O_RDWR,
|
||||
};
|
||||
|
||||
#[cfg(feature = "event")]
|
||||
#[cfg(test)]
|
||||
pub(crate) use linux_raw_sys::general::epoll_event;
|
||||
|
||||
#[cfg(any(
|
||||
feature = "fs",
|
||||
all(
|
||||
not(feature = "use-libc-auxv"),
|
||||
not(feature = "use-explicitly-provided-auxv"),
|
||||
any(
|
||||
feature = "param",
|
||||
feature = "process",
|
||||
feature = "runtime",
|
||||
feature = "time",
|
||||
target_arch = "x86",
|
||||
)
|
||||
)
|
||||
))]
|
||||
pub(crate) use linux_raw_sys::general::{
|
||||
AT_FDCWD, NFS_SUPER_MAGIC, O_LARGEFILE, PROC_SUPER_MAGIC, UTIME_NOW, UTIME_OMIT, XATTR_CREATE,
|
||||
XATTR_REPLACE,
|
||||
};
|
||||
|
||||
pub(crate) use linux_raw_sys::ioctl::{BLKPBSZGET, BLKSSZGET, FICLONE};
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub(crate) use linux_raw_sys::ioctl::{FS_IOC32_GETFLAGS, FS_IOC32_SETFLAGS};
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub(crate) use linux_raw_sys::ioctl::{FS_IOC_GETFLAGS, FS_IOC_SETFLAGS};
|
||||
|
||||
#[cfg(feature = "io_uring")]
|
||||
pub(crate) use linux_raw_sys::{general::open_how, io_uring::*};
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) use linux_raw_sys::{
|
||||
cmsg_macros::*,
|
||||
general::{O_CLOEXEC as SOCK_CLOEXEC, O_NONBLOCK as SOCK_NONBLOCK},
|
||||
if_ether::*,
|
||||
net::{
|
||||
linger, msghdr, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, socklen_t, AF_DECnet,
|
||||
__kernel_sa_family_t as sa_family_t, __kernel_sockaddr_storage as sockaddr_storage,
|
||||
cmsghdr, in6_addr, in_addr, ip_mreq, ip_mreq_source, ip_mreqn, ipv6_mreq, 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, AF_XDP,
|
||||
IP6T_SO_ORIGINAL_DST, IPPROTO_FRAGMENT, IPPROTO_ICMPV6, IPPROTO_MH, IPPROTO_ROUTING,
|
||||
IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_FREEBIND, IPV6_MULTICAST_HOPS,
|
||||
IPV6_MULTICAST_LOOP, IPV6_RECVTCLASS, IPV6_TCLASS, IPV6_UNICAST_HOPS, IPV6_V6ONLY,
|
||||
IP_ADD_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP,
|
||||
IP_FREEBIND, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_RECVTOS, IP_TOS, 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, SCM_CREDENTIALS,
|
||||
SCM_RIGHTS, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET,
|
||||
SOCK_STREAM, SOL_SOCKET, SOL_XDP, SO_ACCEPTCONN, SO_BROADCAST, SO_COOKIE, SO_DOMAIN,
|
||||
SO_ERROR, SO_INCOMING_CPU, SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE, SO_ORIGINAL_DST,
|
||||
SO_PASSCRED, SO_PROTOCOL, SO_RCVBUF, SO_RCVTIMEO_NEW, SO_RCVTIMEO_NEW as SO_RCVTIMEO,
|
||||
SO_RCVTIMEO_OLD, SO_REUSEADDR, SO_REUSEPORT, SO_SNDBUF, SO_SNDTIMEO_NEW,
|
||||
SO_SNDTIMEO_NEW as SO_SNDTIMEO, SO_SNDTIMEO_OLD, SO_TYPE, TCP_CONGESTION, TCP_CORK,
|
||||
TCP_KEEPCNT, TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_NODELAY, TCP_QUICKACK,
|
||||
TCP_THIN_LINEAR_TIMEOUTS, TCP_USER_TIMEOUT,
|
||||
},
|
||||
netlink::*,
|
||||
xdp::{
|
||||
sockaddr_xdp, xdp_desc, xdp_mmap_offsets, xdp_mmap_offsets_v1, xdp_options,
|
||||
xdp_ring_offset, xdp_ring_offset_v1, xdp_statistics, xdp_statistics_v1, xdp_umem_reg,
|
||||
xdp_umem_reg_v1, XDP_COPY, XDP_MMAP_OFFSETS, XDP_OPTIONS, XDP_OPTIONS_ZEROCOPY,
|
||||
XDP_PGOFF_RX_RING, XDP_PGOFF_TX_RING, XDP_PKT_CONTD, XDP_RING_NEED_WAKEUP, XDP_RX_RING,
|
||||
XDP_SHARED_UMEM, XDP_STATISTICS, XDP_TX_RING, XDP_UMEM_COMPLETION_RING, XDP_UMEM_FILL_RING,
|
||||
XDP_UMEM_PGOFF_COMPLETION_RING, XDP_UMEM_PGOFF_FILL_RING, XDP_UMEM_REG,
|
||||
XDP_UMEM_UNALIGNED_CHUNK_FLAG, XDP_USE_NEED_WAKEUP, XDP_USE_SG, XDP_ZEROCOPY,
|
||||
XSK_UNALIGNED_BUF_ADDR_MASK, XSK_UNALIGNED_BUF_OFFSET_SHIFT,
|
||||
},
|
||||
};
|
||||
|
||||
// Cast away bindgen's `enum` type to make these consistent with the other
|
||||
// `setsockopt`/`getsockopt` level values.
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_IP: u32 = linux_raw_sys::net::IPPROTO_IP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_ICMP: u32 = linux_raw_sys::net::IPPROTO_ICMP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_IGMP: u32 = linux_raw_sys::net::IPPROTO_IGMP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_IPIP: u32 = linux_raw_sys::net::IPPROTO_IPIP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_TCP: u32 = linux_raw_sys::net::IPPROTO_TCP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_EGP: u32 = linux_raw_sys::net::IPPROTO_EGP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_PUP: u32 = linux_raw_sys::net::IPPROTO_PUP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_UDP: u32 = linux_raw_sys::net::IPPROTO_UDP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_IDP: u32 = linux_raw_sys::net::IPPROTO_IDP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_TP: u32 = linux_raw_sys::net::IPPROTO_TP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_DCCP: u32 = linux_raw_sys::net::IPPROTO_DCCP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_IPV6: u32 = linux_raw_sys::net::IPPROTO_IPV6 as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_RSVP: u32 = linux_raw_sys::net::IPPROTO_RSVP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_GRE: u32 = linux_raw_sys::net::IPPROTO_GRE as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_ESP: u32 = linux_raw_sys::net::IPPROTO_ESP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_AH: u32 = linux_raw_sys::net::IPPROTO_AH as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_MTP: u32 = linux_raw_sys::net::IPPROTO_MTP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_BEETPH: u32 = linux_raw_sys::net::IPPROTO_BEETPH as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_ENCAP: u32 = linux_raw_sys::net::IPPROTO_ENCAP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_PIM: u32 = linux_raw_sys::net::IPPROTO_PIM as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_COMP: u32 = linux_raw_sys::net::IPPROTO_COMP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_SCTP: u32 = linux_raw_sys::net::IPPROTO_SCTP as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_UDPLITE: u32 = linux_raw_sys::net::IPPROTO_UDPLITE as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_MPLS: u32 = linux_raw_sys::net::IPPROTO_MPLS as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_ETHERNET: u32 = linux_raw_sys::net::IPPROTO_ETHERNET as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_RAW: u32 = linux_raw_sys::net::IPPROTO_RAW as _;
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) const IPPROTO_MPTCP: u32 = linux_raw_sys::net::IPPROTO_MPTCP as _;
|
||||
|
||||
#[cfg(any(feature = "process", feature = "runtime"))]
|
||||
pub(crate) use linux_raw_sys::general::siginfo_t;
|
||||
|
||||
#[cfg(any(feature = "process", feature = "runtime"))]
|
||||
pub(crate) const EXIT_SUCCESS: c_int = 0;
|
||||
#[cfg(any(feature = "process", feature = "runtime"))]
|
||||
pub(crate) const EXIT_FAILURE: c_int = 1;
|
||||
#[cfg(feature = "process")]
|
||||
pub(crate) const EXIT_SIGNALED_SIGABRT: c_int = 128 + linux_raw_sys::general::SIGABRT as c_int;
|
||||
#[cfg(feature = "runtime")]
|
||||
pub(crate) const CLONE_CHILD_SETTID: c_int = linux_raw_sys::general::CLONE_CHILD_SETTID as c_int;
|
||||
|
||||
#[cfg(feature = "process")]
|
||||
pub(crate) use linux_raw_sys::{
|
||||
general::{
|
||||
CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, CLD_TRAPPED,
|
||||
O_NONBLOCK as PIDFD_NONBLOCK, P_ALL, P_PGID, P_PID, P_PIDFD,
|
||||
},
|
||||
ioctl::TIOCSCTTY,
|
||||
};
|
||||
|
||||
#[cfg(feature = "pty")]
|
||||
pub(crate) use linux_raw_sys::ioctl::TIOCGPTPEER;
|
||||
|
||||
#[cfg(feature = "termios")]
|
||||
pub(crate) use linux_raw_sys::{
|
||||
general::{
|
||||
cc_t, speed_t, tcflag_t, termios, termios2, winsize, B0, B1000000, B110, B115200, B1152000,
|
||||
B1200, B134, B150, B1500000, B1800, B19200, B200, B2000000, B230400, B2400, B2500000, B300,
|
||||
B3000000, B3500000, B38400, B4000000, B460800, B4800, B50, B500000, B57600, B576000, B600,
|
||||
B75, B921600, B9600, BOTHER, BRKINT, BS0, BS1, BSDLY, CBAUD, CBAUDEX, CIBAUD, CLOCAL,
|
||||
CMSPAR, CR0, CR1, CR2, CR3, CRDLY, CREAD, CRTSCTS, CS5, CS6, CS7, CS8, CSIZE, CSTOPB, ECHO,
|
||||
ECHOCTL, ECHOE, ECHOK, ECHOKE, ECHONL, ECHOPRT, EXTA, EXTB, EXTPROC, FF0, FF1, FFDLY,
|
||||
FLUSHO, HUPCL, IBSHIFT, ICANON, ICRNL, IEXTEN, IGNBRK, IGNCR, IGNPAR, IMAXBEL, INLCR,
|
||||
INPCK, ISIG, ISTRIP, IUCLC, IUTF8, IXANY, IXOFF, IXON, NCCS, NL0, NL1, NLDLY, NOFLSH,
|
||||
OCRNL, OFDEL, OFILL, OLCUC, ONLCR, ONLRET, ONOCR, OPOST, PARENB, PARMRK, PARODD, PENDIN,
|
||||
TAB0, TAB1, TAB2, TAB3, TABDLY, TCIFLUSH, TCIOFF, TCIOFLUSH, TCION, TCOFLUSH, TCOOFF,
|
||||
TCOON, TCSADRAIN, TCSAFLUSH, TCSANOW, TOSTOP, VDISCARD, VEOF, VEOL, VEOL2, VERASE, VINTR,
|
||||
VKILL, VLNEXT, VMIN, VQUIT, VREPRINT, VSTART, VSTOP, VSUSP, VSWTC, VT0, VT1, VTDLY, VTIME,
|
||||
VWERASE, XCASE, XTABS,
|
||||
},
|
||||
ioctl::{TCGETS2, TCSETS2, TCSETSF2, TCSETSW2, TIOCEXCL, TIOCNXCL},
|
||||
};
|
||||
|
||||
// On MIPS, `TCSANOW` et al have `TCSETS` added to them, so we need it to
|
||||
// subtract it out.
|
||||
#[cfg(all(
|
||||
feature = "termios",
|
||||
any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6"
|
||||
)
|
||||
))]
|
||||
pub(crate) use linux_raw_sys::ioctl::TCSETS;
|
||||
|
||||
// Define our own `uid_t` and `gid_t` if the kernel's versions are not 32-bit.
|
||||
#[cfg(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86"))]
|
||||
pub(crate) type uid_t = u32;
|
||||
#[cfg(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86"))]
|
||||
pub(crate) type gid_t = u32;
|
||||
|
||||
// Bindgen infers `u32` for many of these macro types which meant to be
|
||||
// used with `c_int` in the C APIs, so cast them to `c_int`.
|
||||
|
||||
// Convert the signal constants from `u32` to `c_int`.
|
||||
pub(crate) const SIGHUP: c_int = linux_raw_sys::general::SIGHUP as _;
|
||||
pub(crate) const SIGINT: c_int = linux_raw_sys::general::SIGINT as _;
|
||||
pub(crate) const SIGQUIT: c_int = linux_raw_sys::general::SIGQUIT as _;
|
||||
pub(crate) const SIGILL: c_int = linux_raw_sys::general::SIGILL as _;
|
||||
pub(crate) const SIGTRAP: c_int = linux_raw_sys::general::SIGTRAP as _;
|
||||
pub(crate) const SIGABRT: c_int = linux_raw_sys::general::SIGABRT as _;
|
||||
pub(crate) const SIGBUS: c_int = linux_raw_sys::general::SIGBUS as _;
|
||||
pub(crate) const SIGFPE: c_int = linux_raw_sys::general::SIGFPE as _;
|
||||
pub(crate) const SIGKILL: c_int = linux_raw_sys::general::SIGKILL as _;
|
||||
pub(crate) const SIGUSR1: c_int = linux_raw_sys::general::SIGUSR1 as _;
|
||||
pub(crate) const SIGSEGV: c_int = linux_raw_sys::general::SIGSEGV as _;
|
||||
pub(crate) const SIGUSR2: c_int = linux_raw_sys::general::SIGUSR2 as _;
|
||||
pub(crate) const SIGPIPE: c_int = linux_raw_sys::general::SIGPIPE as _;
|
||||
pub(crate) const SIGALRM: c_int = linux_raw_sys::general::SIGALRM as _;
|
||||
pub(crate) const SIGTERM: c_int = linux_raw_sys::general::SIGTERM as _;
|
||||
#[cfg(not(any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
)))]
|
||||
pub(crate) const SIGSTKFLT: c_int = linux_raw_sys::general::SIGSTKFLT as _;
|
||||
pub(crate) const SIGCHLD: c_int = linux_raw_sys::general::SIGCHLD as _;
|
||||
pub(crate) const SIGCONT: c_int = linux_raw_sys::general::SIGCONT as _;
|
||||
pub(crate) const SIGSTOP: c_int = linux_raw_sys::general::SIGSTOP as _;
|
||||
pub(crate) const SIGTSTP: c_int = linux_raw_sys::general::SIGTSTP as _;
|
||||
pub(crate) const SIGTTIN: c_int = linux_raw_sys::general::SIGTTIN as _;
|
||||
pub(crate) const SIGTTOU: c_int = linux_raw_sys::general::SIGTTOU as _;
|
||||
pub(crate) const SIGURG: c_int = linux_raw_sys::general::SIGURG as _;
|
||||
pub(crate) const SIGXCPU: c_int = linux_raw_sys::general::SIGXCPU as _;
|
||||
pub(crate) const SIGXFSZ: c_int = linux_raw_sys::general::SIGXFSZ as _;
|
||||
pub(crate) const SIGVTALRM: c_int = linux_raw_sys::general::SIGVTALRM as _;
|
||||
pub(crate) const SIGPROF: c_int = linux_raw_sys::general::SIGPROF as _;
|
||||
pub(crate) const SIGWINCH: c_int = linux_raw_sys::general::SIGWINCH as _;
|
||||
pub(crate) const SIGIO: c_int = linux_raw_sys::general::SIGIO as _;
|
||||
pub(crate) const SIGPWR: c_int = linux_raw_sys::general::SIGPWR as _;
|
||||
pub(crate) const SIGSYS: c_int = linux_raw_sys::general::SIGSYS as _;
|
||||
#[cfg(any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
))]
|
||||
pub(crate) const SIGEMT: c_int = linux_raw_sys::general::SIGEMT as _;
|
||||
|
||||
#[cfg(feature = "stdio")]
|
||||
pub(crate) const STDIN_FILENO: c_int = linux_raw_sys::general::STDIN_FILENO as _;
|
||||
#[cfg(feature = "stdio")]
|
||||
pub(crate) const STDOUT_FILENO: c_int = linux_raw_sys::general::STDOUT_FILENO as _;
|
||||
#[cfg(feature = "stdio")]
|
||||
pub(crate) const STDERR_FILENO: c_int = linux_raw_sys::general::STDERR_FILENO as _;
|
||||
|
||||
pub(crate) const PIPE_BUF: usize = linux_raw_sys::general::PIPE_BUF as _;
|
||||
|
||||
pub(crate) const CLOCK_MONOTONIC: c_int = linux_raw_sys::general::CLOCK_MONOTONIC as _;
|
||||
pub(crate) const CLOCK_REALTIME: c_int = linux_raw_sys::general::CLOCK_REALTIME as _;
|
||||
pub(crate) const CLOCK_MONOTONIC_RAW: c_int = linux_raw_sys::general::CLOCK_MONOTONIC_RAW as _;
|
||||
pub(crate) const CLOCK_MONOTONIC_COARSE: c_int =
|
||||
linux_raw_sys::general::CLOCK_MONOTONIC_COARSE as _;
|
||||
pub(crate) const CLOCK_REALTIME_COARSE: c_int = linux_raw_sys::general::CLOCK_REALTIME_COARSE as _;
|
||||
pub(crate) const CLOCK_THREAD_CPUTIME_ID: c_int =
|
||||
linux_raw_sys::general::CLOCK_THREAD_CPUTIME_ID as _;
|
||||
pub(crate) const CLOCK_PROCESS_CPUTIME_ID: c_int =
|
||||
linux_raw_sys::general::CLOCK_PROCESS_CPUTIME_ID as _;
|
||||
#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
|
||||
pub(crate) const CLOCK_BOOTTIME: c_int = linux_raw_sys::general::CLOCK_BOOTTIME as _;
|
||||
#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
|
||||
pub(crate) const CLOCK_BOOTTIME_ALARM: c_int = linux_raw_sys::general::CLOCK_BOOTTIME_ALARM as _;
|
||||
#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
|
||||
pub(crate) const CLOCK_TAI: c_int = linux_raw_sys::general::CLOCK_TAI as _;
|
||||
#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
|
||||
pub(crate) const CLOCK_REALTIME_ALARM: c_int = linux_raw_sys::general::CLOCK_REALTIME_ALARM as _;
|
||||
|
||||
#[cfg(feature = "system")]
|
||||
mod reboot_symbols {
|
||||
use super::c_int;
|
||||
|
||||
pub(crate) const LINUX_REBOOT_MAGIC1: c_int = linux_raw_sys::general::LINUX_REBOOT_MAGIC1 as _;
|
||||
pub(crate) const LINUX_REBOOT_MAGIC2: c_int = linux_raw_sys::general::LINUX_REBOOT_MAGIC2 as _;
|
||||
|
||||
pub(crate) const LINUX_REBOOT_CMD_RESTART: c_int =
|
||||
linux_raw_sys::general::LINUX_REBOOT_CMD_RESTART as _;
|
||||
pub(crate) const LINUX_REBOOT_CMD_HALT: c_int =
|
||||
linux_raw_sys::general::LINUX_REBOOT_CMD_HALT as _;
|
||||
pub(crate) const LINUX_REBOOT_CMD_CAD_ON: c_int =
|
||||
linux_raw_sys::general::LINUX_REBOOT_CMD_CAD_ON as _;
|
||||
pub(crate) const LINUX_REBOOT_CMD_CAD_OFF: c_int =
|
||||
linux_raw_sys::general::LINUX_REBOOT_CMD_CAD_OFF as _;
|
||||
pub(crate) const LINUX_REBOOT_CMD_POWER_OFF: c_int =
|
||||
linux_raw_sys::general::LINUX_REBOOT_CMD_POWER_OFF as _;
|
||||
pub(crate) const LINUX_REBOOT_CMD_SW_SUSPEND: c_int =
|
||||
linux_raw_sys::general::LINUX_REBOOT_CMD_SW_SUSPEND as _;
|
||||
pub(crate) const LINUX_REBOOT_CMD_KEXEC: c_int =
|
||||
linux_raw_sys::general::LINUX_REBOOT_CMD_KEXEC as _;
|
||||
}
|
||||
#[cfg(feature = "system")]
|
||||
pub(crate) use reboot_symbols::*;
|
||||
1019
third-party/vendor/rustix/src/backend/linux_raw/conv.rs
vendored
Normal file
1019
third-party/vendor/rustix/src/backend/linux_raw/conv.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
470
third-party/vendor/rustix/src/backend/linux_raw/event/epoll.rs
vendored
Normal file
470
third-party/vendor/rustix/src/backend/linux_raw/event/epoll.rs
vendored
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
//! Linux `epoll` support.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # #[cfg(feature = "net")]
|
||||
//! # fn main() -> std::io::Result<()> {
|
||||
//! use rustix::event::epoll;
|
||||
//! use rustix::fd::AsFd;
|
||||
//! use rustix::io::{ioctl_fionbio, read, write};
|
||||
//! use rustix::net::{
|
||||
//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, SocketType,
|
||||
//! };
|
||||
//! use std::collections::HashMap;
|
||||
//! use std::os::unix::io::AsRawFd;
|
||||
//!
|
||||
//! // Create a socket and listen on it.
|
||||
//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, None)?;
|
||||
//! 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::create(epoll::CreateFlags::CLOEXEC)?;
|
||||
//!
|
||||
//! // Register the socket with the epoll object.
|
||||
//! epoll::add(
|
||||
//! &epoll,
|
||||
//! &listen_sock,
|
||||
//! epoll::EventData::new_u64(1),
|
||||
//! epoll::EventFlags::IN,
|
||||
//! )?;
|
||||
//!
|
||||
//! // Keep track of the sockets we've opened.
|
||||
//! let mut next_id = epoll::EventData::new_u64(2);
|
||||
//! let mut sockets = HashMap::new();
|
||||
//!
|
||||
//! // Process events.
|
||||
//! let mut event_list = epoll::EventVec::with_capacity(4);
|
||||
//! loop {
|
||||
//! epoll::wait(&epoll, &mut event_list, -1)?;
|
||||
//! for event in &event_list {
|
||||
//! let target = event.data;
|
||||
//! if target.u64() == 1 {
|
||||
//! // 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(&listen_sock)?;
|
||||
//! ioctl_fionbio(&conn_sock, true)?;
|
||||
//! epoll::add(
|
||||
//! &epoll,
|
||||
//! &conn_sock,
|
||||
//! next_id,
|
||||
//! epoll::EventFlags::OUT | epoll::EventFlags::ET,
|
||||
//! )?;
|
||||
//!
|
||||
//! // Keep track of the socket.
|
||||
//! sockets.insert(next_id, conn_sock);
|
||||
//! next_id = epoll::EventData::new_u64(next_id.u64() + 1);
|
||||
//! } else {
|
||||
//! // Write a message to the stream and then unregister it.
|
||||
//! let target = sockets.remove(&target).unwrap();
|
||||
//! write(&target, b"hello\n")?;
|
||||
//! let _ = epoll::delete(&epoll, &target)?;
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! # }
|
||||
//! # #[cfg(not(feature = "net"))]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::event::syscalls;
|
||||
use crate::fd::{AsFd, AsRawFd, OwnedFd};
|
||||
use crate::io;
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::vec::Vec;
|
||||
use bitflags::bitflags;
|
||||
use core::ffi::c_void;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::slice;
|
||||
|
||||
bitflags! {
|
||||
/// `EPOLL_*` for use with [`new`].
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct CreateFlags: c::c_uint {
|
||||
/// `EPOLL_CLOEXEC`
|
||||
const CLOEXEC = linux_raw_sys::general::EPOLL_CLOEXEC;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `EPOLL*` for use with [`add`].
|
||||
#[repr(transparent)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// `EPOLLRDNORM`
|
||||
const RDNORM = linux_raw_sys::general::EPOLLRDNORM as u32;
|
||||
|
||||
/// `EPOLLRDBAND`
|
||||
const RDBAND = linux_raw_sys::general::EPOLLRDBAND as u32;
|
||||
|
||||
/// `EPOLLWRNORM`
|
||||
const WRNORM = linux_raw_sys::general::EPOLLWRNORM as u32;
|
||||
|
||||
/// `EPOLLWRBAND`
|
||||
const WRBAND = linux_raw_sys::general::EPOLLWRBAND as u32;
|
||||
|
||||
/// `EPOLLMSG`
|
||||
const MSG = linux_raw_sys::general::EPOLLMSG as u32;
|
||||
|
||||
/// `EPOLLRDHUP`
|
||||
const RDHUP = linux_raw_sys::general::EPOLLRDHUP 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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_create1(flags)`—Creates a new epoll object.
|
||||
///
|
||||
/// 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 create(flags: CreateFlags) -> io::Result<OwnedFd> {
|
||||
syscalls::epoll_create(flags)
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an epoll
|
||||
/// object.
|
||||
///
|
||||
/// This registers interest in any of the events set in `events` occurring on
|
||||
/// the file descriptor associated with `data`.
|
||||
///
|
||||
/// If [`delete`] is not called on the I/O source passed into this function
|
||||
/// before the I/O source is `close`d, then the `epoll` will act as if the I/O
|
||||
/// source is still registered with it. This can lead to spurious events being
|
||||
/// returned from [`wait`]. If a file descriptor is an
|
||||
/// `Arc<dyn SystemResource>`, then `epoll` can be thought to maintain a
|
||||
/// `Weak<dyn SystemResource>` to the file descriptor.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
#[inline]
|
||||
pub fn add(
|
||||
epoll: impl AsFd,
|
||||
source: impl AsFd,
|
||||
data: EventData,
|
||||
event_flags: EventFlags,
|
||||
) -> io::Result<()> {
|
||||
// SAFETY: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
syscalls::epoll_add(
|
||||
epoll.as_fd(),
|
||||
source.as_fd().as_raw_fd(),
|
||||
&Event {
|
||||
flags: event_flags,
|
||||
data,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in a
|
||||
/// given epoll object.
|
||||
///
|
||||
/// This sets the events of interest with `target` to `events`.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
#[inline]
|
||||
pub fn modify(
|
||||
epoll: impl AsFd,
|
||||
source: impl AsFd,
|
||||
data: EventData,
|
||||
event_flags: EventFlags,
|
||||
) -> io::Result<()> {
|
||||
// SAFETY: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
let raw_fd = source.as_fd().as_raw_fd();
|
||||
syscalls::epoll_mod(
|
||||
epoll.as_fd(),
|
||||
raw_fd,
|
||||
&Event {
|
||||
flags: event_flags,
|
||||
data,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in a
|
||||
/// given epoll object.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
#[inline]
|
||||
pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
|
||||
// SAFETY: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
let raw_fd = source.as_fd().as_raw_fd();
|
||||
syscalls::epoll_del(epoll.as_fd(), raw_fd)
|
||||
}
|
||||
}
|
||||
|
||||
/// `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.
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
||||
#[inline]
|
||||
pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, 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 = syscalls::epoll_wait(
|
||||
epoll.as_fd(),
|
||||
event_list.events[..].as_mut_ptr().cast(),
|
||||
event_list.events.capacity(),
|
||||
timeout,
|
||||
)?;
|
||||
event_list.events.set_len(nfds);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// An iterator over the `Event`s in an `EventVec`.
|
||||
pub struct Iter<'a> {
|
||||
/// Use `Copied` to copy the struct, since `Event` is `packed` on some
|
||||
/// platforms, and it's common for users to directly destructure it, which
|
||||
/// would lead to errors about forming references to packed fields.
|
||||
iter: core::iter::Copied<slice::Iter<'a, Event>>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = Event;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
/// A record of an event that occurred.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(target_arch = "x86_64", repr(packed))]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Event {
|
||||
/// Which specific event(s) occurred.
|
||||
pub flags: EventFlags,
|
||||
/// User data.
|
||||
pub data: EventData,
|
||||
}
|
||||
|
||||
/// Data associated with an [`Event`]. This can either be a 64-bit integer
|
||||
/// value or a pointer which preserves pointer provenance.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union EventData {
|
||||
/// A 64-bit integer value.
|
||||
as_u64: u64,
|
||||
|
||||
/// A `*mut c_void` which preserves pointer provenance, extended to be
|
||||
/// 64-bit so that if we read the value as a `u64` union field, we don't
|
||||
/// get uninitialized memory.
|
||||
sixty_four_bit_pointer: SixtyFourBitPointer,
|
||||
}
|
||||
|
||||
impl EventData {
|
||||
/// Construct a new value containing a `u64`.
|
||||
#[inline]
|
||||
pub const fn new_u64(value: u64) -> Self {
|
||||
Self { as_u64: value }
|
||||
}
|
||||
|
||||
/// Construct a new value containing a `*mut c_void`.
|
||||
#[inline]
|
||||
pub const fn new_ptr(value: *mut c_void) -> Self {
|
||||
Self {
|
||||
sixty_four_bit_pointer: SixtyFourBitPointer {
|
||||
pointer: value,
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
_padding: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the value as a `u64`.
|
||||
///
|
||||
/// If the stored value was a pointer, the pointer is zero-extended to a
|
||||
/// `u64`.
|
||||
#[inline]
|
||||
pub fn u64(self) -> u64 {
|
||||
unsafe { self.as_u64 }
|
||||
}
|
||||
|
||||
/// Return the value as a `*mut c_void`.
|
||||
///
|
||||
/// If the stored value was a `u64`, the least-significant bits of the
|
||||
/// `u64` are returned as a pointer value.
|
||||
#[inline]
|
||||
pub fn ptr(self) -> *mut c_void {
|
||||
unsafe { self.sixty_four_bit_pointer.pointer }
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for EventData {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.u64() == other.u64()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for EventData {}
|
||||
|
||||
impl Hash for EventData {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.u64().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct SixtyFourBitPointer {
|
||||
#[cfg(target_endian = "big")]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
_padding: u32,
|
||||
|
||||
pointer: *mut c_void,
|
||||
|
||||
#[cfg(target_endian = "little")]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
_padding: u32,
|
||||
}
|
||||
|
||||
/// A vector of `Event`s, plus context for interpreting them.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub struct EventVec {
|
||||
events: Vec<Event>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl EventVec {
|
||||
/// Constructs an `EventVec` from raw pointer, length, and capacity.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function calls [`Vec::from_raw_parts`] with its arguments.
|
||||
///
|
||||
/// [`Vec::from_raw_parts`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.from_raw_parts
|
||||
#[inline]
|
||||
pub unsafe fn from_raw_parts(ptr: *mut Event, len: usize, capacity: usize) -> Self {
|
||||
Self {
|
||||
events: Vec::from_raw_parts(ptr, len, capacity),
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an `EventVec` with memory for `capacity` `Event`s.
|
||||
#[inline]
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
Self {
|
||||
events: Vec::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<'_> {
|
||||
Iter {
|
||||
iter: self.events.iter().copied(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> IntoIterator for &'a EventVec {
|
||||
type IntoIter = Iter<'a>;
|
||||
type Item = Event;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_epoll_layouts() {
|
||||
check_renamed_type!(Event, epoll_event);
|
||||
check_renamed_type!(Event, epoll_event);
|
||||
check_renamed_struct_renamed_field!(Event, epoll_event, flags, events);
|
||||
check_renamed_struct_renamed_field!(Event, epoll_event, data, data);
|
||||
}
|
||||
4
third-party/vendor/rustix/src/backend/linux_raw/event/mod.rs
vendored
Normal file
4
third-party/vendor/rustix/src/backend/linux_raw/event/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
pub mod epoll;
|
||||
pub(crate) mod poll_fd;
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
98
third-party/vendor/rustix/src/backend/linux_raw/event/poll_fd.rs
vendored
Normal file
98
third-party/vendor/rustix/src/backend/linux_raw/event/poll_fd.rs
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
use crate::fd::{AsFd, BorrowedFd};
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `POLL*` flags for use with [`poll`].
|
||||
///
|
||||
/// [`poll`]: crate::event::poll
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `struct pollfd`—File descriptor and flags for use with [`poll`].
|
||||
///
|
||||
/// [`poll`]: crate::event::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()
|
||||
}
|
||||
}
|
||||
152
third-party/vendor/rustix/src/backend/linux_raw/event/syscalls.rs
vendored
Normal file
152
third-party/vendor/rustix/src/backend/linux_raw/event/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
//! linux_raw syscalls supporting `rustix::event`.
|
||||
//!
|
||||
//! # Safety
|
||||
//!
|
||||
//! See the `rustix::backend` module documentation for details.
|
||||
#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)]
|
||||
|
||||
use crate::backend::c;
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::backend::conv::pass_usize;
|
||||
use crate::backend::conv::{
|
||||
by_ref, c_int, c_uint, raw_fd, ret, ret_error, ret_owned_fd, ret_usize, slice_mut, zero,
|
||||
};
|
||||
use crate::event::{epoll, EventfdFlags, PollFd};
|
||||
use crate::fd::{BorrowedFd, OwnedFd};
|
||||
use crate::io;
|
||||
use linux_raw_sys::general::{EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD};
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
|
||||
use {
|
||||
crate::backend::conv::{opt_ref, size_of},
|
||||
linux_raw_sys::general::{__kernel_timespec, kernel_sigset_t},
|
||||
};
|
||||
|
||||
#[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::<kernel_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()
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[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()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[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 pause() {
|
||||
unsafe {
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
|
||||
let error = ret_error(syscall_readonly!(
|
||||
__NR_ppoll,
|
||||
zero(),
|
||||
zero(),
|
||||
zero(),
|
||||
zero()
|
||||
));
|
||||
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
|
||||
let error = ret_error(syscall_readonly!(__NR_pause));
|
||||
|
||||
debug_assert_eq!(error, io::Errno::INTR);
|
||||
}
|
||||
}
|
||||
21
third-party/vendor/rustix/src/backend/linux_raw/event/types.rs
vendored
Normal file
21
third-party/vendor/rustix/src/backend/linux_raw/event/types.rs
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use crate::backend::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `EFD_*` flags for use with [`eventfd`].
|
||||
///
|
||||
/// [`eventfd`]: crate::event::eventfd
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
315
third-party/vendor/rustix/src/backend/linux_raw/fs/dir.rs
vendored
Normal file
315
third-party/vendor/rustix/src/backend/linux_raw/fs/dir.rs
vendored
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
use crate::fd::{AsFd, BorrowedFd, OwnedFd};
|
||||
use crate::ffi::{CStr, CString};
|
||||
use crate::fs::{
|
||||
fcntl_getfl, fstat, fstatfs, fstatvfs, openat, FileType, Mode, OFlags, Stat, StatFs, StatVfs,
|
||||
};
|
||||
use crate::io;
|
||||
#[cfg(feature = "process")]
|
||||
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,
|
||||
|
||||
/// Have we seen any errors in this iteration?
|
||||
any_errors: bool,
|
||||
|
||||
/// Should we rewind the stream on the next iteration?
|
||||
rewind: bool,
|
||||
|
||||
/// The buffer for `linux_dirent64` entries.
|
||||
buf: Vec<u8>,
|
||||
|
||||
/// Where we are in the buffer.
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl Dir {
|
||||
/// Take ownership of `fd` and construct a `Dir` that reads entries from
|
||||
/// the given directory file descriptor.
|
||||
#[inline]
|
||||
pub fn new<Fd: Into<OwnedFd>>(fd: Fd) -> io::Result<Self> {
|
||||
Self::_new(fd.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn _new(fd: OwnedFd) -> io::Result<Self> {
|
||||
Ok(Self {
|
||||
fd,
|
||||
any_errors: false,
|
||||
rewind: false,
|
||||
buf: Vec::new(),
|
||||
pos: 0,
|
||||
})
|
||||
}
|
||||
|
||||
/// Borrow `fd` and 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,
|
||||
any_errors: false,
|
||||
rewind: false,
|
||||
buf: Vec::new(),
|
||||
pos: 0,
|
||||
})
|
||||
}
|
||||
|
||||
/// `rewinddir(self)`
|
||||
#[inline]
|
||||
pub fn rewind(&mut self) {
|
||||
self.any_errors = false;
|
||||
self.rewind = true;
|
||||
self.pos = self.buf.len();
|
||||
}
|
||||
|
||||
/// `readdir(self)`, where `None` means the end of the directory.
|
||||
pub fn read(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
// If we've seen errors, don't continue to try to read anything further.
|
||||
if self.any_errors {
|
||||
return None;
|
||||
}
|
||||
|
||||
// If a rewind was requested, seek to the beginning.
|
||||
if self.rewind {
|
||||
self.rewind = false;
|
||||
match io::retry_on_intr(|| {
|
||||
crate::backend::fs::syscalls::_seek(self.fd.as_fd(), 0, SEEK_SET)
|
||||
}) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
self.any_errors = true;
|
||||
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(err) => return Some(Err(err)),
|
||||
}
|
||||
}
|
||||
|
||||
// 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_len]).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,
|
||||
}))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn read_more(&mut self) -> Option<io::Result<()>> {
|
||||
// The first few times we're called, we allocate a relatively small
|
||||
// buffer, because many directories are small. If we're called more,
|
||||
// use progressively larger allocations, up to a fixed maximum.
|
||||
//
|
||||
// The specific sizes and policy here have not been tuned in detail yet
|
||||
// and may need to be adjusted. In doing so, we should be careful to
|
||||
// avoid unbounded buffer growth. This buffer only exists to share the
|
||||
// cost of a `getdents` call over many entries, so if it gets too big,
|
||||
// cache and heap usage will outweigh the benefit. And ultimately,
|
||||
// directories can contain more entries than we can allocate contiguous
|
||||
// memory for, so we'll always need to cap the size at some point.
|
||||
if self.buf.len() < 1024 * size_of::<linux_dirent64>() {
|
||||
self.buf.reserve(32 * size_of::<linux_dirent64>());
|
||||
}
|
||||
self.buf.resize(self.buf.capacity(), 0);
|
||||
let nread = match io::retry_on_intr(|| {
|
||||
crate::backend::fs::syscalls::getdents(self.fd.as_fd(), &mut self.buf)
|
||||
}) {
|
||||
Ok(nread) => nread,
|
||||
Err(io::Errno::NOENT) => {
|
||||
self.any_errors = true;
|
||||
return None;
|
||||
}
|
||||
Err(err) => {
|
||||
self.any_errors = true;
|
||||
return Some(Err(err));
|
||||
}
|
||||
};
|
||||
self.buf.resize(nread, 0);
|
||||
self.pos = 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)
|
||||
}
|
||||
|
||||
/// `fstatvfs(self)`
|
||||
#[inline]
|
||||
pub fn statvfs(&self) -> io::Result<StatVfs> {
|
||||
fstatvfs(&self.fd)
|
||||
}
|
||||
|
||||
/// `fchdir(self)`
|
||||
#[cfg(feature = "process")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "process")))]
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir_iterator_handles_io_errors() {
|
||||
// create a dir, keep the FD, then delete the dir
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let fd = crate::fs::openat(
|
||||
crate::fs::CWD,
|
||||
tmp.path(),
|
||||
crate::fs::OFlags::RDONLY | crate::fs::OFlags::CLOEXEC,
|
||||
crate::fs::Mode::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let file_fd = crate::fs::openat(
|
||||
&fd,
|
||||
tmp.path().join("test.txt"),
|
||||
crate::fs::OFlags::WRONLY | crate::fs::OFlags::CREATE,
|
||||
crate::fs::Mode::RWXU,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut dir = Dir::read_from(&fd).unwrap();
|
||||
|
||||
// Reach inside the `Dir` and replace its directory with a file, which
|
||||
// will cause the subsequent `getdents64` to fail.
|
||||
crate::io::dup2(&file_fd, &mut dir.fd).unwrap();
|
||||
|
||||
assert!(matches!(dir.next(), Some(Err(_))));
|
||||
assert!(dir.next().is_none());
|
||||
}
|
||||
118
third-party/vendor/rustix/src/backend/linux_raw/fs/inotify.rs
vendored
Normal file
118
third-party/vendor/rustix/src/backend/linux_raw/fs/inotify.rs
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
//! inotify support for working with inotifies
|
||||
|
||||
use crate::backend::c;
|
||||
use crate::backend::fs::syscalls;
|
||||
use crate::fd::{BorrowedFd, OwnedFd};
|
||||
use crate::io;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `IN_*` for use with [`inotify_init`].
|
||||
///
|
||||
/// [`inotify_init`]: crate::fs::inotify::inotify_init
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct CreateFlags: c::c_uint {
|
||||
/// `IN_CLOEXEC`
|
||||
const CLOEXEC = linux_raw_sys::general::IN_CLOEXEC;
|
||||
/// `IN_NONBLOCK`
|
||||
const NONBLOCK = linux_raw_sys::general::IN_NONBLOCK;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `IN*` for use with [`inotify_add_watch`].
|
||||
///
|
||||
/// [`inotify_add_watch`]: crate::fs::inotify::inotify_add_watch
|
||||
#[repr(transparent)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct WatchFlags: c::c_uint {
|
||||
/// `IN_ACCESS`
|
||||
const ACCESS = linux_raw_sys::general::IN_ACCESS;
|
||||
/// `IN_ATTRIB`
|
||||
const ATTRIB = linux_raw_sys::general::IN_ATTRIB;
|
||||
/// `IN_CLOSE_NOWRITE`
|
||||
const CLOSE_NOWRITE = linux_raw_sys::general::IN_CLOSE_NOWRITE;
|
||||
/// `IN_CLOSE_WRITE`
|
||||
const CLOSE_WRITE = linux_raw_sys::general::IN_CLOSE_WRITE;
|
||||
/// `IN_CREATE`
|
||||
const CREATE = linux_raw_sys::general::IN_CREATE;
|
||||
/// `IN_DELETE`
|
||||
const DELETE = linux_raw_sys::general::IN_DELETE;
|
||||
/// `IN_DELETE_SELF`
|
||||
const DELETE_SELF = linux_raw_sys::general::IN_DELETE_SELF;
|
||||
/// `IN_MODIFY`
|
||||
const MODIFY = linux_raw_sys::general::IN_MODIFY;
|
||||
/// `IN_MOVE_SELF`
|
||||
const MOVE_SELF = linux_raw_sys::general::IN_MOVE_SELF;
|
||||
/// `IN_MOVED_FROM`
|
||||
const MOVED_FROM = linux_raw_sys::general::IN_MOVED_FROM;
|
||||
/// `IN_MOVED_TO`
|
||||
const MOVED_TO = linux_raw_sys::general::IN_MOVED_TO;
|
||||
/// `IN_OPEN`
|
||||
const OPEN = linux_raw_sys::general::IN_OPEN;
|
||||
|
||||
/// `IN_CLOSE`
|
||||
const CLOSE = linux_raw_sys::general::IN_CLOSE;
|
||||
/// `IN_MOVE`
|
||||
const MOVE = linux_raw_sys::general::IN_MOVE;
|
||||
/// `IN_ALL_EVENTS`
|
||||
const ALL_EVENTS = linux_raw_sys::general::IN_ALL_EVENTS;
|
||||
|
||||
/// `IN_DONT_FOLLOW`
|
||||
const DONT_FOLLOW = linux_raw_sys::general::IN_DONT_FOLLOW;
|
||||
/// `IN_EXCL_UNLINK`
|
||||
const EXCL_UNLINK = linux_raw_sys::general::IN_EXCL_UNLINK;
|
||||
/// `IN_MASK_ADD`
|
||||
const MASK_ADD = linux_raw_sys::general::IN_MASK_ADD;
|
||||
/// `IN_MASK_CREATE`
|
||||
const MASK_CREATE = linux_raw_sys::general::IN_MASK_CREATE;
|
||||
/// `IN_ONESHOT`
|
||||
const ONESHOT = linux_raw_sys::general::IN_ONESHOT;
|
||||
/// `IN_ONLYDIR`
|
||||
const ONLYDIR = linux_raw_sys::general::IN_ONLYDIR;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `inotify_init1(flags)`—Creates a new inotify object.
|
||||
///
|
||||
/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
|
||||
/// descriptor from being implicitly passed across `exec` boundaries.
|
||||
#[doc(alias = "inotify_init1")]
|
||||
#[inline]
|
||||
pub fn inotify_init(flags: CreateFlags) -> io::Result<OwnedFd> {
|
||||
syscalls::inotify_init1(flags)
|
||||
}
|
||||
|
||||
/// `inotify_add_watch(self, path, flags)`—Adds a watch to inotify.
|
||||
///
|
||||
/// This registers or updates a watch for the filesystem path `path` and
|
||||
/// returns a watch descriptor corresponding to this watch.
|
||||
///
|
||||
/// Note: Due to the existence of hardlinks, providing two different paths to
|
||||
/// this method may result in it returning the same watch descriptor. An
|
||||
/// application should keep track of this externally to avoid logic errors.
|
||||
#[inline]
|
||||
pub fn inotify_add_watch<P: crate::path::Arg>(
|
||||
inot: BorrowedFd<'_>,
|
||||
path: P,
|
||||
flags: WatchFlags,
|
||||
) -> io::Result<i32> {
|
||||
path.into_with_c_str(|path| syscalls::inotify_add_watch(inot, path, flags))
|
||||
}
|
||||
|
||||
/// `inotify_rm_watch(self, wd)`—Removes a watch from this inotify.
|
||||
///
|
||||
/// The watch descriptor provided should have previously been returned by
|
||||
/// [`inotify_add_watch`] and not previously have been removed.
|
||||
#[doc(alias = "inotify_rm_watch")]
|
||||
#[inline]
|
||||
pub fn inotify_remove_watch(inot: BorrowedFd<'_>, wd: i32) -> io::Result<()> {
|
||||
syscalls::inotify_rm_watch(inot, wd)
|
||||
}
|
||||
19
third-party/vendor/rustix/src/backend/linux_raw/fs/makedev.rs
vendored
Normal file
19
third-party/vendor/rustix/src/backend/linux_raw/fs/makedev.rs
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
13
third-party/vendor/rustix/src/backend/linux_raw/fs/mod.rs
vendored
Normal file
13
third-party/vendor/rustix/src/backend/linux_raw/fs/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#[cfg(feature = "alloc")]
|
||||
pub(crate) mod dir;
|
||||
pub mod inotify;
|
||||
pub(crate) mod makedev;
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
|
||||
// TODO: Fix linux-raw-sys to define ioctl codes for sparc.
|
||||
#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
|
||||
pub(crate) const EXT4_IOC_RESIZE_FS: u32 = 0x8008_6610;
|
||||
|
||||
#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))]
|
||||
pub(crate) use linux_raw_sys::ioctl::EXT4_IOC_RESIZE_FS;
|
||||
1660
third-party/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs
vendored
Normal file
1660
third-party/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
742
third-party/vendor/rustix/src/backend/linux_raw/fs/types.rs
vendored
Normal file
742
third-party/vendor/rustix/src/backend/linux_raw/fs/types.rs
vendored
Normal file
|
|
@ -0,0 +1,742 @@
|
|||
use crate::backend::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `*_OK` constants for use with [`accessat`].
|
||||
///
|
||||
/// [`accessat`]: fn.accessat.html
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `AT_*` constants for use with [`openat`], [`statat`], and other `*at`
|
||||
/// functions.
|
||||
///
|
||||
/// [`openat`]: crate::fs::openat
|
||||
/// [`statat`]: crate::fs::statat
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct AtFlags: c::c_uint {
|
||||
/// `AT_SYMLINK_NOFOLLOW`
|
||||
const SYMLINK_NOFOLLOW = linux_raw_sys::general::AT_SYMLINK_NOFOLLOW;
|
||||
|
||||
/// `AT_EACCESS`
|
||||
const EACCESS = linux_raw_sys::general::AT_EACCESS;
|
||||
|
||||
/// `AT_REMOVEDIR`
|
||||
const REMOVEDIR = linux_raw_sys::general::AT_REMOVEDIR;
|
||||
|
||||
/// `AT_SYMLINK_FOLLOW`
|
||||
const SYMLINK_FOLLOW = linux_raw_sys::general::AT_SYMLINK_FOLLOW;
|
||||
|
||||
/// `AT_NO_AUTOMOUNT`
|
||||
const NO_AUTOMOUNT = linux_raw_sys::general::AT_NO_AUTOMOUNT;
|
||||
|
||||
/// `AT_EMPTY_PATH`
|
||||
const EMPTY_PATH = linux_raw_sys::general::AT_EMPTY_PATH;
|
||||
|
||||
/// `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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `S_I*` constants for use with [`openat`], [`chmodat`], and [`fchmod`].
|
||||
///
|
||||
/// [`openat`]: crate::fs::openat
|
||||
/// [`chmodat`]: crate::fs::chmodat
|
||||
/// [`fchmod`]: crate::fs::fchmod
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
/// Construct a `Mode` from the mode bits of the `st_mode` field of a
|
||||
/// `Mode`.
|
||||
#[inline]
|
||||
pub const fn from_raw_mode(st_mode: RawMode) -> Self {
|
||||
Self::from_bits_truncate(st_mode)
|
||||
}
|
||||
|
||||
/// Construct an `st_mode` value from a `Mode`.
|
||||
#[inline]
|
||||
pub const fn as_raw_mode(self) -> RawMode {
|
||||
self.bits()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RawMode> for Mode {
|
||||
/// Support conversions from raw mode values to `Mode`.
|
||||
///
|
||||
/// ```
|
||||
/// use rustix::fs::{Mode, RawMode};
|
||||
/// assert_eq!(Mode::from(0o700), Mode::RWXU);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn from(st_mode: RawMode) -> Self {
|
||||
Self::from_raw_mode(st_mode)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Mode> for RawMode {
|
||||
/// Support conversions from `Mode` to raw mode values.
|
||||
///
|
||||
/// ```
|
||||
/// use rustix::fs::{Mode, RawMode};
|
||||
/// assert_eq!(RawMode::from(Mode::RWXU), 0o700);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn from(mode: Mode) -> Self {
|
||||
mode.as_raw_mode()
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `O_*` constants for use with [`openat`].
|
||||
///
|
||||
/// [`openat`]: crate::fs::openat
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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.
|
||||
///
|
||||
/// On some platforms, `PATH` may be included in `ACCMODE`, when
|
||||
/// sometimes we really just want the read/write bits. Caution is
|
||||
/// indicated, as the presence of `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`.
|
||||
const DSYNC = linux_raw_sys::general::O_SYNC;
|
||||
|
||||
/// `O_EXCL`
|
||||
const EXCL = linux_raw_sys::general::O_EXCL;
|
||||
|
||||
/// `O_FSYNC`.
|
||||
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`
|
||||
///
|
||||
/// This is not equal to `RDONLY | WRONLY`. It's a distinct flag.
|
||||
const RDWR = linux_raw_sys::general::O_RDWR;
|
||||
|
||||
/// `O_NOCTTY`
|
||||
const NOCTTY = linux_raw_sys::general::O_NOCTTY;
|
||||
|
||||
/// `O_RSYNC`.
|
||||
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;
|
||||
|
||||
/// `O_DIRECT`
|
||||
const DIRECT = linux_raw_sys::general::O_DIRECT;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `RESOLVE_*` constants for use with [`openat2`].
|
||||
///
|
||||
/// [`openat2`]: crate::fs::openat2
|
||||
#[repr(transparent)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `RENAME_*` constants for use with [`renameat_with`].
|
||||
///
|
||||
/// [`renameat_with`]: crate::fs::renameat_with
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `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`
|
||||
#[doc(alias = "IFO")]
|
||||
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 a `FileType`.
|
||||
#[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 `c::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
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `STATX_*` constants for use with [`statx`].
|
||||
///
|
||||
/// [`statx`]: crate::fs::statx
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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_DIOALIGN` (since Linux 6.1)
|
||||
const DIOALIGN = linux_raw_sys::general::STATX_DIOALIGN;
|
||||
|
||||
/// `STATX_ALL`
|
||||
const ALL = linux_raw_sys::general::STATX_ALL;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `FALLOC_FL_*` constants for use with [`fallocate`].
|
||||
///
|
||||
/// [`fallocate`]: crate::fs::fallocate
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
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;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `ST_*` constants for use with [`StatVfs`].
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct StatVfsMountFlags: u64 {
|
||||
/// `ST_MANDLOCK`
|
||||
const MANDLOCK = linux_raw_sys::general::MS_MANDLOCK as u64;
|
||||
|
||||
/// `ST_NOATIME`
|
||||
const NOATIME = linux_raw_sys::general::MS_NOATIME as u64;
|
||||
|
||||
/// `ST_NODEV`
|
||||
const NODEV = linux_raw_sys::general::MS_NODEV as u64;
|
||||
|
||||
/// `ST_NODIRATIME`
|
||||
const NODIRATIME = linux_raw_sys::general::MS_NODIRATIME as u64;
|
||||
|
||||
/// `ST_NOEXEC`
|
||||
const NOEXEC = linux_raw_sys::general::MS_NOEXEC as u64;
|
||||
|
||||
/// `ST_NOSUID`
|
||||
const NOSUID = linux_raw_sys::general::MS_NOSUID as u64;
|
||||
|
||||
/// `ST_RDONLY`
|
||||
const RDONLY = linux_raw_sys::general::MS_RDONLY as u64;
|
||||
|
||||
/// `ST_RELATIME`
|
||||
const RELATIME = linux_raw_sys::general::MS_RELATIME as u64;
|
||||
|
||||
/// `ST_SYNCHRONOUS`
|
||||
const SYNCHRONOUS = linux_raw_sys::general::MS_SYNCHRONOUS as u64;
|
||||
|
||||
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
|
||||
const _ = !0;
|
||||
}
|
||||
}
|
||||
|
||||
/// `LOCK_*` constants for use with [`flock`] and [`fcntl_lock`].
|
||||
///
|
||||
/// [`flock`]: crate::fs::flock
|
||||
/// [`fcntl_lock`]: crate::fs::fcntl_lock
|
||||
#[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",
|
||||
target_arch = "mips64r6"
|
||||
))]
|
||||
#[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,
|
||||
#[deprecated(note = "Use `rustix::fs::StatExt::atime` instead.")]
|
||||
pub st_atime: u64,
|
||||
pub st_atime_nsec: u32,
|
||||
#[deprecated(note = "Use `rustix::fs::StatExt::mtime` instead.")]
|
||||
pub st_mtime: u64,
|
||||
pub st_mtime_nsec: u32,
|
||||
#[deprecated(note = "Use `rustix::fs::StatExt::ctime` instead.")]
|
||||
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"),
|
||||
not(target_arch = "mips64r6")
|
||||
))]
|
||||
pub type Stat = linux_raw_sys::general::stat;
|
||||
|
||||
/// `struct statfs` for use with [`statfs`] and [`fstatfs`].
|
||||
///
|
||||
/// [`statfs`]: crate::fs::statfs
|
||||
/// [`fstatfs`]: crate::fs::fstatfs
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub type StatFs = linux_raw_sys::general::statfs64;
|
||||
|
||||
/// `struct statvfs` for use with [`statvfs`] and [`fstatvfs`].
|
||||
///
|
||||
/// [`statvfs`]: crate::fs::statvfs
|
||||
/// [`fstatvfs`]: crate::fs::fstatvfs
|
||||
#[allow(missing_docs)]
|
||||
pub struct StatVfs {
|
||||
pub f_bsize: u64,
|
||||
pub f_frsize: u64,
|
||||
pub f_blocks: u64,
|
||||
pub f_bfree: u64,
|
||||
pub f_bavail: u64,
|
||||
pub f_files: u64,
|
||||
pub f_ffree: u64,
|
||||
pub f_favail: u64,
|
||||
pub f_fsid: u64,
|
||||
pub f_flag: StatVfsMountFlags,
|
||||
pub f_namemax: u64,
|
||||
}
|
||||
|
||||
/// `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(any(target_arch = "mips64", target_arch = "mips64r6")))]
|
||||
pub type FsWord = linux_raw_sys::general::__fsword_t;
|
||||
|
||||
/// `__fsword_t`
|
||||
#[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))]
|
||||
pub type FsWord = i64;
|
||||
553
third-party/vendor/rustix/src/backend/linux_raw/io/errno.rs
vendored
Normal file
553
third-party/vendor/rustix/src/backend/linux_raw/io/errno.rs
vendored
Normal file
|
|
@ -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<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`.
|
||||
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<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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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::backend) 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(any(feature = "event", feature = "runtime"))]
|
||||
#[inline]
|
||||
pub(in crate::backend) 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::backend) fn decode_usize_infallible<Num: RetNumber>(raw: RetReg<Num>) -> usize {
|
||||
raw.decode_usize()
|
||||
}
|
||||
|
||||
/// Return the contained `c_int` value.
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[inline]
|
||||
pub(in crate::backend) fn decode_c_int_infallible<Num: RetNumber>(raw: RetReg<Num>) -> 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<Num: RetNumber>(raw: RetReg<Num>) -> 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);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue