summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/backend/linux_raw
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/backend/linux_raw')
-rw-r--r--vendor/rustix/src/backend/linux_raw/c.rs32
-rw-r--r--vendor/rustix/src/backend/linux_raw/conv.rs73
-rw-r--r--vendor/rustix/src/backend/linux_raw/fs/inotify.rs108
-rw-r--r--vendor/rustix/src/backend/linux_raw/fs/mod.rs1
-rw-r--r--vendor/rustix/src/backend/linux_raw/fs/syscalls.rs170
-rw-r--r--vendor/rustix/src/backend/linux_raw/fs/types.rs138
-rw-r--r--vendor/rustix/src/backend/linux_raw/io/epoll.rs519
-rw-r--r--vendor/rustix/src/backend/linux_raw/io/errno.rs19
-rw-r--r--vendor/rustix/src/backend/linux_raw/io/syscalls.rs7
-rw-r--r--vendor/rustix/src/backend/linux_raw/io/types.rs11
-rw-r--r--vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs6
-rw-r--r--vendor/rustix/src/backend/linux_raw/mod.rs5
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/addr.rs4
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/syscalls.rs10
-rw-r--r--vendor/rustix/src/backend/linux_raw/param/auxv.rs6
-rw-r--r--vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs39
-rw-r--r--vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs14
-rw-r--r--vendor/rustix/src/backend/linux_raw/process/cpu_set.rs2
-rw-r--r--vendor/rustix/src/backend/linux_raw/process/syscalls.rs111
-rw-r--r--vendor/rustix/src/backend/linux_raw/process/wait.rs4
-rw-r--r--vendor/rustix/src/backend/linux_raw/runtime/tls.rs8
-rw-r--r--vendor/rustix/src/backend/linux_raw/termios/syscalls.rs50
-rw-r--r--vendor/rustix/src/backend/linux_raw/termios/types.rs37
-rw-r--r--vendor/rustix/src/backend/linux_raw/thread/syscalls.rs62
-rw-r--r--vendor/rustix/src/backend/linux_raw/time/syscalls.rs41
-rw-r--r--vendor/rustix/src/backend/linux_raw/vdso.rs4
-rw-r--r--vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs14
-rw-r--r--vendor/rustix/src/backend/linux_raw/weak.rs228
28 files changed, 1255 insertions, 468 deletions
diff --git a/vendor/rustix/src/backend/linux_raw/c.rs b/vendor/rustix/src/backend/linux_raw/c.rs
index a6f0b8ff6..e7263305a 100644
--- a/vendor/rustix/src/backend/linux_raw/c.rs
+++ b/vendor/rustix/src/backend/linux_raw/c.rs
@@ -9,21 +9,23 @@ pub(crate) use linux_raw_sys::ctypes::*;
pub(crate) use linux_raw_sys::errno::EINVAL;
pub(crate) use linux_raw_sys::general::{
AF_DECnet, __kernel_sa_family_t as sa_family_t, __kernel_sockaddr_storage as sockaddr_storage,
- in6_addr, in_addr, iovec, ip_mreq, ipv6_mreq, linger, sockaddr, sockaddr_in, sockaddr_in6,
- sockaddr_un, socklen_t, AF_APPLETALK, AF_ASH, AF_ATMPVC, AF_ATMSVC, AF_AX25, AF_BLUETOOTH,
- AF_BRIDGE, AF_CAN, AF_ECONET, AF_IEEE802154, AF_INET, AF_INET6, AF_IPX, AF_IRDA, AF_ISDN,
- AF_IUCV, AF_KEY, AF_LLC, AF_NETBEUI, AF_NETLINK, AF_NETROM, AF_PACKET, AF_PHONET, AF_PPPOX,
- AF_RDS, AF_ROSE, AF_RXRPC, AF_SECURITY, AF_SNA, AF_TIPC, AF_UNIX, AF_UNSPEC, AF_WANPIPE,
- AF_X25, IPPROTO_AH, IPPROTO_BEETPH, IPPROTO_COMP, IPPROTO_DCCP, IPPROTO_EGP, IPPROTO_ENCAP,
- IPPROTO_ESP, IPPROTO_ETHERNET, IPPROTO_FRAGMENT, IPPROTO_GRE, IPPROTO_ICMP, IPPROTO_ICMPV6,
- IPPROTO_IDP, IPPROTO_IGMP, IPPROTO_IP, IPPROTO_IPIP, IPPROTO_IPV6, IPPROTO_MH, IPPROTO_MPLS,
- IPPROTO_MPTCP, IPPROTO_MTP, IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW, IPPROTO_ROUTING,
- IPPROTO_RSVP, IPPROTO_SCTP, IPPROTO_TCP, IPPROTO_TP, IPPROTO_UDP, IPPROTO_UDPLITE,
- IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY, IP_ADD_MEMBERSHIP,
- IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL, MSG_CMSG_CLOEXEC, MSG_CONFIRM,
- MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_ERRQUEUE, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PEEK,
- MSG_TRUNC, MSG_WAITALL, O_CLOEXEC, O_NONBLOCK, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM,
- SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_LINGER,
+ in6_addr, in_addr, iovec, ip_mreq, ipv6_mreq, linger, siginfo_t, sockaddr, sockaddr_in,
+ sockaddr_in6, sockaddr_un, socklen_t, AF_APPLETALK, AF_ASH, AF_ATMPVC, AF_ATMSVC, AF_AX25,
+ AF_BLUETOOTH, AF_BRIDGE, AF_CAN, AF_ECONET, AF_IEEE802154, AF_INET, AF_INET6, AF_IPX, AF_IRDA,
+ AF_ISDN, AF_IUCV, AF_KEY, AF_LLC, AF_NETBEUI, AF_NETLINK, AF_NETROM, AF_PACKET, AF_PHONET,
+ AF_PPPOX, AF_RDS, AF_ROSE, AF_RXRPC, AF_SECURITY, AF_SNA, AF_TIPC, AF_UNIX, AF_UNSPEC,
+ AF_WANPIPE, AF_X25, IPPROTO_AH, IPPROTO_BEETPH, IPPROTO_COMP, IPPROTO_DCCP, IPPROTO_EGP,
+ IPPROTO_ENCAP, IPPROTO_ESP, IPPROTO_ETHERNET, IPPROTO_FRAGMENT, IPPROTO_GRE, IPPROTO_ICMP,
+ IPPROTO_ICMPV6, IPPROTO_IDP, IPPROTO_IGMP, IPPROTO_IP, IPPROTO_IPIP, IPPROTO_IPV6, IPPROTO_MH,
+ IPPROTO_MPLS, IPPROTO_MPTCP, IPPROTO_MTP, IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW,
+ IPPROTO_ROUTING, IPPROTO_RSVP, IPPROTO_SCTP, IPPROTO_TCP, IPPROTO_TP, IPPROTO_UDP,
+ IPPROTO_UDPLITE, IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY,
+ IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL,
+ MSG_CMSG_CLOEXEC, MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_ERRQUEUE, MSG_MORE,
+ MSG_NOSIGNAL, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, O_CLOEXEC, O_NONBLOCK,
+ O_NONBLOCK as PIDFD_NONBLOCK, P_ALL, P_PID, P_PIDFD, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM,
+ SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_ERROR, SO_LINGER,
SO_PASSCRED, SO_RCVTIMEO_NEW, SO_RCVTIMEO_OLD, SO_REUSEADDR, SO_SNDTIMEO_NEW, SO_SNDTIMEO_OLD,
SO_TYPE, TCP_NODELAY,
};
+pub(crate) use linux_raw_sys::general::{NFS_SUPER_MAGIC, PROC_SUPER_MAGIC, UTIME_NOW, UTIME_OMIT};
diff --git a/vendor/rustix/src/backend/linux_raw/conv.rs b/vendor/rustix/src/backend/linux_raw/conv.rs
index 7e09cdf80..b9fe725bb 100644
--- a/vendor/rustix/src/backend/linux_raw/conv.rs
+++ b/vendor/rustix/src/backend/linux_raw/conv.rs
@@ -15,12 +15,12 @@
use super::c;
use super::fd::{AsRawFd, BorrowedFd, FromRawFd, RawFd};
-#[cfg(not(debug_assertions))]
-use super::io::errno::decode_usize_infallible;
#[cfg(feature = "runtime")]
use super::io::errno::try_decode_error;
#[cfg(target_pointer_width = "64")]
use super::io::errno::try_decode_u64;
+#[cfg(not(debug_assertions))]
+use super::io::errno::{decode_c_uint_infallible, decode_usize_infallible};
use super::io::errno::{
try_decode_c_int, try_decode_c_uint, try_decode_raw_fd, try_decode_usize, try_decode_void,
try_decode_void_star,
@@ -143,7 +143,7 @@ impl<'a, Num: ArgNumber> From<Option<&'a CStr>> for ArgReg<'a, Num> {
impl<'a, Num: ArgNumber> From<BorrowedFd<'a>> for ArgReg<'a, Num> {
#[inline]
fn from(fd: BorrowedFd<'a>) -> Self {
- // Safety: `BorrowedFd` ensures that the file descriptor is valid, and the
+ // SAFETY: `BorrowedFd` ensures that the file descriptor is valid, and the
// lifetime parameter on the resulting `ArgReg` ensures that the result is
// bounded by the `BorrowedFd`'s lifetime.
unsafe { raw_fd(fd.as_raw_fd()) }
@@ -314,6 +314,22 @@ impl<'a, Num: ArgNumber> From<crate::fs::AtFlags> for ArgReg<'a, Num> {
}
#[cfg(feature = "fs")]
+impl<'a, Num: ArgNumber> From<crate::fs::inotify::CreateFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::inotify::CreateFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "fs")]
+impl<'a, Num: ArgNumber> From<crate::fs::inotify::WatchFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::fs::inotify::WatchFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+#[cfg(feature = "fs")]
impl<'a, Num: ArgNumber> From<crate::fs::MemfdFlags> for ArgReg<'a, Num> {
#[inline]
fn from(flags: crate::fs::MemfdFlags) -> Self {
@@ -665,6 +681,38 @@ impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> {
}
}
+#[cfg(feature = "fs")]
+#[cfg(any(target_os = "android", target_os = "linux"))]
+impl<'a, Num: ArgNumber> From<crate::backend::fs::types::MountFlagsArg> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::backend::fs::types::MountFlagsArg) -> Self {
+ c_uint(flags.0)
+ }
+}
+
+#[cfg(feature = "fs")]
+#[cfg(any(target_os = "android", target_os = "linux"))]
+impl<'a, Num: ArgNumber> From<crate::backend::fs::types::UnmountFlags> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(flags: crate::backend::fs::types::UnmountFlags) -> Self {
+ c_uint(flags.bits())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::process::Uid> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(t: crate::process::Uid) -> Self {
+ c_uint(t.as_raw())
+ }
+}
+
+impl<'a, Num: ArgNumber> From<crate::process::Gid> for ArgReg<'a, Num> {
+ #[inline]
+ fn from(t: crate::process::Gid) -> Self {
+ c_uint(t.as_raw())
+ }
+}
+
/// Convert a `usize` returned from a syscall that effectively returns `()` on
/// success.
///
@@ -754,6 +802,25 @@ pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize {
}
}
+/// Convert a `c_uint` returned from a syscall that effectively always
+/// returns a `c_uint`.
+///
+/// # Safety
+///
+/// This function must only be used with return values from infallible
+/// syscalls.
+#[inline]
+pub(super) unsafe fn ret_c_uint_infallible(raw: RetReg<R0>) -> c::c_uint {
+ #[cfg(debug_assertions)]
+ {
+ try_decode_c_uint(raw).unwrap()
+ }
+ #[cfg(not(debug_assertions))]
+ {
+ decode_c_uint_infallible(raw)
+ }
+}
+
/// Convert a `usize` returned from a syscall that effectively returns an
/// `OwnedFd` on success.
///
diff --git a/vendor/rustix/src/backend/linux_raw/fs/inotify.rs b/vendor/rustix/src/backend/linux_raw/fs/inotify.rs
new file mode 100644
index 000000000..4221565a6
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/fs/inotify.rs
@@ -0,0 +1,108 @@
+//! inotify support for working with inotifies
+
+use super::super::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
+ 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;
+ }
+}
+
+bitflags! {
+ /// `IN*` for use with [`inotify_add_watch`].
+ ///
+ /// [`inotify_add_watch`]: crate::fs::inotify::inotify_add_watch
+ #[derive(Default)]
+ 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;
+ }
+}
+
+/// `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> {
+ 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.
+pub fn inotify_add_watch<P: crate::path::Arg>(
+ inot: BorrowedFd<'_>,
+ path: P,
+ flags: WatchFlags,
+) -> io::Result<i32> {
+ let path = path.as_cow_c_str().unwrap();
+ 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")]
+pub fn inotify_remove_watch(inot: BorrowedFd<'_>, wd: i32) -> io::Result<()> {
+ syscalls::inotify_rm_watch(inot, wd)
+}
diff --git a/vendor/rustix/src/backend/linux_raw/fs/mod.rs b/vendor/rustix/src/backend/linux_raw/fs/mod.rs
index 015c6baec..acf43ce4f 100644
--- a/vendor/rustix/src/backend/linux_raw/fs/mod.rs
+++ b/vendor/rustix/src/backend/linux_raw/fs/mod.rs
@@ -1,4 +1,5 @@
pub(crate) mod dir;
+pub mod inotify;
pub(crate) mod makedev;
pub(crate) mod syscalls;
pub(crate) mod types;
diff --git a/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs b/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs
index ff58f0a7b..8bd9ccc27 100644
--- a/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs
+++ b/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs
@@ -10,7 +10,7 @@
use super::super::c;
use super::super::conv::{
by_ref, c_int, c_uint, dev_t, oflags_for_open_how, opt_mut, pass_usize, raw_fd, ret, ret_c_int,
- ret_c_uint, ret_owned_fd, ret_usize, size_of, slice_mut, zero,
+ ret_c_uint, ret_infallible, ret_owned_fd, ret_usize, size_of, slice_mut, zero,
};
#[cfg(target_pointer_width = "64")]
use super::super::conv::{loff_t, loff_t_from_u64, ret_u64};
@@ -24,12 +24,13 @@ use crate::fd::AsFd;
use crate::fd::{BorrowedFd, OwnedFd};
use crate::ffi::CStr;
use crate::fs::{
- Access, Advice, AtFlags, FallocateFlags, FileType, FlockOperation, MemfdFlags, Mode, OFlags,
- RenameFlags, ResolveFlags, SealFlags, Stat, StatFs, StatVfs, StatVfsMountFlags, StatxFlags,
- Timestamps,
+ inotify, Access, Advice, AtFlags, FallocateFlags, FileType, FlockOperation, MemfdFlags, Mode,
+ OFlags, RenameFlags, ResolveFlags, SealFlags, Stat, StatFs, StatVfs, StatVfsMountFlags,
+ StatxFlags, Timestamps,
};
use crate::io::{self, SeekFrom};
use crate::process::{Gid, Uid};
+#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
use core::convert::TryInto;
use core::mem::MaybeUninit;
#[cfg(target_arch = "mips64")]
@@ -37,7 +38,8 @@ use linux_raw_sys::general::stat as linux_stat64;
use linux_raw_sys::general::{
__kernel_fsid_t, __kernel_timespec, open_how, statx, AT_EACCESS, AT_FDCWD, AT_REMOVEDIR,
AT_SYMLINK_NOFOLLOW, F_ADD_SEALS, F_GETFL, F_GETLEASE, F_GETOWN, F_GETPIPE_SZ, F_GETSIG,
- F_GET_SEALS, F_SETFL, F_SETPIPE_SZ, SEEK_CUR, SEEK_END, SEEK_SET, STATX__RESERVED,
+ F_GET_SEALS, F_SETFL, F_SETPIPE_SZ, SEEK_CUR, SEEK_DATA, SEEK_END, SEEK_HOLE, SEEK_SET,
+ STATX__RESERVED,
};
#[cfg(target_pointer_width = "32")]
use {
@@ -136,7 +138,18 @@ pub(crate) fn chmod(filename: &CStr, mode: Mode) -> io::Result<()> {
}
#[inline]
-pub(crate) fn chmodat(dirfd: BorrowedFd<'_>, filename: &CStr, mode: Mode) -> io::Result<()> {
+pub(crate) fn chmodat(
+ dirfd: BorrowedFd<'_>,
+ filename: &CStr,
+ mode: Mode,
+ flags: AtFlags,
+) -> io::Result<()> {
+ if flags == AtFlags::SYMLINK_NOFOLLOW {
+ return Err(io::Errno::OPNOTSUPP);
+ }
+ if !flags.is_empty() {
+ return Err(io::Errno::INVAL);
+ }
unsafe { ret(syscall_readonly!(__NR_fchmodat, dirfd, filename, mode)) }
}
@@ -214,6 +227,10 @@ pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result<u64> {
}
SeekFrom::End(offset) => (SEEK_END, offset),
SeekFrom::Current(offset) => (SEEK_CUR, offset),
+ #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))]
+ SeekFrom::Data(offset) => (SEEK_DATA, offset),
+ #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))]
+ SeekFrom::Hole(offset) => (SEEK_HOLE, offset),
};
_seek(fd, offset, whence)
}
@@ -404,7 +421,23 @@ pub(crate) fn fdatasync(fd: BorrowedFd<'_>) -> io::Result<()> {
#[inline]
pub(crate) fn flock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::Result<()> {
- unsafe { ret(syscall!(__NR_flock, fd, c_uint(operation as c::c_uint))) }
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_flock,
+ fd,
+ c_uint(operation as c::c_uint)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn syncfs(fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_syncfs, fd)) }
+}
+
+#[inline]
+pub(crate) fn sync() {
+ unsafe { ret_infallible(syscall_readonly!(__NR_sync)) }
}
#[inline]
@@ -1017,6 +1050,58 @@ pub(crate) fn fcntl_add_seals(fd: BorrowedFd<'_>, seals: SealFlags) -> io::Resul
}
#[inline]
+pub(crate) fn fcntl_lock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::Result<()> {
+ #[cfg(target_pointer_width = "64")]
+ use linux_raw_sys::general::{flock, F_SETLK, F_SETLKW};
+ #[cfg(target_pointer_width = "32")]
+ use linux_raw_sys::general::{flock64 as flock, F_SETLK64 as F_SETLK, F_SETLKW64 as F_SETLKW};
+ use linux_raw_sys::general::{F_RDLCK, F_UNLCK, F_WRLCK};
+
+ let (cmd, l_type) = match operation {
+ FlockOperation::LockShared => (F_SETLKW, F_RDLCK),
+ FlockOperation::LockExclusive => (F_SETLKW, F_WRLCK),
+ FlockOperation::Unlock => (F_SETLKW, F_UNLCK),
+ FlockOperation::NonBlockingLockShared => (F_SETLK, F_RDLCK),
+ FlockOperation::NonBlockingLockExclusive => (F_SETLK, F_WRLCK),
+ FlockOperation::NonBlockingUnlock => (F_SETLK, F_UNLCK),
+ };
+
+ unsafe {
+ let lock = flock {
+ l_type: l_type as _,
+
+ // When `l_len` is zero, this locks all the bytes from
+ // `l_whence`/`l_start` to the end of the file, even as the
+ // file grows dynamically.
+ l_whence: SEEK_SET as _,
+ l_start: 0,
+ l_len: 0,
+
+ ..core::mem::zeroed()
+ };
+
+ #[cfg(target_pointer_width = "32")]
+ {
+ ret(syscall_readonly!(
+ __NR_fcntl64,
+ fd,
+ c_uint(cmd),
+ by_ref(&lock)
+ ))
+ }
+ #[cfg(target_pointer_width = "64")]
+ {
+ ret(syscall_readonly!(
+ __NR_fcntl,
+ fd,
+ c_uint(cmd),
+ by_ref(&lock)
+ ))
+ }
+ }
+}
+
+#[inline]
pub(crate) fn rename(oldname: &CStr, newname: &CStr) -> io::Result<()> {
#[cfg(target_arch = "riscv64")]
unsafe {
@@ -1196,6 +1281,16 @@ pub(crate) fn getdents(fd: BorrowedFd<'_>, dirent: &mut [u8]) -> io::Result<usiz
}
#[inline]
+pub(crate) fn getdents_uninit(
+ fd: BorrowedFd<'_>,
+ dirent: &mut [MaybeUninit<u8>],
+) -> io::Result<usize> {
+ let (dirent_addr_mut, dirent_len) = slice_mut(dirent);
+
+ unsafe { ret_usize(syscall!(__NR_getdents64, fd, dirent_addr_mut, dirent_len)) }
+}
+
+#[inline]
pub(crate) fn utimensat(
dirfd: BorrowedFd<'_>,
pathname: &CStr,
@@ -1321,20 +1416,7 @@ pub(crate) fn copy_file_range(
off_in: Option<&mut u64>,
fd_out: BorrowedFd<'_>,
off_out: Option<&mut u64>,
- len: u64,
-) -> io::Result<u64> {
- let len: usize = len.try_into().unwrap_or(usize::MAX);
- _copy_file_range(fd_in, off_in, fd_out, off_out, len, 0).map(|result| result as u64)
-}
-
-#[inline]
-fn _copy_file_range(
- fd_in: BorrowedFd<'_>,
- off_in: Option<&mut u64>,
- fd_out: BorrowedFd<'_>,
- off_out: Option<&mut u64>,
len: usize,
- flags: c::c_uint,
) -> io::Result<usize> {
unsafe {
ret_usize(syscall!(
@@ -1344,7 +1426,7 @@ fn _copy_file_range(
fd_out,
opt_mut(off_out),
pass_usize(len),
- c_uint(flags)
+ c_uint(0)
))
}
}
@@ -1382,3 +1464,49 @@ pub(crate) fn sendfile(
))
}
}
+
+#[inline]
+#[cfg(any(target_os = "android", target_os = "linux"))]
+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(syscall_readonly!(
+ __NR_mount,
+ source,
+ target,
+ file_system_type,
+ flags,
+ data
+ ))
+ }
+}
+
+#[inline]
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) fn unmount(target: &CStr, flags: super::types::UnmountFlags) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_umount2, target, flags)) }
+}
+
+#[inline]
+pub(crate) fn inotify_init1(flags: inotify::CreateFlags) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(syscall_readonly!(__NR_inotify_init1, flags)) }
+}
+
+#[inline]
+pub(crate) fn inotify_add_watch(
+ infd: BorrowedFd<'_>,
+ path: &CStr,
+ flags: inotify::WatchFlags,
+) -> io::Result<i32> {
+ unsafe { ret_c_int(syscall_readonly!(__NR_inotify_add_watch, infd, path, flags)) }
+}
+
+#[inline]
+pub(crate) fn inotify_rm_watch(infd: BorrowedFd<'_>, wfd: i32) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_inotify_rm_watch, infd, c_int(wfd))) }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/fs/types.rs b/vendor/rustix/src/backend/linux_raw/fs/types.rs
index a8d225ede..9bafb8ac0 100644
--- a/vendor/rustix/src/backend/linux_raw/fs/types.rs
+++ b/vendor/rustix/src/backend/linux_raw/fs/types.rs
@@ -122,6 +122,32 @@ impl Mode {
}
}
+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`].
///
@@ -198,6 +224,9 @@ bitflags! {
/// `O_NOATIME`
const NOATIME = linux_raw_sys::general::O_NOATIME;
+
+ /// `O_DIRECT`
+ const DIRECT = linux_raw_sys::general::O_DIRECT;
}
}
@@ -515,9 +544,10 @@ bitflags! {
}
}
-/// `LOCK_*` constants for use with [`flock`]
+/// `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 {
@@ -637,10 +667,106 @@ pub type FsWord = linux_raw_sys::general::__fsword_t;
#[cfg(target_arch = "mips64")]
pub type FsWord = i64;
-pub use linux_raw_sys::general::{UTIME_NOW, UTIME_OMIT};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `MS_*` constants for use with [`mount`].
+ ///
+ /// [`mount`]: crate::fs::mount
+ pub struct MountFlags: c::c_uint {
+ /// `MS_BIND`
+ const BIND = linux_raw_sys::general::MS_BIND;
+
+ /// `MS_DIRSYNC`
+ const DIRSYNC = linux_raw_sys::general::MS_DIRSYNC;
+
+ /// `MS_LAZYTIME`
+ const LAZYTIME = linux_raw_sys::general::MS_LAZYTIME;
+
+ /// `MS_MANDLOCK`
+ #[doc(alias = "MANDLOCK")]
+ const PERMIT_MANDATORY_FILE_LOCKING = linux_raw_sys::general::MS_MANDLOCK;
+
+ /// `MS_NOATIME`
+ const NOATIME = linux_raw_sys::general::MS_NOATIME;
+
+ /// `MS_NODEV`
+ const NODEV = linux_raw_sys::general::MS_NODEV;
+
+ /// `MS_NODIRATIME`
+ const NODIRATIME = linux_raw_sys::general::MS_NODIRATIME;
+
+ /// `MS_NOEXEC`
+ const NOEXEC = linux_raw_sys::general::MS_NOEXEC;
+
+ /// `MS_NOSUID`
+ const NOSUID = linux_raw_sys::general::MS_NOSUID;
+
+ /// `MS_RDONLY`
+ const RDONLY = linux_raw_sys::general::MS_RDONLY;
-/// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem.
-pub const PROC_SUPER_MAGIC: FsWord = linux_raw_sys::general::PROC_SUPER_MAGIC as FsWord;
+ /// `MS_REC`
+ const REC = linux_raw_sys::general::MS_REC;
-/// `NFS_SUPER_MAGIC`—The magic number for the NFS filesystem.
-pub const NFS_SUPER_MAGIC: FsWord = linux_raw_sys::general::NFS_SUPER_MAGIC as FsWord;
+ /// `MS_RELATIME`
+ const RELATIME = linux_raw_sys::general::MS_RELATIME;
+
+ /// `MS_SILENT`
+ const SILENT = linux_raw_sys::general::MS_SILENT;
+
+ /// `MS_STRICTATIME`
+ const STRICTATIME = linux_raw_sys::general::MS_STRICTATIME;
+
+ /// `MS_SYNCHRONOUS`
+ const SYNCHRONOUS = linux_raw_sys::general::MS_SYNCHRONOUS;
+
+ /// `MS_NOSYMFOLLOW`
+ const NOSYMFOLLOW = linux_raw_sys::general::MS_NOSYMFOLLOW;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `MS_*` constants for use with [`change_mount`].
+ ///
+ /// [`change_mount`]: crate::fs::mount::change_mount
+ pub struct MountPropagationFlags: c::c_uint {
+ /// `MS_SHARED`
+ const SHARED = linux_raw_sys::general::MS_SHARED;
+ /// `MS_PRIVATE`
+ const PRIVATE = linux_raw_sys::general::MS_PRIVATE;
+ /// `MS_SLAVE`
+ const SLAVE = linux_raw_sys::general::MS_SLAVE;
+ /// `MS_UNBINDABLE`
+ const UNBINDABLE = linux_raw_sys::general::MS_UNBINDABLE;
+ /// `MS_REC`
+ const REC = linux_raw_sys::general::MS_REC;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ pub(crate) struct InternalMountFlags: c::c_uint {
+ const REMOUNT = linux_raw_sys::general::MS_REMOUNT;
+ const MOVE = linux_raw_sys::general::MS_MOVE;
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(crate) struct MountFlagsArg(pub(crate) c::c_uint);
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+bitflags! {
+ /// `MNT_*` constants for use with [`unmount`].
+ ///
+ /// [`unmount`]: crate::fs::mount::unmount
+ pub struct UnmountFlags: c::c_uint {
+ /// `MNT_FORCE`
+ const FORCE = linux_raw_sys::general::MNT_FORCE;
+ /// `MNT_DETACH`
+ const DETACH = linux_raw_sys::general::MNT_DETACH;
+ /// `MNT_EXPIRE`
+ const EXPIRE = linux_raw_sys::general::MNT_EXPIRE;
+ /// `UMOUNT_NOFOLLOW`
+ const NOFOLLOW = linux_raw_sys::general::UMOUNT_NOFOLLOW;
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/io/epoll.rs b/vendor/rustix/src/backend/linux_raw/io/epoll.rs
index d55ad75b1..3fc6462a2 100644
--- a/vendor/rustix/src/backend/linux_raw/io/epoll.rs
+++ b/vendor/rustix/src/backend/linux_raw/io/epoll.rs
@@ -6,17 +6,17 @@
//!
//! # Examples
//!
-//! ```rust,no_run
+//! ```no_run
//! # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
//! # #[cfg(feature = "net")]
//! # fn main() -> std::io::Result<()> {
//! use io_lifetimes::AsFd;
-//! use rustix::io::epoll::{self, Epoll};
-//! use rustix::io::{ioctl_fionbio, read, write};
+//! use rustix::io::{epoll, ioctl_fionbio, read, write};
//! use rustix::net::{
//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4,
//! SocketType,
//! };
+//! use std::collections::HashMap;
//! use std::os::unix::io::AsRawFd;
//!
//! // Create a socket and listen on it.
@@ -26,29 +26,40 @@
//!
//! // Create an epoll object. Using `Owning` here means the epoll object will
//! // take ownership of the file descriptors registered with it.
-//! let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC, epoll::Owning::new())?;
-//!
-//! // Remember the socket raw fd, which we use for comparisons only.
-//! let raw_listen_sock = listen_sock.as_fd().as_raw_fd();
+//! let epoll = epoll::epoll_create(epoll::CreateFlags::CLOEXEC)?;
//!
//! // Register the socket with the epoll object.
-//! epoll.add(listen_sock, epoll::EventFlags::IN)?;
+//! epoll::epoll_add(&epoll, &listen_sock, 1, epoll::EventFlags::IN)?;
+//!
+//! // Keep track of the sockets we've opened.
+//! let mut next_id = 2;
+//! let mut sockets = HashMap::new();
//!
//! // Process events.
//! let mut event_list = epoll::EventVec::with_capacity(4);
//! loop {
-//! epoll.wait(&mut event_list, -1)?;
+//! epoll::epoll_wait(&epoll, &mut event_list, -1)?;
//! for (_event_flags, target) in &event_list {
-//! if target.as_raw_fd() == raw_listen_sock {
+//! if target == 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(&*target)?;
+//! let conn_sock = accept(&listen_sock)?;
//! ioctl_fionbio(&conn_sock, true)?;
-//! epoll.add(conn_sock, epoll::EventFlags::OUT | epoll::EventFlags::ET)?;
+//! epoll::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 += 1;
//! } else {
//! // Write a message to the stream and then unregister it.
-//! write(&*target, b"hello\n")?;
-//! let _ = epoll.del(target)?;
+//! let target = sockets.remove(&target).unwrap();
+//! write(&target, b"hello\n")?;
+//! let _ = epoll::epoll_del(&epoll, &target)?;
//! }
//! }
//! }
@@ -60,17 +71,11 @@
#![allow(unsafe_code)]
use super::super::c;
-use crate::backend::io::syscalls::{epoll_add, epoll_create, epoll_del, epoll_mod, epoll_wait};
-use crate::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
-#[cfg(feature = "std")]
-use crate::fd::{FromRawFd, IntoRawFd};
+use crate::backend::io::syscalls;
+use crate::fd::{AsFd, AsRawFd, OwnedFd};
use crate::io;
use alloc::vec::Vec;
use bitflags::bitflags;
-use core::fmt;
-use core::marker::PhantomData;
-use core::ops::Deref;
-use core::ptr::null;
bitflags! {
/// `EPOLL_*` for use with [`Epoll::new`].
@@ -99,6 +104,24 @@ bitflags! {
/// `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;
@@ -113,351 +136,127 @@ bitflags! {
}
}
-/// A reference to a `T`.
-pub struct Ref<'a, T> {
- t: T,
- _phantom: PhantomData<&'a T>,
-}
-
-impl<'a, T> Ref<'a, T> {
- #[inline]
- fn new(t: T) -> Self {
- Self {
- t,
- _phantom: PhantomData,
- }
- }
-
- #[inline]
- fn consume(self) -> T {
- self.t
- }
-}
-
-impl<'a, T> Deref for Ref<'a, T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &T {
- &self.t
- }
-}
-
-impl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.t.fmt(fmt)
- }
-}
-
-/// A trait for data stored within an [`Epoll`] instance.
-pub trait Context {
- /// The type of an element owned by this context.
- type Data;
-
- /// The type of a value used to refer to an element owned by this context.
- type Target: AsFd;
-
- /// Assume ownership of `data`, and returning a `Target`.
- fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target>;
-
- /// Encode `target` as a `u64`. The only requirement on this value is that
- /// it be decodable by `decode`.
- fn encode(&self, target: Ref<'_, Self::Target>) -> u64;
-
- /// Decode `raw`, which is a value encoded by `encode`, into a `Target`.
- ///
- /// # Safety
- ///
- /// `raw` must be a `u64` value returned from `encode`, from the same
- /// context, and within the context's lifetime.
- unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target>;
-
- /// Release ownership of the value referred to by `target` and return it.
- fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data;
-}
-
-/// A type implementing [`Context`] where the `Data` type is `BorrowedFd<'a>`.
-pub struct Borrowing<'a> {
- _phantom: PhantomData<BorrowedFd<'a>>,
-}
-
-impl<'a> Context for Borrowing<'a> {
- type Data = BorrowedFd<'a>;
- type Target = BorrowedFd<'a>;
-
- #[inline]
- fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
- Ref::new(data)
- }
-
- #[inline]
- fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
- target.as_raw_fd() as u64
- }
-
- #[inline]
- unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
- Ref::new(BorrowedFd::<'a>::borrow_raw(raw as RawFd))
- }
-
- #[inline]
- fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
- target.consume()
- }
-}
-
-/// A type implementing [`Context`] where the `Data` type is `T`, a type
-/// implementing `From<OwnedFd>` and `From<T> of OwnedFd`.
+/// `epoll_create1(flags)`—Creates a new `Epoll`.
///
-/// This may be used with [`OwnedFd`], or higher-level types like
-/// [`std::fs::File`] or [`std::net::TcpStream`].
-#[cfg(feature = "std")]
-pub struct Owning<'context, T: Into<OwnedFd> + From<OwnedFd>> {
- _phantom: PhantomData<&'context T>,
+/// 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 epoll_create(flags: CreateFlags) -> io::Result<OwnedFd> {
+ syscalls::epoll_create(flags)
}
-#[cfg(feature = "std")]
-impl<'context, T: Into<OwnedFd> + From<OwnedFd>> Owning<'context, T> {
- /// Creates a new empty `Owning`.
- #[allow(clippy::new_without_default)] // This is a specialized type that doesn't need to be generically constructible.
- #[inline]
- pub fn new() -> Self {
- Self {
- _phantom: PhantomData,
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> Context for Owning<'context, T> {
- type Data = T;
- type Target = BorrowedFd<'context>;
-
- #[inline]
- fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
- let raw_fd = data.into().into_raw_fd();
- // Safety: `epoll` will assign ownership of the file descriptor to the
- // kernel epoll object. We use `Into<OwnedFd>`+`IntoRawFd` to consume
- // the `Data` and extract the raw file descriptor and then "borrow" it
- // with `borrow_raw` knowing that the borrow won't outlive the
- // kernel epoll object.
- unsafe { Ref::new(BorrowedFd::<'context>::borrow_raw(raw_fd)) }
- }
-
- #[inline]
- fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
- target.as_fd().as_raw_fd() as u64
- }
-
- #[inline]
- unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
- Ref::new(BorrowedFd::<'context>::borrow_raw(raw as RawFd))
- }
-
- #[inline]
- fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
- let raw_fd = target.consume().as_raw_fd();
-
- // Safety: The file descriptor was held by the kernel epoll object and
- // is now being released, so we can create a new `OwnedFd` that assumes
- // ownership.
- unsafe { T::from(io_lifetimes::OwnedFd::from_raw_fd(raw_fd)) }
- }
-}
-
-/// An "epoll", an interface to an OS object allowing one to repeatedly wait
-/// for events from a set of file descriptors efficiently.
-pub struct Epoll<Context: self::Context> {
- epoll_fd: OwnedFd,
- context: Context,
-}
-
-impl<Context: self::Context> Epoll<Context> {
- /// `epoll_create1(flags)`—Creates a new `Epoll`.
- ///
- /// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
- /// descriptor from being implicitly passed across `exec` boundaries.
- #[inline]
- #[doc(alias = "epoll_create1")]
- pub fn new(flags: CreateFlags, context: Context) -> io::Result<Self> {
- // Safety: We're calling `epoll_create1` via FFI and we know how it
- // behaves.
- Ok(Self {
- epoll_fd: epoll_create(flags)?,
- context,
- })
- }
-
- /// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an
- /// `Epoll`.
- ///
- /// This registers interest in any of the events set in `events` occurring
- /// on the file descriptor associated with `data`.
- #[doc(alias = "epoll_ctl")]
- pub fn add(
- &self,
- data: Context::Data,
- event_flags: EventFlags,
- ) -> io::Result<Ref<'_, Context::Target>> {
- // Safety: We're calling `epoll_ctl` via FFI and we know how it
- // behaves.
- unsafe {
- let target = self.context.acquire(data);
- let raw_fd = target.as_fd().as_raw_fd();
- let encoded = self.context.encode(target);
- epoll_add(
- self.epoll_fd.as_fd(),
- raw_fd,
- &linux_raw_sys::general::epoll_event {
- events: event_flags.bits(),
- data: encoded,
- },
- )?;
- Ok(self.context.decode(encoded))
- }
- }
-
- /// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in
- /// this `Epoll`.
- ///
- /// This sets the events of interest with `target` to `events`.
- #[doc(alias = "epoll_ctl")]
- pub fn mod_(
- &self,
- target: Ref<'_, Context::Target>,
- event_flags: EventFlags,
- ) -> io::Result<()> {
- let raw_fd = target.as_fd().as_raw_fd();
- let encoded = self.context.encode(target);
- // Safety: We're calling `epoll_ctl` via FFI and we know how it
- // behaves.
- unsafe {
- epoll_mod(
- self.epoll_fd.as_fd(),
- raw_fd,
- &linux_raw_sys::general::epoll_event {
- events: event_flags.bits(),
- data: encoded,
- },
- )
- }
- }
-
- /// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in
- /// this `Epoll`.
- ///
- /// This also returns the owning `Data`.
- #[doc(alias = "epoll_ctl")]
- pub fn del(&self, target: Ref<'_, Context::Target>) -> io::Result<Context::Data> {
- // Safety: We're calling `epoll_ctl` via FFI and we know how it
- // behaves.
- unsafe {
- let raw_fd = target.as_fd().as_raw_fd();
- epoll_del(self.epoll_fd.as_fd(), raw_fd)?;
- }
- Ok(self.context.release(target))
- }
-
- /// `epoll_wait(self, events, timeout)`—Waits for registered events of
- /// interest.
- ///
- /// For each event of interest, an element is written to `events`. On
- /// success, this returns the number of written elements.
- #[doc(alias = "epoll_wait")]
- pub fn wait<'context>(
- &'context self,
- event_list: &mut EventVec<'context, Context>,
- timeout: c::c_int,
- ) -> io::Result<()> {
- // Safety: We're calling `epoll_wait` via FFI and we know how it
- // behaves.
- unsafe {
- event_list.events.set_len(0);
- let nfds = epoll_wait(
- self.epoll_fd.as_fd(),
- event_list.events[..].as_mut_ptr().cast(),
- event_list.events.capacity(),
- timeout,
- )?;
- event_list.events.set_len(nfds);
- event_list.context = &self.context;
- }
-
- Ok(())
- }
-}
-
-#[cfg(feature = "std")]
-impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> AsRawFd for Epoll<Owning<'context, T>> {
- fn as_raw_fd(&self) -> RawFd {
- self.epoll_fd.as_raw_fd()
- }
-}
-
-#[cfg(feature = "std")]
-impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> IntoRawFd for Epoll<Owning<'context, T>> {
- fn into_raw_fd(self) -> RawFd {
- self.epoll_fd.into_raw_fd()
- }
-}
-
-#[cfg(feature = "std")]
-impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> FromRawFd for Epoll<Owning<'context, T>> {
- unsafe fn from_raw_fd(fd: RawFd) -> Self {
- Self {
- epoll_fd: OwnedFd::from_raw_fd(fd),
- context: Owning::new(),
- }
+/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an
+/// `Epoll`.
+///
+/// This registers interest in any of the events set in `events` occurring
+/// on the file descriptor associated with `data`.
+///
+/// Note that if `epoll_del` 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 `epoll_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 epoll_add(
+ epoll: impl AsFd,
+ source: impl AsFd,
+ data: u64,
+ 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(),
+ &linux_raw_sys::general::epoll_event {
+ events: event_flags.bits(),
+ data,
+ },
+ )
}
}
-#[cfg(feature = "std")]
-impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> AsFd for Epoll<Owning<'context, T>> {
- fn as_fd(&self) -> BorrowedFd<'_> {
- self.epoll_fd.as_fd()
+/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in
+/// this `Epoll`.
+///
+/// This sets the events of interest with `target` to `events`.
+#[doc(alias = "epoll_ctl")]
+pub fn epoll_mod(
+ epoll: impl AsFd,
+ source: impl AsFd,
+ data: u64,
+ 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,
+ &linux_raw_sys::general::epoll_event {
+ events: event_flags.bits(),
+ data,
+ },
+ )
}
}
-#[cfg(feature = "std")]
-impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> From<Epoll<Owning<'context, T>>>
- for OwnedFd
-{
- fn from(epoll: Epoll<Owning<'context, T>>) -> Self {
- epoll.epoll_fd
+/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in
+/// this `Epoll`.
+///
+/// This also returns the owning `Data`.
+#[doc(alias = "epoll_ctl")]
+pub fn epoll_del(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)
}
}
-#[cfg(feature = "std")]
-impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> From<OwnedFd>
- for Epoll<Owning<'context, T>>
-{
- fn from(fd: OwnedFd) -> Self {
- Self {
- epoll_fd: fd,
- context: Owning::new(),
- }
- }
+/// `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.
+pub fn epoll_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<'context, Context: self::Context> {
- iter: core::slice::Iter<'context, Event>,
- context: *const Context,
- _phantom: PhantomData<&'context Context>,
+pub struct Iter<'a> {
+ iter: core::slice::Iter<'a, Event>,
}
-impl<'context, Context: self::Context> Iterator for Iter<'context, Context> {
- type Item = (EventFlags, Ref<'context, Context::Target>);
+impl<'a> Iterator for Iter<'a> {
+ type Item = (EventFlags, u64);
fn next(&mut self) -> Option<Self::Item> {
- self.iter.next().map(|event| {
- // Safety: `self.context` is guaranteed to be valid because we hold
- // `'context` for it. And we know this event is associated with this
- // context because `wait` sets both.
- let decoded = unsafe { (*self.context).decode(event.encoded) };
-
- (event.event_flags, decoded)
- })
+ self.iter
+ .next()
+ .map(|event| (event.event_flags, event.data))
}
}
@@ -466,28 +265,22 @@ impl<'context, Context: self::Context> Iterator for Iter<'context, Context> {
#[cfg_attr(target_arch = "x86_64", repr(packed))]
struct Event {
// Match the layout of `linux_raw_sys::general::epoll_event`. We just use a
- // `u64` instead of the full union; `Context` implementations will simply
- // need to deal with casting the value into and out of the `u64`
- // themselves.
+ // `u64` instead of the full union.
event_flags: EventFlags,
- encoded: u64,
+ data: u64,
}
/// A vector of `Event`s, plus context for interpreting them.
-pub struct EventVec<'context, Context: self::Context> {
+pub struct EventVec {
events: Vec<Event>,
- context: *const Context,
- _phantom: PhantomData<&'context Context>,
}
-impl<'context, Context: self::Context> EventVec<'context, Context> {
+impl EventVec {
/// Constructs an `EventVec` with memory for `capacity` `Event`s.
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
events: Vec::with_capacity(capacity),
- context: null(),
- _phantom: PhantomData,
}
}
@@ -523,11 +316,9 @@ impl<'context, Context: self::Context> EventVec<'context, Context> {
/// Returns an iterator over the `Event`s in this `EventVec`.
#[inline]
- pub fn iter(&self) -> Iter<'_, Context> {
+ pub fn iter(&self) -> Iter<'_> {
Iter {
iter: self.events.iter(),
- context: self.context,
- _phantom: PhantomData,
}
}
@@ -544,9 +335,9 @@ impl<'context, Context: self::Context> EventVec<'context, Context> {
}
}
-impl<'context, Context: self::Context> IntoIterator for &'context EventVec<'context, Context> {
- type IntoIter = Iter<'context, Context>;
- type Item = (EventFlags, Ref<'context, Context::Target>);
+impl<'a> IntoIterator for &'a EventVec {
+ type IntoIter = Iter<'a>;
+ type Item = (EventFlags, u64);
#[inline]
fn into_iter(self) -> Self::IntoIter {
diff --git a/vendor/rustix/src/backend/linux_raw/io/errno.rs b/vendor/rustix/src/backend/linux_raw/io/errno.rs
index 5c7b2fcd5..b01910138 100644
--- a/vendor/rustix/src/backend/linux_raw/io/errno.rs
+++ b/vendor/rustix/src/backend/linux_raw/io/errno.rs
@@ -69,7 +69,7 @@ impl Errno {
// TODO: Use Range::contains, once that's `const`.
const_assert!(encoded >= 0xf001);
- // Safety: Linux syscalls return negated error values in the range
+ // SAFETY: Linux syscalls return negated error values in the range
// `-4095..0`, which we just asserted.
unsafe { Self(encoded) }
}
@@ -82,7 +82,7 @@ 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
+ // 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()) });
}
@@ -97,7 +97,7 @@ 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
+ // 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()) });
}
@@ -110,7 +110,7 @@ pub(in crate::backend) fn try_decode_c_uint<Num: RetNumber>(
#[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
+ // 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()) });
}
@@ -125,7 +125,7 @@ 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
+ // 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()) });
}
@@ -139,7 +139,7 @@ pub(in crate::backend) fn try_decode_void_star<Num: RetNumber>(
#[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
+ // 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()) });
}
@@ -236,6 +236,13 @@ pub(in crate::backend) fn decode_usize_infallible<Num: RetNumber>(raw: RetReg<Nu
raw.decode_usize()
}
+/// Return the contained `c_int` 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")]
diff --git a/vendor/rustix/src/backend/linux_raw/io/syscalls.rs b/vendor/rustix/src/backend/linux_raw/io/syscalls.rs
index 2cc7898af..3acf9ffdb 100644
--- a/vendor/rustix/src/backend/linux_raw/io/syscalls.rs
+++ b/vendor/rustix/src/backend/linux_raw/io/syscalls.rs
@@ -32,7 +32,7 @@ use linux_raw_sys::general::{
epoll_event, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD, F_DUPFD_CLOEXEC, F_GETFD, F_SETFD,
UIO_MAXIOV,
};
-use linux_raw_sys::ioctl::{BLKPBSZGET, BLKSSZGET, FIONBIO, FIONREAD, TIOCEXCL, TIOCNXCL};
+use linux_raw_sys::ioctl::{BLKPBSZGET, BLKSSZGET, FICLONE, FIONBIO, FIONREAD, TIOCEXCL, TIOCNXCL};
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
use {
super::super::conv::{opt_ref, size_of},
@@ -352,6 +352,11 @@ pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result<u32> {
}
}
+#[inline]
+pub(crate) fn ioctl_ficlone(fd: BorrowedFd<'_>, src_fd: BorrowedFd<'_>) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(FICLONE), src_fd)) }
+}
+
#[cfg(all(feature = "fs", feature = "net"))]
pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
let (mut read, mut write) = crate::fs::fd::_is_file_read_write(fd)?;
diff --git a/vendor/rustix/src/backend/linux_raw/io/types.rs b/vendor/rustix/src/backend/linux_raw/io/types.rs
index 51ab61d94..cb6c6acef 100644
--- a/vendor/rustix/src/backend/linux_raw/io/types.rs
+++ b/vendor/rustix/src/backend/linux_raw/io/types.rs
@@ -94,9 +94,10 @@ pub(crate) const STDOUT_FILENO: c::c_uint = linux_raw_sys::general::STDOUT_FILEN
pub(crate) const STDERR_FILENO: c::c_uint = linux_raw_sys::general::STDERR_FILENO;
/// A buffer type used 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.
+/// 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.
#[repr(transparent)]
pub struct IoSliceRaw<'a> {
_buf: c::iovec,
@@ -104,7 +105,7 @@ pub struct IoSliceRaw<'a> {
}
impl<'a> IoSliceRaw<'a> {
- /// Creates a new IoSlice wrapping a byte slice.
+ /// Creates a new `IoSlice` wrapping a byte slice.
pub fn from_slice(buf: &'a [u8]) -> Self {
IoSliceRaw {
_buf: c::iovec {
@@ -115,7 +116,7 @@ impl<'a> IoSliceRaw<'a> {
}
}
- /// Creates a new IoSlice wrapping a mutable byte slice.
+ /// Creates a new `IoSlice` wrapping a mutable byte slice.
pub fn from_slice_mut(buf: &'a mut [u8]) -> Self {
IoSliceRaw {
_buf: c::iovec {
diff --git a/vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs b/vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs
index 196676985..16655fe77 100644
--- a/vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs
+++ b/vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs
@@ -6,7 +6,7 @@
#![allow(unsafe_code)]
#![allow(clippy::undocumented_unsafe_blocks)]
-use super::super::conv::{by_mut, c_uint, pass_usize, ret, ret_c_uint, ret_owned_fd};
+use super::super::conv::{by_mut, c_uint, pass_usize, ret_c_uint, ret_owned_fd};
use crate::fd::{BorrowedFd, OwnedFd};
use crate::io;
use crate::io_uring::{io_uring_params, IoringEnterFlags, IoringRegisterOp};
@@ -29,8 +29,8 @@ pub(crate) unsafe fn io_uring_register(
opcode: IoringRegisterOp,
arg: *const c_void,
nr_args: u32,
-) -> io::Result<()> {
- ret(syscall_readonly!(
+) -> io::Result<u32> {
+ ret_c_uint(syscall_readonly!(
__NR_io_uring_register,
fd,
c_uint(opcode as u32),
diff --git a/vendor/rustix/src/backend/linux_raw/mod.rs b/vendor/rustix/src/backend/linux_raw/mod.rs
index e7e073e32..1b91fc3ab 100644
--- a/vendor/rustix/src/backend/linux_raw/mod.rs
+++ b/vendor/rustix/src/backend/linux_raw/mod.rs
@@ -14,6 +14,11 @@
//! such as which pointers are array slices, out parameters, or in-out
//! parameters, which integers are owned or borrowed file descriptors, etc.
+// Weak symbols used by the use-libc-auxv feature for glibc 2.15 support.
+#[cfg(feature = "use-libc-auxv")]
+#[macro_use]
+mod weak;
+
#[macro_use]
mod arch;
mod conv;
diff --git a/vendor/rustix/src/backend/linux_raw/net/addr.rs b/vendor/rustix/src/backend/linux_raw/net/addr.rs
index d5683f34e..b69c6deca 100644
--- a/vendor/rustix/src/backend/linux_raw/net/addr.rs
+++ b/vendor/rustix/src/backend/linux_raw/net/addr.rs
@@ -71,7 +71,7 @@ impl SocketAddrUnix {
if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char {
let end = len as usize - offsetof_sun_path();
let bytes = &self.unix.sun_path[..end];
- // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And
+ // 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(
@@ -91,7 +91,7 @@ impl SocketAddrUnix {
if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char {
let end = len as usize - offsetof_sun_path();
let bytes = &self.unix.sun_path[1..end];
- // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
+ // 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
diff --git a/vendor/rustix/src/backend/linux_raw/net/syscalls.rs b/vendor/rustix/src/backend/linux_raw/net/syscalls.rs
index 7b9947a03..6093cd3a5 100644
--- a/vendor/rustix/src/backend/linux_raw/net/syscalls.rs
+++ b/vendor/rustix/src/backend/linux_raw/net/syscalls.rs
@@ -1066,6 +1066,16 @@ pub(crate) mod sockopt {
}
#[inline]
+ pub(crate) fn get_socket_error(fd: BorrowedFd<'_>) -> io::Result<Result<(), crate::io::Errno>> {
+ let err: c::c_int = getsockopt(fd, c::SOL_SOCKET as _, c::SO_ERROR)?;
+ Ok(if err == 0 {
+ Ok(())
+ } else {
+ Err(crate::io::Errno::from_raw_os_error(err))
+ })
+ }
+
+ #[inline]
pub(crate) fn set_ip_ttl(fd: BorrowedFd<'_>, ttl: u32) -> io::Result<()> {
setsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL, ttl)
}
diff --git a/vendor/rustix/src/backend/linux_raw/param/auxv.rs b/vendor/rustix/src/backend/linux_raw/param/auxv.rs
index acdd9d0e7..741a0564f 100644
--- a/vendor/rustix/src/backend/linux_raw/param/auxv.rs
+++ b/vendor/rustix/src/backend/linux_raw/param/auxv.rs
@@ -77,7 +77,7 @@ pub(crate) fn linux_execfn() -> &'static CStr {
execfn = EXECFN.load(Relaxed);
}
- // Safety: We assume the `AT_EXECFN` value provided by the kernel is a
+ // SAFETY: We assume the `AT_EXECFN` value provided by the kernel is a
// valid pointer to a valid NUL-terminated array of bytes.
unsafe { CStr::from_ptr(execfn.cast()) }
}
@@ -102,7 +102,7 @@ pub(crate) fn exe_phdrs() -> (*const c::c_void, usize) {
pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] {
let (phdr, phnum) = exe_phdrs();
- // Safety: We assume the `AT_PHDR` and `AT_PHNUM` values provided by the
+ // SAFETY: We assume the `AT_PHDR` and `AT_PHNUM` values provided by the
// kernel form a valid slice.
unsafe { slice::from_raw_parts(phdr.cast(), phnum) }
}
@@ -177,7 +177,7 @@ fn init_from_auxv_file(auxv: OwnedFd) -> Option<()> {
buffer.resize(cur + n, 0_u8);
}
- // Safety: We loaded from an auxv file into the buffer.
+ // SAFETY: We loaded from an auxv file into the buffer.
unsafe { init_from_auxp(buffer.as_ptr().cast()) }
}
diff --git a/vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs b/vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs
index 1597fd727..a8e291ff6 100644
--- a/vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs
+++ b/vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs
@@ -5,14 +5,15 @@
//! This uses raw pointers to locate and read the kernel-provided auxv array.
#![allow(unsafe_code)]
-#[cfg(any(feature = "param", feature = "runtime"))]
-use super::super::c;
use super::super::elf::*;
#[cfg(feature = "param")]
use crate::ffi::CStr;
#[cfg(feature = "runtime")]
use core::slice;
+// `getauxval` wasn't supported in glibc until 2.16.
+weak!(fn getauxval(libc::c_ulong) -> *mut libc::c_void);
+
#[cfg(feature = "param")]
#[inline]
pub(crate) fn page_size() -> usize {
@@ -22,35 +23,39 @@ pub(crate) fn page_size() -> usize {
#[cfg(feature = "param")]
#[inline]
pub(crate) fn clock_ticks_per_second() -> u64 {
- unsafe { libc::getauxval(libc::AT_CLKTCK) as u64 }
+ unsafe { libc::sysconf(libc::_SC_CLK_TCK) as u64 }
}
#[cfg(feature = "param")]
#[inline]
pub(crate) fn linux_hwcap() -> (usize, usize) {
- unsafe {
- (
- libc::getauxval(libc::AT_HWCAP) as usize,
- libc::getauxval(libc::AT_HWCAP2) as usize,
- )
+ if let Some(libc_getauxval) = getauxval.get() {
+ unsafe {
+ let hwcap = libc_getauxval(libc::AT_HWCAP) as usize;
+ let hwcap2 = libc_getauxval(libc::AT_HWCAP2) as usize;
+ (hwcap, hwcap2)
+ }
+ } else {
+ (0, 0)
}
}
#[cfg(feature = "param")]
#[inline]
pub(crate) fn linux_execfn() -> &'static CStr {
- unsafe {
- let execfn = libc::getauxval(libc::AT_EXECFN) as *const c::c_char;
- CStr::from_ptr(execfn.cast())
+ if let Some(libc_getauxval) = getauxval.get() {
+ unsafe { CStr::from_ptr(libc_getauxval(libc::AT_EXECFN).cast()) }
+ } else {
+ cstr!("")
}
}
#[cfg(feature = "runtime")]
#[inline]
-pub(crate) fn exe_phdrs() -> (*const c::c_void, usize) {
+pub(crate) fn exe_phdrs() -> (*const libc::c_void, usize) {
unsafe {
(
- libc::getauxval(libc::AT_PHDR) as *const c::c_void,
+ libc::getauxval(libc::AT_PHDR) as *const libc::c_void,
libc::getauxval(libc::AT_PHNUM) as usize,
)
}
@@ -61,7 +66,7 @@ pub(crate) fn exe_phdrs() -> (*const c::c_void, usize) {
pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] {
let (phdr, phnum) = exe_phdrs();
- // Safety: We assume the `AT_PHDR` and `AT_PHNUM` values provided by the
+ // SAFETY: We assume the `AT_PHDR` and `AT_PHNUM` values provided by the
// kernel form a valid slice.
unsafe { slice::from_raw_parts(phdr.cast(), phnum) }
}
@@ -70,5 +75,9 @@ pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] {
/// so if we don't see it, this function returns a null pointer.
#[inline]
pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr {
- unsafe { libc::getauxval(linux_raw_sys::general::AT_SYSINFO_EHDR.into()) as *const Elf_Ehdr }
+ if let Some(libc_getauxval) = getauxval.get() {
+ unsafe { libc_getauxval(linux_raw_sys::general::AT_SYSINFO_EHDR.into()) as *const Elf_Ehdr }
+ } else {
+ core::ptr::null()
+ }
}
diff --git a/vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs b/vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs
index e9b89b500..49cb1457c 100644
--- a/vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs
+++ b/vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs
@@ -22,28 +22,28 @@ use linux_raw_sys::general::{
#[cfg(feature = "param")]
#[inline]
pub(crate) fn page_size() -> usize {
- // Safety: This is initialized during program startup.
+ // SAFETY: This is initialized during program startup.
unsafe { PAGE_SIZE }
}
#[cfg(feature = "param")]
#[inline]
pub(crate) fn clock_ticks_per_second() -> u64 {
- // Safety: This is initialized during program startup.
+ // SAFETY: This is initialized during program startup.
unsafe { CLOCK_TICKS_PER_SECOND as u64 }
}
#[cfg(feature = "param")]
#[inline]
pub(crate) fn linux_hwcap() -> (usize, usize) {
- // Safety: This is initialized during program startup.
+ // SAFETY: This is initialized during program startup.
unsafe { (HWCAP, HWCAP2) }
}
#[cfg(feature = "param")]
#[inline]
pub(crate) fn linux_execfn() -> &'static CStr {
- // Safety: This is initialized during program startup. And we
+ // SAFETY: This is initialized during program startup. And we
// assume it's a valid pointer to a NUL-terminated string.
unsafe { CStr::from_ptr(EXECFN.0.cast()) }
}
@@ -51,7 +51,7 @@ pub(crate) fn linux_execfn() -> &'static CStr {
#[cfg(feature = "runtime")]
#[inline]
pub(crate) fn exe_phdrs() -> (*const c_void, usize) {
- // Safety: This is initialized during program startup.
+ // SAFETY: This is initialized during program startup.
unsafe { (PHDR.0.cast(), PHNUM) }
}
@@ -60,7 +60,7 @@ pub(crate) fn exe_phdrs() -> (*const c_void, usize) {
pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] {
let (phdr, phnum) = exe_phdrs();
- // Safety: We assume the `AT_PHDR` and `AT_PHNUM` values provided by the
+ // SAFETY: We assume the `AT_PHDR` and `AT_PHNUM` values provided by the
// kernel form a valid slice.
unsafe { slice::from_raw_parts(phdr.cast(), phnum) }
}
@@ -69,7 +69,7 @@ pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] {
/// so if we don't see it, this function returns a null pointer.
#[inline]
pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr {
- // Safety: This is initialized during program startup.
+ // SAFETY: This is initialized during program startup.
unsafe { SYSINFO_EHDR.0 }
}
diff --git a/vendor/rustix/src/backend/linux_raw/process/cpu_set.rs b/vendor/rustix/src/backend/linux_raw/process/cpu_set.rs
index 10c5f478e..fc81859d8 100644
--- a/vendor/rustix/src/backend/linux_raw/process/cpu_set.rs
+++ b/vendor/rustix/src/backend/linux_raw/process/cpu_set.rs
@@ -1,3 +1,5 @@
+//! Rust implementation of the `CPU_*` macro API.
+
#![allow(non_snake_case)]
use super::types::RawCpuSet;
diff --git a/vendor/rustix/src/backend/linux_raw/process/syscalls.rs b/vendor/rustix/src/backend/linux_raw/process/syscalls.rs
index ac62e6944..f86f8e5b9 100644
--- a/vendor/rustix/src/backend/linux_raw/process/syscalls.rs
+++ b/vendor/rustix/src/backend/linux_raw/process/syscalls.rs
@@ -12,12 +12,13 @@ use super::super::conv::{
ret_infallible, ret_usize, ret_usize_infallible, size_of, slice_just_addr, slice_mut, zero,
};
use super::types::{RawCpuSet, RawUname};
-use crate::fd::BorrowedFd;
+use crate::backend::conv::ret_owned_fd;
+use crate::fd::{AsRawFd, BorrowedFd, OwnedFd};
use crate::ffi::CStr;
use crate::io;
use crate::process::{
- Cpuid, Gid, MembarrierCommand, MembarrierQuery, Pid, RawNonZeroPid, RawPid, Resource, Rlimit,
- Signal, Uid, WaitOptions, WaitStatus,
+ Cpuid, Gid, MembarrierCommand, MembarrierQuery, Pid, PidfdFlags, RawNonZeroPid, RawPid,
+ Resource, Rlimit, Signal, Uid, WaitId, WaitOptions, WaitStatus, WaitidOptions, WaitidStatus,
};
use core::convert::TryInto;
use core::mem::MaybeUninit;
@@ -27,6 +28,9 @@ use linux_raw_sys::general::{
__kernel_gid_t, __kernel_pid_t, __kernel_uid_t, membarrier_cmd, membarrier_cmd_flag, rlimit,
rlimit64, PRIO_PGRP, PRIO_PROCESS, PRIO_USER, RLIM64_INFINITY, RLIM_INFINITY,
};
+#[cfg(not(target_os = "wasi"))]
+#[cfg(feature = "fs")]
+use {super::super::conv::ret_c_uint_infallible, crate::fs::Mode};
#[inline]
pub(crate) fn chdir(filename: &CStr) -> io::Result<()> {
@@ -53,7 +57,7 @@ pub(crate) fn membarrier_query() -> MembarrierQuery {
c_uint(0)
)) {
Ok(query) => {
- // Safety: The safety of `from_bits_unchecked` is discussed
+ // SAFETY: The safety of `from_bits_unchecked` is discussed
// [here]. Our "source of truth" is Linux, and here, the
// `query` value is coming from Linux, so we know it only
// contains "source of truth" valid bits.
@@ -235,11 +239,20 @@ pub(crate) fn sched_yield() {
pub(crate) fn uname() -> RawUname {
let mut uname = MaybeUninit::<RawUname>::uninit();
unsafe {
- ret(syscall!(__NR_uname, &mut uname)).unwrap();
+ ret_infallible(syscall!(__NR_uname, &mut uname));
uname.assume_init()
}
}
+#[cfg(feature = "fs")]
+#[inline]
+pub(crate) fn umask(mode: Mode) -> Mode {
+ unsafe {
+ // TODO: Use `from_bits_retain` when we switch to bitflags 2.0.
+ Mode::from_bits_truncate(ret_c_uint_infallible(syscall_readonly!(__NR_umask, mode)))
+ }
+}
+
#[inline]
pub(crate) fn nice(inc: i32) -> io::Result<i32> {
let priority = if inc > -40 && inc < 40 {
@@ -516,6 +529,83 @@ pub(crate) fn _waitpid(
}
}
+#[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::PidFd(fd) => _waitid_pidfd(fd, options),
+ }
+}
+
+#[inline]
+fn _waitid_all(options: WaitidOptions) -> io::Result<Option<WaitidStatus>> {
+ let mut status = MaybeUninit::<c::siginfo_t>::uninit();
+ unsafe {
+ ret(syscall!(
+ __NR_waitid,
+ c_uint(c::P_ALL),
+ c_uint(0),
+ by_mut(&mut status),
+ c_int(options.bits() as _),
+ zero()
+ ))?
+ };
+
+ Ok(unsafe { cvt_waitid_status(status) })
+}
+
+#[inline]
+fn _waitid_pid(pid: Pid, options: WaitidOptions) -> io::Result<Option<WaitidStatus>> {
+ let mut status = MaybeUninit::<c::siginfo_t>::uninit();
+ unsafe {
+ ret(syscall!(
+ __NR_waitid,
+ c_uint(c::P_PID),
+ c_uint(Pid::as_raw(Some(pid))),
+ by_mut(&mut status),
+ c_int(options.bits() as _),
+ zero()
+ ))?
+ };
+
+ Ok(unsafe { cvt_waitid_status(status) })
+}
+
+#[inline]
+fn _waitid_pidfd(fd: BorrowedFd<'_>, options: WaitidOptions) -> io::Result<Option<WaitidStatus>> {
+ let mut status = MaybeUninit::<c::siginfo_t>::uninit();
+ unsafe {
+ ret(syscall!(
+ __NR_waitid,
+ c_uint(c::P_PIDFD),
+ c_uint(fd.as_raw_fd() as _),
+ by_mut(&mut status),
+ c_int(options.bits() as _),
+ zero()
+ ))?
+ };
+
+ 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.
+#[inline]
+unsafe fn cvt_waitid_status(status: MaybeUninit<c::siginfo_t>) -> Option<WaitidStatus> {
+ let status = status.assume_init();
+ if status.__bindgen_anon_1.__bindgen_anon_1.si_signo == 0 {
+ None
+ } else {
+ Some(WaitidStatus(status))
+ }
+}
+
#[cfg(feature = "runtime")]
#[inline]
pub(crate) fn exit_group(code: c::c_int) -> ! {
@@ -558,3 +648,14 @@ pub(crate) unsafe fn prctl(
) -> io::Result<c::c_int> {
ret_c_int(syscall!(__NR_prctl, c_int(option), arg2, arg3, arg4, arg5))
}
+
+#[inline]
+pub(crate) fn pidfd_open(pid: Pid, flags: PidfdFlags) -> io::Result<OwnedFd> {
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_pidfd_open,
+ pid,
+ c_int(flags.bits() as _)
+ ))
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/process/wait.rs b/vendor/rustix/src/backend/linux_raw/process/wait.rs
index 701b4ac0c..edc564a9f 100644
--- a/vendor/rustix/src/backend/linux_raw/process/wait.rs
+++ b/vendor/rustix/src/backend/linux_raw/process/wait.rs
@@ -1,7 +1,9 @@
// The functions replacing the C macros use the same names as in libc.
#![allow(non_snake_case)]
-pub(crate) use linux_raw_sys::general::{WCONTINUED, WNOHANG, WUNTRACED};
+pub(crate) use linux_raw_sys::general::{
+ WCONTINUED, WEXITED, WNOHANG, WNOWAIT, WSTOPPED, WUNTRACED,
+};
#[inline]
pub(crate) fn WIFSTOPPED(status: u32) -> bool {
diff --git a/vendor/rustix/src/backend/linux_raw/runtime/tls.rs b/vendor/rustix/src/backend/linux_raw/runtime/tls.rs
index 43ed25d7d..8cc156a71 100644
--- a/vendor/rustix/src/backend/linux_raw/runtime/tls.rs
+++ b/vendor/rustix/src/backend/linux_raw/runtime/tls.rs
@@ -1,3 +1,9 @@
+//! TLS utilities.
+//!
+//! # Safety
+//!
+//! This file contains code that reads the raw phdr array pointed to by the
+//! kernel-provided AUXV values.
#![allow(unsafe_code)]
use super::super::c;
@@ -18,7 +24,7 @@ pub(crate) fn startup_tls_info() -> StartupTlsInfo {
let phdrs = exe_phdrs_slice();
- // Safety: We assume the phdr array pointer and length the kernel provided
+ // SAFETY: We assume the phdr array pointer and length the kernel provided
// to the process describe a valid phdr array.
unsafe {
for phdr in phdrs {
diff --git a/vendor/rustix/src/backend/linux_raw/termios/syscalls.rs b/vendor/rustix/src/backend/linux_raw/termios/syscalls.rs
index a8dda5f81..f5643f3c3 100644
--- a/vendor/rustix/src/backend/linux_raw/termios/syscalls.rs
+++ b/vendor/rustix/src/backend/linux_raw/termios/syscalls.rs
@@ -42,6 +42,30 @@ pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
}
#[inline]
+#[cfg(any(
+ target_arch = "x86",
+ target_arch = "x86_64",
+ target_arch = "x32",
+ target_arch = "riscv64",
+ target_arch = "aarch64",
+ target_arch = "arm",
+ target_arch = "mips",
+ target_arch = "mips64",
+))]
+pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result<crate::termios::Termios2> {
+ unsafe {
+ let mut result = MaybeUninit::<crate::termios::Termios2>::uninit();
+ ret(syscall!(
+ __NR_ioctl,
+ fd,
+ c_uint(linux_raw_sys::ioctl::TCGETS2),
+ &mut result
+ ))?;
+ Ok(result.assume_init())
+ }
+}
+
+#[inline]
pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
unsafe {
let mut result = MaybeUninit::<__kernel_pid_t>::uninit();
@@ -78,6 +102,32 @@ pub(crate) fn tcsetattr(
}
#[inline]
+#[cfg(any(
+ target_arch = "x86",
+ target_arch = "x86_64",
+ target_arch = "x32",
+ target_arch = "riscv64",
+ target_arch = "aarch64",
+ target_arch = "arm",
+ target_arch = "mips",
+ target_arch = "mips64",
+))]
+pub(crate) fn tcsetattr2(
+ fd: BorrowedFd,
+ optional_actions: OptionalActions,
+ termios: &crate::termios::Termios2,
+) -> io::Result<()> {
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_ioctl,
+ fd,
+ c_uint(linux_raw_sys::ioctl::TCSETS2 + optional_actions as u32),
+ by_ref(termios)
+ ))
+ }
+}
+
+#[inline]
pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TCSBRK), c_uint(0))) }
}
diff --git a/vendor/rustix/src/backend/linux_raw/termios/types.rs b/vendor/rustix/src/backend/linux_raw/termios/types.rs
index a44f1eda5..3fe45af98 100644
--- a/vendor/rustix/src/backend/linux_raw/termios/types.rs
+++ b/vendor/rustix/src/backend/linux_raw/termios/types.rs
@@ -7,13 +7,16 @@ use super::super::c;
#[repr(u32)]
pub enum OptionalActions {
/// `TCSANOW`—Make the change immediately.
+ #[doc(alias = "TCSANOW")]
Now = linux_raw_sys::general::TCSANOW,
/// `TCSADRAIN`—Make the change after all output has been transmitted.
+ #[doc(alias = "TCSADRAIN")]
Drain = linux_raw_sys::general::TCSADRAIN,
/// `TCSAFLUSH`—Discard any pending input and then make the change
/// after all output has been transmitted.
+ #[doc(alias = "TCSAFLUSH")]
Flush = linux_raw_sys::general::TCSAFLUSH,
}
@@ -24,12 +27,15 @@ pub enum OptionalActions {
#[repr(u32)]
pub enum QueueSelector {
/// `TCIFLUSH`—Flush data received but not read.
+ #[doc(alias = "TCIFLUSH")]
IFlush = linux_raw_sys::general::TCIFLUSH,
/// `TCOFLUSH`—Flush data written but not transmitted.
+ #[doc(alias = "TCOFLUSH")]
OFlush = linux_raw_sys::general::TCOFLUSH,
/// `TCIOFLUSH`—`IFlush` and `OFlush` combined.
+ #[doc(alias = "TCIOFLUSH")]
IOFlush = linux_raw_sys::general::TCIOFLUSH,
}
@@ -40,34 +46,60 @@ pub enum QueueSelector {
#[repr(u32)]
pub enum Action {
/// `TCOOFF`—Suspend output.
+ #[doc(alias = "TCOOFF")]
OOff = linux_raw_sys::general::TCOOFF,
/// `TCOON`—Restart suspended output.
+ #[doc(alias = "TCOON")]
OOn = linux_raw_sys::general::TCOON,
/// `TCIOFF`—Transmits a STOP byte.
+ #[doc(alias = "TCIOFF")]
IOff = linux_raw_sys::general::TCIOFF,
/// `TCION`—Transmits a START byte.
+ #[doc(alias = "TCION")]
IOn = linux_raw_sys::general::TCION,
}
-/// `struct termios` for use with [`tcgetattr`].
+/// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`].
///
/// [`tcgetattr`]: crate::termios::tcgetattr
+/// [`tcsetattr`]: crate::termios::tcsetattr
+#[doc(alias = "termios")]
pub type Termios = linux_raw_sys::general::termios;
+/// `struct termios2` for use with [`tcgetattr2`] and [`tcsetattr2`].
+///
+/// [`tcgetattr2`]: crate::termios::tcgetattr2
+/// [`tcsetattr2`]: crate::termios::tcsetattr2
+#[cfg(any(
+ target_arch = "x86",
+ target_arch = "x86_64",
+ target_arch = "x32",
+ target_arch = "riscv64",
+ target_arch = "aarch64",
+ target_arch = "arm",
+ target_arch = "mips",
+ target_arch = "mips64",
+))]
+#[doc(alias = "termios2")]
+pub type Termios2 = linux_raw_sys::general::termios2;
+
/// `struct winsize` for use with [`tcgetwinsize`].
///
/// [`tcgetwinsize`]: crate::termios::tcgetwinsize
+#[doc(alias = "winsize")]
pub type Winsize = linux_raw_sys::general::winsize;
/// `tcflag_t`—A type for the flags fields of [`Termios`].
+#[doc(alias = "tcflag_t")]
pub type Tcflag = linux_raw_sys::general::tcflag_t;
/// `speed_t`—A return type for [`cfsetspeed`] and similar.
///
/// [`cfsetspeed`]: crate::termios::cfsetspeed
+#[doc(alias = "speed_t")]
pub type Speed = linux_raw_sys::general::speed_t;
/// `VINTR`
@@ -353,6 +385,9 @@ pub const B3500000: Speed = linux_raw_sys::general::B3500000;
#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))]
pub const B4000000: Speed = linux_raw_sys::general::B4000000;
+/// `BOTHER`
+pub const BOTHER: c::c_uint = linux_raw_sys::general::BOTHER;
+
/// `CSIZE`
pub const CSIZE: c::c_uint = linux_raw_sys::general::CSIZE;
diff --git a/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs b/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs
index 2ec3e43e8..af2c9ee8a 100644
--- a/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs
+++ b/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs
@@ -294,3 +294,65 @@ pub(crate) fn setns(fd: BorrowedFd, nstype: c::c_int) -> io::Result<c::c_int> {
pub(crate) fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
unsafe { ret(syscall_readonly!(__NR_unshare, c_uint(flags.bits()))) }
}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[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<()> {
+ let header: *mut _ = header;
+ unsafe { ret(syscall!(__NR_capget, header, data.as_mut_ptr())) }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[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<()> {
+ let header: *mut _ = header;
+ unsafe { ret(syscall!(__NR_capset, header, data.as_ptr())) }
+}
+
+#[inline]
+pub(crate) fn setuid_thread(uid: crate::process::Uid) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_setuid, uid)) }
+}
+
+#[inline]
+pub(crate) fn setresuid_thread(
+ ruid: crate::process::Uid,
+ euid: crate::process::Uid,
+ suid: crate::process::Uid,
+) -> io::Result<()> {
+ #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))]
+ unsafe {
+ ret(syscall_readonly!(__NR_setresuid32, ruid, euid, suid))
+ }
+ #[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))]
+ unsafe {
+ ret(syscall_readonly!(__NR_setresuid, ruid, euid, suid))
+ }
+}
+
+#[inline]
+pub(crate) fn setgid_thread(gid: crate::process::Gid) -> io::Result<()> {
+ unsafe { ret(syscall_readonly!(__NR_setgid, gid)) }
+}
+
+#[inline]
+pub(crate) fn setresgid_thread(
+ rgid: crate::process::Gid,
+ egid: crate::process::Gid,
+ sgid: crate::process::Gid,
+) -> io::Result<()> {
+ #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))]
+ unsafe {
+ ret(syscall_readonly!(__NR_setresgid32, rgid, egid, sgid))
+ }
+ #[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))]
+ unsafe {
+ ret(syscall_readonly!(__NR_setresgid, rgid, egid, sgid))
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/time/syscalls.rs b/vendor/rustix/src/backend/linux_raw/time/syscalls.rs
index 6e73a921b..c039393ef 100644
--- a/vendor/rustix/src/backend/linux_raw/time/syscalls.rs
+++ b/vendor/rustix/src/backend/linux_raw/time/syscalls.rs
@@ -67,6 +67,47 @@ unsafe fn clock_getres_old(which_clock: ClockId, result: &mut MaybeUninit<__kern
#[cfg(feature = "time")]
#[inline]
+pub(crate) fn clock_settime(which_clock: ClockId, timespec: __kernel_timespec) -> io::Result<()> {
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ match ret(syscall_readonly!(
+ __NR_clock_settime64,
+ which_clock,
+ by_ref(&timespec)
+ )) {
+ Err(io::Errno::NOSYS) => clock_settime_old(which_clock, timespec),
+ otherwise => otherwise,
+ }
+ }
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_clock_settime,
+ which_clock,
+ by_ref(&timespec)
+ ))
+ }
+}
+
+#[cfg(feature = "time")]
+#[cfg(target_pointer_width = "32")]
+unsafe fn clock_settime_old(which_clock: ClockId, timespec: __kernel_timespec) -> io::Result<()> {
+ let old_timespec = __kernel_old_timespec {
+ tv_sec: timespec
+ .tv_sec
+ .try_into()
+ .map_err(|_| io::Errno::OVERFLOW)?,
+ tv_nsec: timespec.tv_nsec as _,
+ };
+ ret(syscall_readonly!(
+ __NR_clock_settime,
+ which_clock,
+ by_ref(&old_timespec)
+ ))
+}
+
+#[cfg(feature = "time")]
+#[inline]
pub(crate) fn timerfd_create(clockid: TimerfdClockId, flags: TimerfdFlags) -> io::Result<OwnedFd> {
unsafe { ret_owned_fd(syscall!(__NR_timerfd_create, clockid, flags)) }
}
diff --git a/vendor/rustix/src/backend/linux_raw/vdso.rs b/vendor/rustix/src/backend/linux_raw/vdso.rs
index da7910b88..480378b50 100644
--- a/vendor/rustix/src/backend/linux_raw/vdso.rs
+++ b/vendor/rustix/src/backend/linux_raw/vdso.rs
@@ -55,7 +55,7 @@ fn elf_hash(name: &CStr) -> u32 {
/// Create a `Vdso` value by parsing the vDSO at the `sysinfo_ehdr` address.
fn init_from_sysinfo_ehdr() -> Option<Vdso> {
- // Safety: the auxv initialization code does extensive checks to ensure
+ // SAFETY: the auxv initialization code does extensive checks to ensure
// that the value we get really is an `AT_SYSINFO_EHDR` value from the
// kernel.
unsafe {
@@ -255,7 +255,7 @@ impl Vdso {
let ver_hash = elf_hash(version);
let name_hash = elf_hash(name);
- // Safety: The pointers in `self` must be valid.
+ // SAFETY: The pointers in `self` must be valid.
unsafe {
let mut chain = *self.bucket.add((name_hash % self.nbucket) as usize);
diff --git a/vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs b/vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs
index aaa000622..5b2e084ea 100644
--- a/vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs
+++ b/vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs
@@ -27,7 +27,7 @@ use linux_raw_sys::general::{__kernel_clockid_t, __kernel_timespec};
#[inline]
pub(crate) fn clock_gettime(which_clock: ClockId) -> __kernel_timespec {
- // Safety: `CLOCK_GETTIME` contains either null or the address of a
+ // SAFETY: `CLOCK_GETTIME` contains either null or the address of a
// function with an ABI like libc `clock_gettime`, and calling it has
// the side effect of writing to the result buffer, and no others.
unsafe {
@@ -64,7 +64,7 @@ pub(crate) fn clock_gettime_dynamic(which_clock: DynamicClockId<'_>) -> io::Resu
}
};
- // Safety: `CLOCK_GETTIME` contains either null or the address of a
+ // SAFETY: `CLOCK_GETTIME` contains either null or the address of a
// function with an ABI like libc `clock_gettime`, and calling it has
// the side effect of writing to the result buffer, and no others.
unsafe {
@@ -217,7 +217,7 @@ pub(super) type SyscallType = unsafe extern "C" fn();
/// Initialize `CLOCK_GETTIME` and return its value.
fn init_clock_gettime() -> ClockGettimeType {
init();
- // Safety: Load the function address from static storage that we
+ // SAFETY: Load the function address from static storage that we
// just initialized.
unsafe { transmute(CLOCK_GETTIME.load(Relaxed)) }
}
@@ -226,7 +226,7 @@ fn init_clock_gettime() -> ClockGettimeType {
#[cfg(target_arch = "x86")]
fn init_syscall() -> SyscallType {
init();
- // Safety: Load the function address from static storage that we
+ // SAFETY: Load the function address from static storage that we
// just initialized.
unsafe { transmute(SYSCALL.load(Relaxed)) }
}
@@ -309,7 +309,7 @@ extern "C" {
}
fn minimal_init() {
- // Safety: Store default function addresses in static storage so that if we
+ // SAFETY: Store default function addresses in static storage so that if we
// end up making any system calls while we read the vDSO, they'll work.
// If the memory happens to already be initialized, this is redundant, but
// not harmful.
@@ -375,7 +375,7 @@ fn init() {
if ok {
assert!(!ptr.is_null());
- // Safety: Store the computed function addresses in static storage
+ // SAFETY: Store the computed function addresses in static storage
// so that we don't need to compute it again (but if we do, it doesn't
// hurt anything).
unsafe {
@@ -389,7 +389,7 @@ fn init() {
let ptr = vdso.sym(cstr!("LINUX_2.5"), cstr!("__kernel_vsyscall"));
assert!(!ptr.is_null());
- // Safety: As above, store the computed function addresses in
+ // SAFETY: As above, store the computed function addresses in
// static storage.
unsafe {
SYSCALL.store(ptr.cast(), Relaxed);
diff --git a/vendor/rustix/src/backend/linux_raw/weak.rs b/vendor/rustix/src/backend/linux_raw/weak.rs
new file mode 100644
index 000000000..ae7d6832e
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/weak.rs
@@ -0,0 +1,228 @@
+// Implementation derived from `weak` in Rust's
+// library/std/src/sys/unix/weak.rs at revision
+// fd0cb0cdc21dd9c06025277d772108f8d42cb25f.
+
+#![allow(unsafe_code)]
+
+//! Support for "weak linkage" to symbols on Unix
+//!
+//! Some I/O operations we do in libstd require newer versions of OSes but we
+//! need to maintain binary compatibility with older releases for now. In order
+//! to use the new functionality when available we use this module for
+//! detection.
+//!
+//! One option to use here is weak linkage, but that is unfortunately only
+//! really workable on Linux. Hence, use dlsym to get the symbol value at
+//! runtime. This is also done for compatibility with older versions of glibc,
+//! and to avoid creating dependencies on `GLIBC_PRIVATE` symbols. It assumes
+//! that we've been dynamically linked to the library the symbol comes from,
+//! but that is currently always the case for things like libpthread/libc.
+//!
+//! A long time ago this used weak linkage for the `__pthread_get_minstack`
+//! symbol, but that caused Debian to detect an unnecessarily strict versioned
+//! dependency on libc6 (#23628).
+
+// There are a variety of `#[cfg]`s controlling which targets are involved in
+// each instance of `weak!` and `syscall!`. Rather than trying to unify all of
+// that, we'll just allow that some unix targets don't use this module at all.
+#![allow(dead_code, unused_macros)]
+#![allow(clippy::doc_markdown)]
+
+use crate::ffi::CStr;
+use core::ffi::c_void;
+use core::ptr::null_mut;
+use core::sync::atomic::{self, AtomicPtr, Ordering};
+use core::{marker, mem};
+
+const NULL: *mut c_void = null_mut();
+const INVALID: *mut c_void = 1 as *mut c_void;
+
+macro_rules! weak {
+ ($vis:vis fn $name:ident($($t:ty),*) -> $ret:ty) => (
+ #[allow(non_upper_case_globals)]
+ $vis static $name: $crate::backend::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
+ $crate::backend::weak::Weak::new(concat!(stringify!($name), '\0'));
+ )
+}
+
+pub(crate) struct Weak<F> {
+ name: &'static str,
+ addr: AtomicPtr<c_void>,
+ _marker: marker::PhantomData<F>,
+}
+
+impl<F> Weak<F> {
+ pub(crate) const fn new(name: &'static str) -> Self {
+ Self {
+ name,
+ addr: AtomicPtr::new(INVALID),
+ _marker: marker::PhantomData,
+ }
+ }
+
+ pub(crate) fn get(&self) -> Option<F> {
+ assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+ unsafe {
+ // Relaxed is fine here because we fence before reading through the
+ // pointer (see the comment below).
+ match self.addr.load(Ordering::Relaxed) {
+ INVALID => self.initialize(),
+ NULL => None,
+ addr => {
+ let func = mem::transmute_copy::<*mut c_void, F>(&addr);
+ // The caller is presumably going to read through this value
+ // (by calling the function we've dlsymed). This means we'd
+ // need to have loaded it with at least C11's consume
+ // ordering in order to be guaranteed that the data we read
+ // from the pointer isn't from before the pointer was
+ // stored. Rust has no equivalent to memory_order_consume,
+ // so we use an acquire fence (sorry, ARM).
+ //
+ // Now, in practice this likely isn't needed even on CPUs
+ // where relaxed and consume mean different things. The
+ // symbols we're loading are probably present (or not) at
+ // init, and even if they aren't the runtime dynamic loader
+ // is extremely likely have sufficient barriers internally
+ // (possibly implicitly, for example the ones provided by
+ // invoking `mprotect`).
+ //
+ // That said, none of that's *guaranteed*, and so we fence.
+ atomic::fence(Ordering::Acquire);
+ Some(func)
+ }
+ }
+ }
+ }
+
+ // Cold because it should only happen during first-time initialization.
+ #[cold]
+ unsafe fn initialize(&self) -> Option<F> {
+ let val = fetch(self.name);
+ // This synchronizes with the acquire fence in `get`.
+ self.addr.store(val, Ordering::Release);
+
+ match val {
+ NULL => None,
+ addr => Some(mem::transmute_copy::<*mut c_void, F>(&addr)),
+ }
+ }
+}
+
+unsafe fn fetch(name: &str) -> *mut c_void {
+ let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
+ Ok(c_str) => c_str,
+ Err(..) => return null_mut(),
+ };
+ libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr())
+}
+
+#[cfg(not(any(target_os = "android", target_os = "linux")))]
+macro_rules! syscall {
+ (fn $name:ident($($arg_name:ident: $t:ty),*) via $_sys_name:ident -> $ret:ty) => (
+ unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ libc_errno::set_errno(libc_errno::Errno(libc::ENOSYS));
+ -1
+ }
+ }
+ )
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+macro_rules! syscall {
+ (fn $name:ident($($arg_name:ident: $t:ty),*) via $sys_name:ident -> $ret:ty) => (
+ unsafe fn $name($($arg_name:$t),*) -> $ret {
+ // This looks like a hack, but concat_idents only accepts idents
+ // (not paths).
+ use libc::*;
+
+ trait AsSyscallArg {
+ type SyscallArgType;
+ fn into_syscall_arg(self) -> Self::SyscallArgType;
+ }
+
+ // Pass pointer types as pointers, to preserve provenance.
+ impl<T> AsSyscallArg for *mut T {
+ type SyscallArgType = *mut T;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self }
+ }
+ impl<T> AsSyscallArg for *const T {
+ type SyscallArgType = *const T;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self }
+ }
+
+ // Pass `BorrowedFd` values as the integer value.
+ impl AsSyscallArg for $crate::fd::BorrowedFd<'_> {
+ type SyscallArgType = c::c_long;
+ fn into_syscall_arg(self) -> Self::SyscallArgType {
+ $crate::fd::AsRawFd::as_raw_fd(&self) as _
+ }
+ }
+
+ // Coerce integer values into `c_long`.
+ impl AsSyscallArg for i32 {
+ type SyscallArgType = c::c_long;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+ impl AsSyscallArg for u32 {
+ type SyscallArgType = c::c_long;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+ impl AsSyscallArg for usize {
+ type SyscallArgType = c::c_long;
+ fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+
+ // `concat_idents is unstable, so we take an extra `sys_name`
+ // parameter and have our users do the concat for us for now.
+ /*
+ syscall(
+ concat_idents!(SYS_, $name),
+ $($arg_name.into_syscall_arg()),*
+ ) as $ret
+ */
+
+ syscall($sys_name, $($arg_name.into_syscall_arg()),*) as $ret
+ }
+ )
+}
+
+macro_rules! weakcall {
+ ($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ $vis unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
+ // interposition, but if it's not found just fail.
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ libc_errno::set_errno(libc_errno::Errno(libc::ENOSYS));
+ -1
+ }
+ }
+ )
+}
+
+/// A combination of `weakcall` and `syscall`. Use the libc function if it's
+/// available, and fall back to `libc::syscall` otherwise.
+macro_rules! weak_or_syscall {
+ ($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) via $sys_name:ident -> $ret:ty) => (
+ $vis unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
+ // interposition, but if it's not found just fail.
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ syscall! { fn $name($($arg_name: $t),*) via $sys_name -> $ret }
+ $name($($arg_name),*)
+ }
+ }
+ )
+}