Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
use crate::ffi;
use bitflags::bitflags;
bitflags! {
/// `EPOLL_*` for use with [`epoll::create`].
///
/// [`epoll::create`]: crate::event::epoll::create
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct CreateFlags: ffi::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 [`epoll::add`].
///
/// [`epoll::add`]: crate::event::epoll::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;
}
}

View File

@@ -0,0 +1,4 @@
pub mod epoll;
pub(crate) mod poll_fd;
pub(crate) mod syscalls;
pub(crate) mod types;

View 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()
}
}

View File

@@ -0,0 +1,358 @@
//! 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::conv::{
by_ref, c_int, c_uint, opt_mut, opt_ref, pass_usize, ret, ret_c_int, ret_error, ret_owned_fd,
ret_usize, size_of, slice_mut, zero,
};
use crate::event::{epoll, EventfdFlags, FdSetElement, PollFd, Timespec};
use crate::fd::{BorrowedFd, OwnedFd};
use crate::io;
use core::ptr::null_mut;
use linux_raw_sys::general::{kernel_sigset_t, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD};
#[inline]
pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: Option<&Timespec>) -> io::Result<usize> {
let (fds_addr_mut, fds_len) = slice_mut(fds);
#[cfg(target_pointer_width = "32")]
unsafe {
// If we don't have Linux 5.1, and the timeout fits in a
// `__kernel_old_timespec`, use plain `ppoll`.
//
// We do this unconditionally, rather than trying `ppoll_time64` and
// falling back on `Errno::NOSYS`, because seccomp configurations will
// sometimes abort the process on syscalls they don't recognize.
#[cfg(not(feature = "linux_5_1"))]
{
use linux_raw_sys::general::__kernel_old_timespec;
// If we don't have a timeout, or if we can convert the timeout to
// a `__kernel_old_timespec`, the use `__NR_ppoll`.
fn convert(timeout: &Timespec) -> Option<__kernel_old_timespec> {
Some(__kernel_old_timespec {
tv_sec: timeout.tv_sec.try_into().ok()?,
tv_nsec: timeout.tv_nsec.try_into().ok()?,
})
}
let old_timeout = if let Some(timeout) = timeout {
match convert(timeout) {
// Could not convert timeout.
None => None,
// Could convert timeout. Ok!
Some(old_timeout) => Some(Some(old_timeout)),
}
} else {
// No timeout. Ok!
Some(None)
};
if let Some(mut old_timeout) = old_timeout {
// Call `ppoll`.
//
// Linux's `ppoll` mutates the timeout argument. Our public
// interface does not do this, because it's not portable to other
// platforms, so we create a temporary value to hide this behavior.
return ret_usize(syscall!(
__NR_ppoll,
fds_addr_mut,
fds_len,
opt_mut(old_timeout.as_mut()),
zero(),
size_of::<kernel_sigset_t, _>()
));
}
}
// We either have Linux 5.1 or the timeout didn't fit in
// `__kernel_old_timespec` so `__NR_ppoll_time64` will either
// succeed or fail due to our having no other options.
// Call `ppoll_time64`.
//
// Linux's `ppoll_time64` mutates the timeout argument. Our public
// interface does not do this, because it's not portable to other
// platforms, so we create a temporary value to hide this behavior.
ret_usize(syscall!(
__NR_ppoll_time64,
fds_addr_mut,
fds_len,
opt_mut(timeout.copied().as_mut()),
zero(),
size_of::<kernel_sigset_t, _>()
))
}
#[cfg(target_pointer_width = "64")]
unsafe {
// Call `ppoll`.
//
// Linux's `ppoll` mutates the timeout argument. Our public interface
// does not do this, because it's not portable to other platforms, so
// we create a temporary value to hide this behavior.
ret_usize(syscall!(
__NR_ppoll,
fds_addr_mut,
fds_len,
opt_mut(timeout.copied().as_mut()),
zero(),
size_of::<kernel_sigset_t, _>()
))
}
}
pub(crate) unsafe fn select(
nfds: i32,
readfds: Option<&mut [FdSetElement]>,
writefds: Option<&mut [FdSetElement]>,
exceptfds: Option<&mut [FdSetElement]>,
timeout: Option<&crate::timespec::Timespec>,
) -> io::Result<i32> {
let len = crate::event::fd_set_num_elements_for_bitvector(nfds);
let readfds = match readfds {
Some(readfds) => {
assert!(readfds.len() >= len);
readfds.as_mut_ptr()
}
None => null_mut(),
};
let writefds = match writefds {
Some(writefds) => {
assert!(writefds.len() >= len);
writefds.as_mut_ptr()
}
None => null_mut(),
};
let exceptfds = match exceptfds {
Some(exceptfds) => {
assert!(exceptfds.len() >= len);
exceptfds.as_mut_ptr()
}
None => null_mut(),
};
#[cfg(target_pointer_width = "32")]
{
// If we don't have Linux 5.1, and the timeout fits in a
// `__kernel_old_timespec`, use plain `pselect6`.
//
// We do this unconditionally, rather than trying `pselect6_time64` and
// falling back on `Errno::NOSYS`, because seccomp configurations will
// sometimes abort the process on syscalls they don't recognize.
#[cfg(not(feature = "linux_5_1"))]
{
use linux_raw_sys::general::__kernel_old_timespec;
// If we don't have a timeout, or if we can convert the timeout to
// a `__kernel_old_timespec`, the use `__NR_pselect6`.
fn convert(timeout: &Timespec) -> Option<__kernel_old_timespec> {
Some(__kernel_old_timespec {
tv_sec: timeout.tv_sec.try_into().ok()?,
tv_nsec: timeout.tv_nsec.try_into().ok()?,
})
}
let old_timeout = if let Some(timeout) = timeout {
match convert(timeout) {
// Could not convert timeout.
None => None,
// Could convert timeout. Ok!
Some(old_timeout) => Some(Some(old_timeout)),
}
} else {
// No timeout. Ok!
Some(None)
};
if let Some(mut old_timeout) = old_timeout {
// Call `pselect6`.
//
// Linux's `pselect6` mutates the timeout argument. Our public
// interface does not do this, because it's not portable to other
// platforms, so we create a temporary value to hide this behavior.
return ret_c_int(syscall!(
__NR_pselect6,
c_int(nfds),
readfds,
writefds,
exceptfds,
opt_mut(old_timeout.as_mut()),
zero()
));
}
}
// We either have Linux 5.1 or the timeout didn't fit in
// `__kernel_old_timespec` so `__NR_pselect6_time64` will either
// succeed or fail due to our having no other options.
// Call `pselect6_time64`.
//
// Linux's `pselect6_time64` mutates the timeout argument. Our public
// interface does not do this, because it's not portable to other
// platforms, so we create a temporary value to hide this behavior.
ret_c_int(syscall!(
__NR_pselect6_time64,
c_int(nfds),
readfds,
writefds,
exceptfds,
opt_mut(timeout.copied().as_mut()),
zero()
))
}
#[cfg(target_pointer_width = "64")]
{
// Call `pselect6`.
//
// Linux's `pselect6` mutates the timeout argument. Our public interface
// does not do this, because it's not portable to other platforms, so we
// create a temporary value to hide this behavior.
ret_c_int(syscall!(
__NR_pselect6,
c_int(nfds),
readfds,
writefds,
exceptfds,
opt_mut(timeout.copied().as_mut()),
zero()
))
}
}
#[inline]
pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result<OwnedFd> {
// SAFETY: `__NR_epoll_create1` doesn't access any user memory.
unsafe { ret_owned_fd(syscall_readonly!(__NR_epoll_create1, flags)) }
}
#[inline]
pub(crate) fn epoll_add(
epfd: BorrowedFd<'_>,
fd: BorrowedFd<'_>,
event: &epoll::Event,
) -> io::Result<()> {
// SAFETY: `__NR_epoll_ctl` with `EPOLL_CTL_ADD` doesn't modify any user
// memory, and it only reads from `event`.
unsafe {
ret(syscall_readonly!(
__NR_epoll_ctl,
epfd,
c_uint(EPOLL_CTL_ADD),
fd,
by_ref(event)
))
}
}
#[inline]
pub(crate) fn epoll_mod(
epfd: BorrowedFd<'_>,
fd: BorrowedFd<'_>,
event: &epoll::Event,
) -> io::Result<()> {
// SAFETY: `__NR_epoll_ctl` with `EPOLL_CTL_MOD` doesn't modify any user
// memory, and it only reads from `event`.
unsafe {
ret(syscall_readonly!(
__NR_epoll_ctl,
epfd,
c_uint(EPOLL_CTL_MOD),
fd,
by_ref(event)
))
}
}
#[inline]
pub(crate) fn epoll_del(epfd: BorrowedFd<'_>, fd: BorrowedFd<'_>) -> io::Result<()> {
// SAFETY: `__NR_epoll_ctl` with `EPOLL_CTL_DEL` doesn't access any user
// memory.
unsafe {
ret(syscall_readonly!(
__NR_epoll_ctl,
epfd,
c_uint(EPOLL_CTL_DEL),
fd,
zero()
))
}
}
#[inline]
pub(crate) unsafe fn epoll_wait(
epfd: BorrowedFd<'_>,
events: (*mut crate::event::epoll::Event, usize),
timeout: Option<&Timespec>,
) -> io::Result<usize> {
// If we don't have Linux 5.1, and the timeout fits in an `i32`, use plain
// `epoll_pwait`.
//
// We do this unconditionally, rather than trying `epoll_pwait2` and
// falling back on `Errno::NOSYS`, because seccomp configurations will
// sometimes abort the process on syscalls they don't recognize.
#[cfg(not(feature = "linux_5_11"))]
{
// If we don't have a timeout, or if we can convert the timeout to an
// `i32`, the use `__NR_epoll_pwait`.
let old_timeout = if let Some(timeout) = timeout {
// Try to convert the timeout; if this is `Some`, we're ok!
timeout.as_c_int_millis()
} else {
// No timeout. Ok!
Some(-1)
};
if let Some(old_timeout) = old_timeout {
// Call `epoll_pwait`.
return ret_usize(syscall!(
__NR_epoll_pwait,
epfd,
events.0,
pass_usize(events.1),
c_int(old_timeout),
zero()
));
}
}
// Call `epoll_pwait2`.
//
// We either have Linux 5.1 or the timeout didn't fit in an `i32`, so
// `__NR_epoll_pwait2` will either succeed or fail due to our having no
// other options.
ret_usize(syscall!(
__NR_epoll_pwait2,
epfd,
events.0,
pass_usize(events.1),
opt_ref(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);
}
}

View File

@@ -0,0 +1,21 @@
use crate::ffi;
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: ffi::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;
}
}