From b772088501cea50b1f25a61d5e27c8d033f3171b Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sun, 6 Sep 2026 00:32:03 +0100 Subject: [PATCH 1/9] ci: add web-sys pin --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 31fdb8ed4..21df08597 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,6 +54,7 @@ jobs: cargo update --package=half --precise=2.2.1 cargo update --package=flate2 --precise=1.0.35 cargo update --package=serde --precise=1.0.228 + cargo update --package=web-sys --precise=0.3.104 cargo update --package=syn --precise=2.0.106 cargo update --package=textwrap --precise=0.16.1 cargo update --package=parking_lot --precise=0.12.4 @@ -596,6 +597,7 @@ jobs: cargo update --package=half --precise=2.2.1 cargo update --package=flate2 --precise=1.0.35 cargo update --package=serde --precise=1.0.228 + cargo update --package=web-sys --precise=0.3.104 cargo update --package=syn --precise=2.0.106 cargo update --package=textwrap --precise=0.16.1 cargo update --package=parking_lot --precise=0.12.4 From 2328228ee14e447c94d8c30e00b7101f7031da6b Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:14:47 +0100 Subject: [PATCH 2/9] Import statx_flags from linux_raw_sys explicitly to avoid libc conflicts --- src/backend/libc/c.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/backend/libc/c.rs b/src/backend/libc/c.rs index 5eeff953f..fb748979f 100644 --- a/src/backend/libc/c.rs +++ b/src/backend/libc/c.rs @@ -474,30 +474,27 @@ mod readwrite_pv64v2 { ))] pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2}; -// Rust's libc crate lacks statx for Non-glibc targets. +// Rust's libc crate > v0.2.189 may also define these constants, +// so we use an explicit import. #[cfg(feature = "fs")] #[cfg(all( linux_like, linux_raw_dep, not(any( + target_os = "android", target_os = "emscripten", target_env = "gnu", all(target_arch = "loongarch64", target_env = "musl") )) ))] -mod statx_flags { - pub(crate) use linux_raw_sys::general::{ - STATX_ALL, STATX_ATIME, STATX_BASIC_STATS, STATX_BLOCKS, STATX_BTIME, STATX_CTIME, - STATX_DIOALIGN, STATX_GID, STATX_INO, STATX_MNT_ID, STATX_MODE, STATX_MTIME, STATX_NLINK, - STATX_SIZE, STATX_TYPE, STATX_UID, - }; - - pub(crate) use linux_raw_sys::general::{ - STATX_ATTR_APPEND, STATX_ATTR_AUTOMOUNT, STATX_ATTR_COMPRESSED, STATX_ATTR_DAX, - STATX_ATTR_ENCRYPTED, STATX_ATTR_IMMUTABLE, STATX_ATTR_MOUNT_ROOT, STATX_ATTR_NODUMP, - STATX_ATTR_VERITY, - }; -} +pub(crate) use linux_raw_sys::general::{ + STATX_ALL, STATX_ATIME, STATX_BASIC_STATS, STATX_BLOCKS, STATX_BTIME, STATX_CTIME, + STATX_DIOALIGN, STATX_GID, STATX_INO, STATX_MNT_ID, STATX_MODE, STATX_MTIME, STATX_NLINK, + STATX_SIZE, STATX_TYPE, STATX_UID, +}; + +// Rust's libc crate > v0.2.189 may also define these constants, +// so we use an explicit import. #[cfg(feature = "fs")] #[cfg(all( linux_like, @@ -509,7 +506,11 @@ mod statx_flags { all(target_arch = "loongarch64", target_env = "musl") )) ))] -pub(crate) use statx_flags::*; +pub(crate) use linux_raw_sys::general::{ + STATX_ATTR_APPEND, STATX_ATTR_AUTOMOUNT, STATX_ATTR_COMPRESSED, STATX_ATTR_DAX, + STATX_ATTR_ENCRYPTED, STATX_ATTR_IMMUTABLE, STATX_ATTR_MOUNT_ROOT, STATX_ATTR_NODUMP, + STATX_ATTR_VERITY, +}; #[cfg(feature = "fs")] #[cfg(target_os = "android")] From f7ea9d5d541c9083da32d8019b59f3a0dd705194 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sun, 6 Sep 2026 21:04:17 +0100 Subject: [PATCH 3/9] Gate sysproto module to macOS The `SYSPROTO_EVENT` and `SYSPROTO_CONTROL` constants are only available on macOS, see https://github.com/rust-lang/libc/pull/5158. --- src/net/types.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net/types.rs b/src/net/types.rs index 6f9ba9f07..e2778bfce 100644 --- a/src/net/types.rs +++ b/src/net/types.rs @@ -1116,6 +1116,7 @@ pub mod ipproto { } /// `SYSPROTO_*` constants. +#[cfg(target_os = "macos")] pub mod sysproto { #[cfg(apple)] use { @@ -1124,11 +1125,9 @@ pub mod sysproto { }; /// `SYSPROTO_EVENT` - #[cfg(apple)] pub const EVENT: Protocol = Protocol(new_raw_protocol(c::SYSPROTO_EVENT as _)); /// `SYSPROTO_CONTROL` - #[cfg(apple)] pub const CONTROL: Protocol = Protocol(new_raw_protocol(c::SYSPROTO_CONTROL as _)); } From 10461782fbb1ccb3f70db93a66c8f201208d3a17 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sun, 6 Sep 2026 21:10:51 +0100 Subject: [PATCH 4/9] Gate `AF_SYS_CONTROL` to macos The `AF_SYS_CONTROL` constant is only available on macOS, see https://github.com/rust-lang/libc/pull/5158. --- src/net/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/types.rs b/src/net/types.rs index e2778bfce..8eca89ca0 100644 --- a/src/net/types.rs +++ b/src/net/types.rs @@ -740,7 +740,7 @@ impl AddressFamily { #[cfg(target_os = "freebsd")] pub const SLOW: Self = Self(c::AF_SLOW as _); /// `AF_SYS_CONTROL` - #[cfg(apple)] + #[cfg(target_os = "macos")] pub const SYS_CONTROL: Self = Self(c::AF_SYS_CONTROL as _); /// `AF_SYSTEM` #[cfg(apple)] From eada0dfcd64697eecbbb43aaa2c665c9d6a36051 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sun, 6 Sep 2026 21:44:23 +0100 Subject: [PATCH 5/9] Return `NOSYS` from `utimensat` on tvOS and watchOS tvOS and watchOS do not provide `fork`, so the `utimensat` fallback cannot be implemented on these platforms. Return `NOSYS` instead. --- src/backend/libc/fs/syscalls.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 8b7f082f5..0b7b32820 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -941,6 +941,7 @@ pub(crate) fn utimensat( c::c_int ) -> c::c_int } + #[cfg(not(any(target_os = "tvos", target_os = "watchos")))] extern "C" { fn setattrlist( path: *const ffi::c_char, @@ -950,6 +951,7 @@ pub(crate) fn utimensat( options: c::c_ulong, ) -> c::c_int; } + #[cfg(not(any(target_os = "tvos", target_os = "watchos")))] const FSOPT_NOFOLLOW: c::c_ulong = 0x0000_0001; // If we have `utimensat`, use it. @@ -962,8 +964,14 @@ pub(crate) fn utimensat( )); } + // Return `NOSYS` on platforms where `utimensat` cannot be emulated + // because `fork` is unavailable. + #[cfg(any(target_os = "tvos", target_os = "watchos"))] + return Err(io::Errno::NOSYS); + // Convert `times`. We only need this in the child, but do it before // calling `fork` because it might fail. + #[cfg(not(any(target_os = "tvos", target_os = "watchos")))] let (attrbuf_size, times, attrs) = times_to_attrlist(times)?; // `setattrlistat` was introduced in 10.13 along with `utimensat`, so @@ -971,6 +979,7 @@ pub(crate) fn utimensat( // Emulate it using `fork`, and `fchdir` and [`setattrlist`]. // // [`setattrlist`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setattrlist.2.html + #[cfg(not(any(target_os = "tvos", target_os = "watchos")))] match c::fork() { -1 => Err(io::Errno::IO), 0 => { From 92624c2ab8c8da96d358819d4effe9b8e4949555 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sun, 6 Sep 2026 00:05:36 +0100 Subject: [PATCH 6/9] avoid unnecessary type annotations for `.cast()` --- src/backend/libc/event/syscalls.rs | 6 +-- src/backend/libc/fs/syscalls.rs | 51 ++++++++-------------- src/backend/libc/io/syscalls.rs | 12 ++--- src/backend/libc/net/addr.rs | 4 +- src/backend/libc/net/read_sockaddr.rs | 6 +-- src/backend/libc/net/syscalls.rs | 14 +++--- src/backend/libc/pipe/syscalls.rs | 9 ++-- src/backend/libc/pipe/types.rs | 4 +- src/backend/libc/thread/syscalls.rs | 8 +--- src/backend/libc/time/types.rs | 4 +- src/backend/linux_raw/net/addr.rs | 6 +-- src/backend/linux_raw/net/netdevice.rs | 8 ++-- src/backend/linux_raw/net/read_sockaddr.rs | 4 +- src/backend/linux_raw/net/syscalls.rs | 2 +- src/backend/linux_raw/param/init.rs | 8 ++-- src/backend/linux_raw/pipe/types.rs | 4 +- src/backend/linux_raw/vdso.rs | 5 +-- src/buffer.rs | 6 +-- src/io_uring/bindgen_types.rs | 4 +- src/io_uring/mod.rs | 4 +- src/ioctl/patterns.rs | 2 +- src/net/send_recv/msg.rs | 9 ++-- src/path/arg.rs | 4 +- src/timespec.rs | 4 +- tests/io_uring/register.rs | 8 ++-- tests/mm/mlock.rs | 14 +++--- 26 files changed, 90 insertions(+), 120 deletions(-) diff --git a/src/backend/libc/event/syscalls.rs b/src/backend/libc/event/syscalls.rs index 3827a2f99..4af61cbcd 100644 --- a/src/backend/libc/event/syscalls.rs +++ b/src/backend/libc/event/syscalls.rs @@ -580,7 +580,7 @@ pub(crate) unsafe fn epoll_wait( if let Some(epoll_pwait2_func) = epoll_pwait2.get() { return ret_u32(epoll_pwait2_func( borrowed_fd(epoll), - events.0.cast::(), + events.0.cast(), events.1.try_into().unwrap_or(i32::MAX), crate::utils::option_as_ptr(timeout).cast(), null(), @@ -604,7 +604,7 @@ pub(crate) unsafe fn epoll_wait( ret_u32(epoll_pwait2( borrowed_fd(epoll), - events.0.cast::(), + events.0.cast(), events.1.try_into().unwrap_or(i32::MAX), crate::utils::option_as_ptr(timeout).cast(), null(), @@ -622,7 +622,7 @@ pub(crate) unsafe fn epoll_wait( ret_u32(c::epoll_wait( borrowed_fd(epoll), - events.0.cast::(), + events.0.cast(), events.1.try_into().unwrap_or(i32::MAX), timeout, )) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 0b7b32820..a144b6e6e 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -327,7 +327,7 @@ pub(crate) fn getdents_uninit( unsafe { ret_usize(getdents64( borrowed_fd(fd), - buf.as_mut_ptr().cast::(), + buf.as_mut_ptr().cast(), buf.len(), )) } @@ -2386,7 +2386,7 @@ pub(crate) unsafe fn getxattr( ret_usize(c::getxattr( path.as_ptr(), name.as_ptr(), - value.0.cast::(), + value.0.cast(), value.1, )) } @@ -2398,7 +2398,7 @@ pub(crate) unsafe fn getxattr( let ptr = if value.1 == 0 { core::ptr::null_mut() } else { - value.0.cast::() + value.0.cast() }; ret_usize(c::getxattr( path.as_ptr(), @@ -2422,7 +2422,7 @@ pub(crate) unsafe fn lgetxattr( ret_usize(c::lgetxattr( path.as_ptr(), name.as_ptr(), - value.0.cast::(), + value.0.cast(), value.1, )) } @@ -2434,7 +2434,7 @@ pub(crate) unsafe fn lgetxattr( let ptr = if value.1 == 0 { core::ptr::null_mut() } else { - value.0.cast::() + value.0.cast() }; ret_usize(c::getxattr( @@ -2459,7 +2459,7 @@ pub(crate) unsafe fn fgetxattr( ret_usize(c::fgetxattr( borrowed_fd(fd), name.as_ptr(), - value.0.cast::(), + value.0.cast(), value.1, )) } @@ -2471,7 +2471,7 @@ pub(crate) unsafe fn fgetxattr( let ptr = if value.1 == 0 { core::ptr::null_mut() } else { - value.0.cast::() + value.0.cast() }; ret_usize(c::fgetxattr( borrowed_fd(fd), @@ -2496,7 +2496,7 @@ pub(crate) fn setxattr( ret(c::setxattr( path.as_ptr(), name.as_ptr(), - value.as_ptr().cast::(), + value.as_ptr().cast(), value.len(), flags.bits() as i32, )) @@ -2507,7 +2507,7 @@ pub(crate) fn setxattr( ret(c::setxattr( path.as_ptr(), name.as_ptr(), - value.as_ptr().cast::(), + value.as_ptr().cast(), value.len(), 0, flags.bits() as i32, @@ -2527,7 +2527,7 @@ pub(crate) fn lsetxattr( ret(c::lsetxattr( path.as_ptr(), name.as_ptr(), - value.as_ptr().cast::(), + value.as_ptr().cast(), value.len(), flags.bits() as i32, )) @@ -2538,7 +2538,7 @@ pub(crate) fn lsetxattr( ret(c::setxattr( path.as_ptr(), name.as_ptr(), - value.as_ptr().cast::(), + value.as_ptr().cast(), value.len(), 0, flags.bits() as i32 | c::XATTR_NOFOLLOW, @@ -2558,7 +2558,7 @@ pub(crate) fn fsetxattr( ret(c::fsetxattr( borrowed_fd(fd), name.as_ptr(), - value.as_ptr().cast::(), + value.as_ptr().cast(), value.len(), flags.bits() as i32, )) @@ -2569,7 +2569,7 @@ pub(crate) fn fsetxattr( ret(c::fsetxattr( borrowed_fd(fd), name.as_ptr(), - value.as_ptr().cast::(), + value.as_ptr().cast(), value.len(), 0, flags.bits() as i32, @@ -2581,21 +2581,12 @@ pub(crate) fn fsetxattr( pub(crate) unsafe fn listxattr(path: &CStr, list: (*mut u8, usize)) -> io::Result { #[cfg(not(apple))] { - ret_usize(c::listxattr( - path.as_ptr(), - list.0.cast::(), - list.1, - )) + ret_usize(c::listxattr(path.as_ptr(), list.0.cast(), list.1)) } #[cfg(apple)] { - ret_usize(c::listxattr( - path.as_ptr(), - list.0.cast::(), - list.1, - 0, - )) + ret_usize(c::listxattr(path.as_ptr(), list.0.cast(), list.1, 0)) } } @@ -2603,18 +2594,14 @@ pub(crate) unsafe fn listxattr(path: &CStr, list: (*mut u8, usize)) -> io::Resul pub(crate) unsafe fn llistxattr(path: &CStr, list: (*mut u8, usize)) -> io::Result { #[cfg(not(apple))] { - ret_usize(c::llistxattr( - path.as_ptr(), - list.0.cast::(), - list.1, - )) + ret_usize(c::llistxattr(path.as_ptr(), list.0.cast(), list.1)) } #[cfg(apple)] { ret_usize(c::listxattr( path.as_ptr(), - list.0.cast::(), + list.0.cast(), list.1, c::XATTR_NOFOLLOW, )) @@ -2627,12 +2614,12 @@ pub(crate) unsafe fn flistxattr(fd: BorrowedFd<'_>, list: (*mut u8, usize)) -> i #[cfg(not(apple))] { - ret_usize(c::flistxattr(fd, list.0.cast::(), list.1)) + ret_usize(c::flistxattr(fd, list.0.cast(), list.1)) } #[cfg(apple)] { - ret_usize(c::flistxattr(fd, list.0.cast::(), list.1, 0)) + ret_usize(c::flistxattr(fd, list.0.cast(), list.1, 0)) } } diff --git a/src/backend/libc/io/syscalls.rs b/src/backend/libc/io/syscalls.rs index d91e983c2..3993d5d67 100644 --- a/src/backend/libc/io/syscalls.rs +++ b/src/backend/libc/io/syscalls.rs @@ -75,7 +75,7 @@ pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut<'_>]) -> io::Resu unsafe { ret_usize(c::readv( borrowed_fd(fd), - bufs.as_ptr().cast::(), + bufs.as_ptr().cast(), min(bufs.len(), MAX_IOV) as c::c_int, )) } @@ -86,7 +86,7 @@ pub(crate) fn writev(fd: BorrowedFd<'_>, bufs: &[IoSlice<'_>]) -> io::Result(), + bufs.as_ptr().cast(), min(bufs.len(), MAX_IOV) as c::c_int, )) } @@ -116,7 +116,7 @@ pub(crate) fn preadv( unsafe { ret_usize(c::preadv( borrowed_fd(fd), - bufs.as_ptr().cast::(), + bufs.as_ptr().cast(), min(bufs.len(), MAX_IOV) as c::c_int, offset, )) @@ -143,7 +143,7 @@ pub(crate) fn pwritev(fd: BorrowedFd<'_>, bufs: &[IoSlice<'_>], offset: u64) -> unsafe { ret_usize(c::pwritev( borrowed_fd(fd), - bufs.as_ptr().cast::(), + bufs.as_ptr().cast(), min(bufs.len(), MAX_IOV) as c::c_int, offset, )) @@ -162,7 +162,7 @@ pub(crate) fn preadv2( unsafe { ret_usize(c::preadv2( borrowed_fd(fd), - bufs.as_ptr().cast::(), + bufs.as_ptr().cast(), min(bufs.len(), MAX_IOV) as c::c_int, offset, bitflags_bits!(flags), @@ -182,7 +182,7 @@ pub(crate) fn pwritev2( unsafe { ret_usize(c::pwritev2( borrowed_fd(fd), - bufs.as_ptr().cast::(), + bufs.as_ptr().cast(), min(bufs.len(), MAX_IOV) as c::c_int, offset, bitflags_bits!(flags), diff --git a/src/backend/libc/net/addr.rs b/src/backend/libc/net/addr.rs index a9b55559c..d3ff0b3c7 100644 --- a/src/backend/libc/net/addr.rs +++ b/src/backend/libc/net/addr.rs @@ -321,7 +321,7 @@ impl SocketAddrStorage { // SAFETY: `self.0` is a `sockaddr_storage` so it has enough space. unsafe { AddressFamily::from_raw(crate::backend::net::read_sockaddr::read_sa_family( - crate::utils::as_ptr(&self.0).cast::(), + crate::utils::as_ptr(&self.0).cast(), )) } } @@ -332,7 +332,7 @@ impl SocketAddrStorage { // SAFETY: `self.0` is a `sockaddr_storage` so it has enough space. unsafe { crate::backend::net::read_sockaddr::initialize_family_to_unspec( - crate::utils::as_mut_ptr(&mut self.0).cast::(), + crate::utils::as_mut_ptr(&mut self.0).cast(), ) } } diff --git a/src/backend/libc/net/read_sockaddr.rs b/src/backend/libc/net/read_sockaddr.rs index 5f8c48ec7..5962aa499 100644 --- a/src/backend/libc/net/read_sockaddr.rs +++ b/src/backend/libc/net/read_sockaddr.rs @@ -122,7 +122,7 @@ pub(crate) unsafe fn sockaddr_nonempty(storage: *const c::sockaddr, len: SocketA } assert!(len as usize >= size_of::()); - let family: c::c_int = read_sa_family(storage.cast::()).into(); + let family: c::c_int = read_sa_family(storage.cast()).into(); if family == c::AF_UNSPEC { return false; } @@ -240,7 +240,7 @@ pub(crate) fn read_sockaddr_xdp(addr: &SocketAddrAny) -> Result= size_of::()); - let decode = unsafe { &*addr.as_ptr().cast::() }; + let decode: &c::sockaddr_xdp = unsafe { &*addr.as_ptr().cast() }; // This ignores the `sxdp_shared_umem_fd` field, which is only expected to // be significant in `bind` calls, and not returned from `acceptfrom` or @@ -259,6 +259,6 @@ pub(crate) fn read_sockaddr_netlink(addr: &SocketAddrAny) -> Result= size_of::()); - let decode = unsafe { &*addr.as_ptr().cast::() }; + let decode: &c::sockaddr_nl = unsafe { &*addr.as_ptr().cast() }; Ok(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups)) } diff --git a/src/backend/libc/net/syscalls.rs b/src/backend/libc/net/syscalls.rs index e9138143d..ed16f860d 100644 --- a/src/backend/libc/net/syscalls.rs +++ b/src/backend/libc/net/syscalls.rs @@ -64,14 +64,14 @@ pub(crate) unsafe fn recvfrom( // `recvfrom` does not write to the storage if the socket is // connection-oriented sockets, so we initialize the family field to // `AF_UNSPEC` so that we can detect this case. - initialize_family_to_unspec(addr.storage.as_mut_ptr().cast::()); + initialize_family_to_unspec(addr.storage.as_mut_ptr().cast()); let nread = ret_send_recv(c::recvfrom( borrowed_fd(fd), buf.0.cast(), send_recv_len(buf.1), bitflags_bits!(flags), - addr.storage.as_mut_ptr().cast::(), + addr.storage.as_mut_ptr().cast(), &mut addr.len, ))?; @@ -309,7 +309,7 @@ pub(crate) fn acceptfrom(sockfd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option< let mut addr = SocketAddrBuf::new(); let owned_fd = ret_owned_fd(c::accept( borrowed_fd(sockfd), - addr.storage.as_mut_ptr().cast::(), + addr.storage.as_mut_ptr().cast(), &mut addr.len, ))?; Ok((owned_fd, addr.into_any_option())) @@ -335,7 +335,7 @@ pub(crate) fn acceptfrom_with( let mut addr = SocketAddrBuf::new(); let owned_fd = ret_owned_fd(c::accept4( borrowed_fd(sockfd), - addr.storage.as_mut_ptr().cast::(), + addr.storage.as_mut_ptr().cast(), &mut addr.len, flags.bits() as c::c_int, ))?; @@ -389,7 +389,7 @@ pub(crate) fn getsockname(sockfd: BorrowedFd<'_>) -> io::Result { let mut addr = SocketAddrBuf::new(); ret(c::getsockname( borrowed_fd(sockfd), - addr.storage.as_mut_ptr().cast::(), + addr.storage.as_mut_ptr().cast(), &mut addr.len, ))?; Ok(addr.into_any()) @@ -401,7 +401,7 @@ pub(crate) fn getpeername(sockfd: BorrowedFd<'_>) -> io::Result(), + addr.storage.as_mut_ptr().cast(), &mut addr.len, ))?; Ok(addr.into_any_option()) @@ -425,7 +425,7 @@ pub(crate) fn socketpair( c::c_int::from(domain.0), (type_.0 | flags.bits()) as c::c_int, raw_protocol as c::c_int, - fds.as_mut_ptr().cast::(), + fds.as_mut_ptr().cast(), ))?; let [fd0, fd1] = fds.assume_init(); diff --git a/src/backend/libc/pipe/syscalls.rs b/src/backend/libc/pipe/syscalls.rs index fe5249546..43e99ec67 100644 --- a/src/backend/libc/pipe/syscalls.rs +++ b/src/backend/libc/pipe/syscalls.rs @@ -26,7 +26,7 @@ use { pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { unsafe { let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); - ret(c::pipe(result.as_mut_ptr().cast::()))?; + ret(c::pipe(result.as_mut_ptr().cast()))?; let [p0, p1] = result.assume_init(); Ok((p0, p1)) } @@ -44,10 +44,7 @@ pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { unsafe { let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); - ret(c::pipe2( - result.as_mut_ptr().cast::(), - bitflags_bits!(flags), - ))?; + ret(c::pipe2(result.as_mut_ptr().cast(), bitflags_bits!(flags)))?; let [p0, p1] = result.assume_init(); Ok((p0, p1)) } @@ -87,7 +84,7 @@ pub(crate) unsafe fn vmsplice( ) -> io::Result { ret_usize(c::vmsplice( borrowed_fd(fd), - bufs.as_ptr().cast::(), + bufs.as_ptr().cast(), min(bufs.len(), MAX_IOV), flags.bits(), )) diff --git a/src/backend/libc/pipe/types.rs b/src/backend/libc/pipe/types.rs index 38e255169..f3d4d27b9 100644 --- a/src/backend/libc/pipe/types.rs +++ b/src/backend/libc/pipe/types.rs @@ -82,7 +82,7 @@ impl<'a> IoSliceRaw<'a> { pub fn from_slice(buf: &'a [u8]) -> Self { IoSliceRaw { _buf: c::iovec { - iov_base: (buf.as_ptr() as *mut u8).cast::(), + iov_base: (buf.as_ptr() as *mut u8).cast(), iov_len: buf.len() as _, }, _lifetime: PhantomData, @@ -93,7 +93,7 @@ impl<'a> IoSliceRaw<'a> { pub fn from_slice_mut(buf: &'a mut [u8]) -> Self { IoSliceRaw { _buf: c::iovec { - iov_base: buf.as_mut_ptr().cast::(), + iov_base: buf.as_mut_ptr().cast(), iov_len: buf.len() as _, }, _lifetime: PhantomData, diff --git a/src/backend/libc/thread/syscalls.rs b/src/backend/libc/thread/syscalls.rs index 84356fee4..9c1bc9c97 100644 --- a/src/backend/libc/thread/syscalls.rs +++ b/src/backend/libc/thread/syscalls.rs @@ -360,13 +360,7 @@ pub(crate) fn capget( ) via SYS_capget -> c::c_int } - unsafe { - ret(capget( - as_mut_ptr(header), - data.as_mut_ptr() - .cast::(), - )) - } + unsafe { ret(capget(as_mut_ptr(header), data.as_mut_ptr().cast())) } } #[cfg(linux_kernel)] diff --git a/src/backend/libc/time/types.rs b/src/backend/libc/time/types.rs index 35173abce..b6c50ca82 100644 --- a/src/backend/libc/time/types.rs +++ b/src/backend/libc/time/types.rs @@ -109,7 +109,7 @@ pub(crate) fn as_libc_itimerspec_ptr(itimerspec: &Itimerspec) -> *const c::itime { static_assertions::assert_eq_size!(Itimerspec, c::itimerspec); } - crate::utils::as_ptr(itimerspec).cast::() + crate::utils::as_ptr(itimerspec).cast() } #[cfg(any( @@ -127,7 +127,7 @@ pub(crate) fn as_libc_itimerspec_mut_ptr( { static_assertions::assert_eq_size!(Itimerspec, c::itimerspec); } - itimerspec.as_mut_ptr().cast::() + itimerspec.as_mut_ptr().cast() } #[cfg(any( diff --git a/src/backend/linux_raw/net/addr.rs b/src/backend/linux_raw/net/addr.rs index 501ca29a1..5b8854474 100644 --- a/src/backend/linux_raw/net/addr.rs +++ b/src/backend/linux_raw/net/addr.rs @@ -57,7 +57,7 @@ impl SocketAddrUnix { let id = &mut unix.sun_path[1..]; // SAFETY: Convert `&mut [c_char]` to `&mut [u8]`. - let id = unsafe { slice::from_raw_parts_mut(id.as_mut_ptr().cast::(), id.len()) }; + let id = unsafe { slice::from_raw_parts_mut(id.as_mut_ptr().cast(), id.len()) }; if let Some(id) = id.get_mut(..name.len()) { id.copy_from_slice(name); @@ -275,7 +275,7 @@ impl SocketAddrStorage { // SAFETY: `self.0` is a `sockaddr_storage` so it has enough space. unsafe { AddressFamily::from_raw(crate::backend::net::read_sockaddr::read_sa_family( - crate::utils::as_ptr(&self.0).cast::(), + crate::utils::as_ptr(&self.0).cast(), )) } } @@ -286,7 +286,7 @@ impl SocketAddrStorage { // SAFETY: `self.0` is a `sockaddr_storage` so it has enough space. unsafe { crate::backend::net::read_sockaddr::initialize_family_to_unspec( - crate::utils::as_mut_ptr(&mut self.0).cast::(), + crate::utils::as_mut_ptr(&mut self.0).cast(), ) } } diff --git a/src/backend/linux_raw/net/netdevice.rs b/src/backend/linux_raw/net/netdevice.rs index 1736d9da8..728be644c 100644 --- a/src/backend/linux_raw/net/netdevice.rs +++ b/src/backend/linux_raw/net/netdevice.rs @@ -7,7 +7,6 @@ use crate::fd::BorrowedFd; use crate::io; use core::ptr::addr_of_mut; use core::{slice, str}; -use linux_raw_sys::ctypes::c_char; use linux_raw_sys::ioctl::{SIOCGIFINDEX, SIOCGIFNAME}; use linux_raw_sys::net::{ifreq, ifreq__bindgen_ty_1, ifreq__bindgen_ty_2, IFNAMSIZ}; @@ -21,9 +20,8 @@ pub(crate) fn name_to_index(fd: BorrowedFd<'_>, if_name: &str) -> io::Result(), if_name_bytes.len()) - }; + let if_name_bytes = + unsafe { slice::from_raw_parts(if_name_bytes.as_ptr().cast(), if_name_bytes.len()) }; let mut ifreq = ifreq { ifr_ifrn: ifreq__bindgen_ty_1 { ifrn_name: [0; 16] }, @@ -54,7 +52,7 @@ pub(crate) fn index_to_name(fd: BorrowedFd<'_>, index: u32) -> io::Result<(usize // SAFETY: Convert `&[c_char]` to `&[u8]`. let ifrn_name = - unsafe { slice::from_raw_parts(ifrn_name.as_ptr().cast::(), ifrn_name.len()) }; + unsafe { slice::from_raw_parts(ifrn_name.as_ptr().cast(), ifrn_name.len()) }; let mut name_buf = [0; 16]; name_buf[..ifrn_name.len()].copy_from_slice(ifrn_name); diff --git a/src/backend/linux_raw/net/read_sockaddr.rs b/src/backend/linux_raw/net/read_sockaddr.rs index f18cd4833..39455b94a 100644 --- a/src/backend/linux_raw/net/read_sockaddr.rs +++ b/src/backend/linux_raw/net/read_sockaddr.rs @@ -110,7 +110,7 @@ pub(crate) fn read_sockaddr_unix(addr: &SocketAddrAny) -> Result(), bytes.len()) }; + let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len()) }; return SocketAddrUnix::new_abstract_name(bytes); } @@ -119,7 +119,7 @@ pub(crate) fn read_sockaddr_unix(addr: &SocketAddrAny) -> Result(), bytes.len()) }; + let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len()) }; assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); SocketAddrUnix::new(bytes) diff --git a/src/backend/linux_raw/net/syscalls.rs b/src/backend/linux_raw/net/syscalls.rs index 488e08f02..245d2d1ec 100644 --- a/src/backend/linux_raw/net/syscalls.rs +++ b/src/backend/linux_raw/net/syscalls.rs @@ -537,7 +537,7 @@ pub(crate) unsafe fn recvfrom( // `recvfrom` does not write to the storage if the socket is // connection-oriented sockets, so we initialize the family field to // `AF_UNSPEC` so that we can detect this case. - initialize_family_to_unspec(addr.storage.as_mut_ptr().cast::()); + initialize_family_to_unspec(addr.storage.as_mut_ptr().cast()); #[cfg(not(target_arch = "x86"))] let nread = ret_usize(syscall!( diff --git a/src/backend/linux_raw/param/init.rs b/src/backend/linux_raw/param/init.rs index dd58cf60b..79e0b0acd 100644 --- a/src/backend/linux_raw/param/init.rs +++ b/src/backend/linux_raw/param/init.rs @@ -151,13 +151,13 @@ unsafe fn init_from_auxp(mut auxp: *const Elf_auxv_t) { AT_HWCAP => HWCAP.store(a_val as usize, Ordering::Relaxed), AT_HWCAP2 => HWCAP2.store(a_val as usize, Ordering::Relaxed), AT_MINSIGSTKSZ => MINSIGSTKSZ.store(a_val as usize, Ordering::Relaxed), - AT_EXECFN => EXECFN.store(a_val.cast::(), Ordering::Relaxed), - AT_SYSINFO_EHDR => SYSINFO_EHDR.store(a_val.cast::(), Ordering::Relaxed), + AT_EXECFN => EXECFN.store(a_val.cast(), Ordering::Relaxed), + AT_SYSINFO_EHDR => SYSINFO_EHDR.store(a_val.cast(), Ordering::Relaxed), #[cfg(feature = "runtime")] AT_SECURE => SECURE.store(a_val as usize != 0, Ordering::Relaxed), #[cfg(feature = "runtime")] - AT_PHDR => PHDR.store(a_val.cast::(), Ordering::Relaxed), + AT_PHDR => PHDR.store(a_val.cast(), Ordering::Relaxed), #[cfg(feature = "runtime")] AT_PHNUM => PHNUM.store(a_val as usize, Ordering::Relaxed), #[cfg(feature = "runtime")] @@ -165,7 +165,7 @@ unsafe fn init_from_auxp(mut auxp: *const Elf_auxv_t) { #[cfg(feature = "runtime")] AT_ENTRY => ENTRY.store(a_val as usize, Ordering::Relaxed), #[cfg(feature = "runtime")] - AT_RANDOM => RANDOM.store(a_val.cast::<[u8; 16]>(), Ordering::Relaxed), + AT_RANDOM => RANDOM.store(a_val.cast(), Ordering::Relaxed), AT_NULL => break, _ => (), diff --git a/src/backend/linux_raw/pipe/types.rs b/src/backend/linux_raw/pipe/types.rs index ae1855626..3aabe96c1 100644 --- a/src/backend/linux_raw/pipe/types.rs +++ b/src/backend/linux_raw/pipe/types.rs @@ -65,7 +65,7 @@ impl<'a> IoSliceRaw<'a> { pub fn from_slice(buf: &'a [u8]) -> Self { IoSliceRaw { _buf: c::iovec { - iov_base: (buf.as_ptr() as *mut u8).cast::(), + iov_base: (buf.as_ptr() as *mut u8).cast(), iov_len: buf.len() as _, }, _lifetime: PhantomData, @@ -76,7 +76,7 @@ impl<'a> IoSliceRaw<'a> { pub fn from_slice_mut(buf: &'a mut [u8]) -> Self { IoSliceRaw { _buf: c::iovec { - iov_base: buf.as_mut_ptr().cast::(), + iov_base: buf.as_mut_ptr().cast(), iov_len: buf.len() as _, }, _lifetime: PhantomData, diff --git a/src/backend/linux_raw/vdso.rs b/src/backend/linux_raw/vdso.rs index 4fa1d1ccf..4ff86a3d2 100644 --- a/src/backend/linux_raw/vdso.rs +++ b/src/backend/linux_raw/vdso.rs @@ -282,10 +282,7 @@ impl Vdso { return false; // No definition. } - def = def - .cast::() - .add((*def).vd_next as usize) - .cast::(); + def = def.cast::().add((*def).vd_next as usize).cast(); } // Now figure out whether it matches. diff --git a/src/buffer.rs b/src/buffer.rs index 3584c5b39..3bb586068 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -176,7 +176,7 @@ impl<'a, T> private::Sealed for &'a mut [MaybeUninit] { let (init, uninit) = self.split_at_mut(len); // SAFETY: The user asserts that the slice is now initialized. - let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::(), init.len()); + let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast(), init.len()); (init, uninit) } @@ -195,7 +195,7 @@ impl<'a, T, const N: usize> private::Sealed for &'a mut [MaybeUninit; N] { let (init, uninit) = self.split_at_mut(len); // SAFETY: The user asserts that the slice is now initialized. - let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::(), init.len()); + let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast(), init.len()); (init, uninit) } @@ -215,7 +215,7 @@ impl<'a, T> private::Sealed for &'a mut Vec> { let (init, uninit) = self.split_at_mut(len); // SAFETY: The user asserts that the slice is now initialized. - let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::(), init.len()); + let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast(), init.len()); (init, uninit) } diff --git a/src/io_uring/bindgen_types.rs b/src/io_uring/bindgen_types.rs index c45aefb67..efb068d38 100644 --- a/src/io_uring/bindgen_types.rs +++ b/src/io_uring/bindgen_types.rs @@ -18,12 +18,12 @@ impl IncompleteArrayField { #[inline] pub fn as_ptr(&self) -> *const T { - as_ptr(self).cast::() + as_ptr(self).cast() } #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { - as_mut_ptr(self).cast::() + as_mut_ptr(self).cast() } #[inline] diff --git a/src/io_uring/mod.rs b/src/io_uring/mod.rs index 00fde8df5..0e6c832c0 100644 --- a/src/io_uring/mod.rs +++ b/src/io_uring/mod.rs @@ -229,7 +229,7 @@ pub unsafe fn io_uring_enter_sigmask( to_submit, min_complete, flags, - option_as_ptr(sigmask).cast::(), + option_as_ptr(sigmask).cast(), size_of::(), ) } @@ -272,7 +272,7 @@ pub unsafe fn io_uring_enter_arg( to_submit, min_complete, flags, - option_as_ptr(arg).cast::(), + option_as_ptr(arg).cast(), size_of::(), ) } diff --git a/src/ioctl/patterns.rs b/src/ioctl/patterns.rs index a08aae74e..ff72006d9 100644 --- a/src/ioctl/patterns.rs +++ b/src/ioctl/patterns.rs @@ -153,7 +153,7 @@ unsafe impl Ioctl for Setter { } fn as_ptr(&mut self) -> *mut c::c_void { - addr_of_mut!(self.input).cast::() + addr_of_mut!(self.input).cast() } unsafe fn output_from_ptr(_: IoctlOutput, _: *mut c::c_void) -> Result { diff --git a/src/net/send_recv/msg.rs b/src/net/send_recv/msg.rs index 234e9933a..6dbdbd34d 100644 --- a/src/net/send_recv/msg.rs +++ b/src/net/send_recv/msg.rs @@ -300,20 +300,19 @@ impl<'buf, 'slice, 'fd> SendAncillaryBuffer<'buf, 'slice, 'fd> { match msg { SendAncillaryMessage::ScmRights(fds) => { let fds_bytes = - unsafe { slice::from_raw_parts(fds.as_ptr().cast::(), size_of_val(fds)) }; + unsafe { slice::from_raw_parts(fds.as_ptr().cast(), size_of_val(fds)) }; self.push_ancillary(fds_bytes, c::SOL_SOCKET as _, c::SCM_RIGHTS as _) } #[cfg(linux_kernel)] SendAncillaryMessage::ScmCredentials(ucred) => { - let ucred_bytes = unsafe { - slice::from_raw_parts(addr_of!(ucred).cast::(), size_of_val(&ucred)) - }; + let ucred_bytes = + unsafe { slice::from_raw_parts(addr_of!(ucred).cast(), size_of_val(&ucred)) }; self.push_ancillary(ucred_bytes, c::SOL_SOCKET as _, c::SCM_CREDENTIALS as _) } #[cfg(target_os = "linux")] SendAncillaryMessage::TxTime(tx_time) => { let tx_time_bytes = unsafe { - slice::from_raw_parts(addr_of!(tx_time).cast::(), size_of_val(&tx_time)) + slice::from_raw_parts(addr_of!(tx_time).cast(), size_of_val(&tx_time)) }; self.push_ancillary(tx_time_bytes, c::SOL_SOCKET as _, c::SO_TXTIME as _) } diff --git a/src/path/arg.rs b/src/path/arg.rs index 851d3a69b..594ff546b 100644 --- a/src/path/arg.rs +++ b/src/path/arg.rs @@ -963,7 +963,7 @@ where // Taken from // let mut buf = MaybeUninit::<[u8; SMALL_PATH_BUFFER_SIZE]>::uninit(); - let buf_ptr = buf.as_mut_ptr().cast::(); + let buf_ptr = buf.as_mut_ptr().cast(); // This helps test our safety condition below. debug_assert!(bytes.len() + 1 <= SMALL_PATH_BUFFER_SIZE); @@ -1024,7 +1024,7 @@ where // Taken from // let mut buf = MaybeUninit::<[u8; LARGE_PATH_BUFFER_SIZE]>::uninit(); - let buf_ptr = buf.as_mut_ptr().cast::(); + let buf_ptr = buf.as_mut_ptr().cast(); // This helps test our safety condition below. if bytes.len() + 1 > LARGE_PATH_BUFFER_SIZE { diff --git a/src/timespec.rs b/src/timespec.rs index 44721958f..0b1012ced 100644 --- a/src/timespec.rs +++ b/src/timespec.rs @@ -309,7 +309,7 @@ pub(crate) fn as_libc_timespec_ptr(timespec: &Timespec) -> *const c::timespec { { static_assertions::assert_eq_size!(Timespec, c::timespec); } - crate::utils::as_ptr(timespec).cast::() + crate::utils::as_ptr(timespec).cast() } #[cfg(not(fix_y2038))] @@ -320,7 +320,7 @@ pub(crate) fn as_libc_timespec_mut_ptr( { static_assertions::assert_eq_size!(Timespec, c::timespec); } - timespec.as_mut_ptr().cast::() + timespec.as_mut_ptr().cast() } #[cfg(not(fix_y2038))] diff --git a/tests/io_uring/register.rs b/tests/io_uring/register.rs index 02d6287aa..6e8e2f922 100644 --- a/tests/io_uring/register.rs +++ b/tests/io_uring/register.rs @@ -45,7 +45,7 @@ fn register_ring(fd: BorrowedFd<'_>) -> Result> { fd, false, IoringRegisterOp::RegisterRingFds, - (&mut update as *mut io_uring_rsrc_update).cast::(), + (&mut update as *mut io_uring_rsrc_update).cast(), 1, )?; @@ -65,7 +65,7 @@ where fd, true, IoringRegisterOp::UnregisterRingFds, - (&update as *const io_uring_rsrc_update as *mut io_uring_rsrc_update).cast::(), + (&update as *const io_uring_rsrc_update as *mut io_uring_rsrc_update).cast(), 1, )?; @@ -83,7 +83,7 @@ where fd, true, IoringRegisterOp::RegisterIowqMaxWorkers, - (&iowq_max_workers as *const [u32; 2] as *mut [u32; 2]).cast::(), + (&iowq_max_workers as *const [u32; 2] as *mut [u32; 2]).cast(), 2, )?; @@ -98,7 +98,7 @@ where fd, false, IoringRegisterOp::RegisterPbufRing, - (reg as *const io_uring_buf_reg as *mut io_uring_buf_reg).cast::(), + (reg as *const io_uring_buf_reg as *mut io_uring_buf_reg).cast(), 1, ) } diff --git a/tests/mm/mlock.rs b/tests/mm/mlock.rs index 6ca74d4d0..337bb4639 100644 --- a/tests/mm/mlock.rs +++ b/tests/mm/mlock.rs @@ -3,8 +3,6 @@ //! We can't easily test that it actually locks memory, but we can test that we //! can call it and either get success or a reasonable error message. -use std::ffi::c_void; - #[test] fn test_mlock() { let mut buf = vec![0_u8; 4096]; @@ -16,8 +14,8 @@ fn test_mlock() { let ptr = ((ptr as usize) & (-4096_isize) as usize) as *mut u8; unsafe { - match rustix::mm::mlock(ptr.cast::(), buf.len()) { - Ok(()) => rustix::mm::munlock(ptr.cast::(), buf.len()).unwrap(), + match rustix::mm::mlock(ptr.cast(), buf.len()) { + Ok(()) => rustix::mm::munlock(ptr.cast(), buf.len()).unwrap(), // Tests won't always have enough memory or permissions, and that's ok. Err(rustix::io::Errno::PERM | rustix::io::Errno::NOMEM) => {} // But they shouldn't fail otherwise. @@ -33,11 +31,11 @@ fn test_mlock_with() { unsafe { match rustix::mm::mlock_with( - buf.as_mut_ptr().cast::(), + buf.as_mut_ptr().cast(), buf.len(), rustix::mm::MlockFlags::empty(), ) { - Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::(), buf.len()).unwrap(), + Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast(), buf.len()).unwrap(), // Tests won't always have enough memory or permissions, and that's ok. Err(rustix::io::Errno::PERM | rustix::io::Errno::NOMEM | rustix::io::Errno::NOSYS) => {} // But they shouldn't fail otherwise. @@ -67,11 +65,11 @@ fn test_mlock_with_onfault() { unsafe { match rustix::mm::mlock_with( - buf.as_mut_ptr().cast::(), + buf.as_mut_ptr().cast(), buf.len(), rustix::mm::MlockFlags::ONFAULT, ) { - Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::(), buf.len()).unwrap(), + Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast(), buf.len()).unwrap(), // Tests won't always have enough memory or permissions, and that's ok. Err(rustix::io::Errno::PERM | rustix::io::Errno::NOMEM | rustix::io::Errno::NOSYS) => {} // But they shouldn't fail otherwise. From eed777d0d69246812533de7b1570c03e81f5104b Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Thu, 3 Sep 2026 17:42:21 +0100 Subject: [PATCH 7/9] Add support for Hermit OS in libs --- src/backend/libc/c.rs | 9 ++++++++ src/backend/libc/io/errno.rs | 2 +- src/backend/libc/io/syscalls.rs | 15 +++++++++---- src/backend/libc/io/types.rs | 1 + src/io/dup.rs | 3 ++- src/io/fcntl.rs | 4 +++- src/io/ioctl.rs | 7 +++++- src/io/read_write.rs | 6 +++-- src/ioctl/mod.rs | 1 + src/lib.rs | 10 ++++++++- src/maybe_polyfill/no_std/os/fd/owned.rs | 28 ++++++++++++++++++++---- src/maybe_polyfill/no_std/os/mod.rs | 2 +- src/maybe_polyfill/std/mod.rs | 7 +++++- 13 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/backend/libc/c.rs b/src/backend/libc/c.rs index fb748979f..dac4be811 100644 --- a/src/backend/libc/c.rs +++ b/src/backend/libc/c.rs @@ -168,6 +168,15 @@ pub(super) use {pread64 as pread, pwrite64 as pwrite}; #[cfg(any(target_os = "linux", target_os = "hurd", target_os = "emscripten"))] pub(super) use {preadv64 as preadv, pwritev64 as pwritev}; +// TODO: https://github.com/rust-lang/libc/pull/5460 +#[cfg(target_os = "hermit")] +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub(crate) struct iovec { + pub iov_base: *mut c_void, + pub iov_len: usize, +} + #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))] pub(super) unsafe fn prlimit( pid: pid_t, diff --git a/src/backend/libc/io/errno.rs b/src/backend/libc/io/errno.rs index 81f0e4893..252afec5e 100644 --- a/src/backend/libc/io/errno.rs +++ b/src/backend/libc/io/errno.rs @@ -791,7 +791,7 @@ impl Errno { #[cfg(not(target_os = "l4re"))] pub const NOTSOCK: Self = Self(c::ENOTSOCK); /// `ENOTSUP` - #[cfg(not(any(windows, target_os = "redox")))] + #[cfg(not(any(windows, target_os = "hermit", target_os = "redox")))] pub const NOTSUP: Self = Self(c::ENOTSUP); /// `ENOTTY` #[cfg(not(windows))] diff --git a/src/backend/libc/io/syscalls.rs b/src/backend/libc/io/syscalls.rs index 3993d5d67..0fa528c36 100644 --- a/src/backend/libc/io/syscalls.rs +++ b/src/backend/libc/io/syscalls.rs @@ -42,6 +42,7 @@ pub(crate) fn write(fd: BorrowedFd<'_>, buf: &[u8]) -> io::Result { } } +#[cfg(not(target_os = "hermit"))] pub(crate) unsafe fn pread( fd: BorrowedFd<'_>, buf: (*mut u8, usize), @@ -58,6 +59,7 @@ pub(crate) unsafe fn pread( ret_usize(c::pread(borrowed_fd(fd), buf.0.cast(), len, offset)) } +#[cfg(not(target_os = "hermit"))] pub(crate) fn pwrite(fd: BorrowedFd<'_>, buf: &[u8], offset: u64) -> io::Result { let len = min(buf.len(), READ_LIMIT); @@ -76,7 +78,7 @@ pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut<'_>]) -> io::Resu ret_usize(c::readv( borrowed_fd(fd), bufs.as_ptr().cast(), - min(bufs.len(), MAX_IOV) as c::c_int, + min(bufs.len(), MAX_IOV) as _, )) } } @@ -87,7 +89,7 @@ pub(crate) fn writev(fd: BorrowedFd<'_>, bufs: &[IoSlice<'_>]) -> io::Result, bufs: &[IoSlice<'_>]) -> io::Result) -> io::Result { let flags = unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFD))? }; Ok(FdFlags::from_bits_retain(bitcast!(flags))) } +#[cfg(not(target_os = "hermit"))] pub(crate) fn fcntl_setfd(fd: BorrowedFd<'_>, flags: FdFlags) -> io::Result<()> { unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETFD, flags.bits())) } } -#[cfg(not(any(target_os = "espidf", target_os = "wasi")))] +#[cfg(not(any(target_os = "espidf", target_os = "hermit", target_os = "wasi")))] pub(crate) fn fcntl_dupfd_cloexec(fd: BorrowedFd<'_>, min: RawFd) -> io::Result { unsafe { ret_owned_fd(c::fcntl(borrowed_fd(fd), c::F_DUPFD_CLOEXEC, min)) } } @@ -258,7 +264,7 @@ pub(crate) fn dup(fd: BorrowedFd<'_>) -> io::Result { } #[allow(clippy::needless_pass_by_ref_mut)] -#[cfg(not(target_os = "wasi"))] +#[cfg(not(any(target_os = "hermit", target_os = "wasi")))] pub(crate) fn dup2(fd: BorrowedFd<'_>, new: &mut OwnedFd) -> io::Result<()> { unsafe { ret_discarded_fd(c::dup2(borrowed_fd(fd), borrowed_fd(new.as_fd()))) } } @@ -271,6 +277,7 @@ pub(crate) fn dup2(fd: BorrowedFd<'_>, new: &mut OwnedFd) -> io::Result<()> { target_os = "dragonfly", target_os = "espidf", target_os = "haiku", + target_os = "hermit", target_os = "horizon", target_os = "nto", target_os = "redox", diff --git a/src/backend/libc/io/types.rs b/src/backend/libc/io/types.rs index b434b68af..9c376942b 100644 --- a/src/backend/libc/io/types.rs +++ b/src/backend/libc/io/types.rs @@ -55,6 +55,7 @@ bitflags! { apple, target_os = "aix", target_os = "android", + target_os = "hermit", target_os = "redox", )))] // Android 5.0 has dup3, but libc doesn't have bindings const CLOEXEC = bitcast!(c::O_CLOEXEC); diff --git a/src/io/dup.rs b/src/io/dup.rs index 1d1a4852d..6df4bfd6e 100644 --- a/src/io/dup.rs +++ b/src/io/dup.rs @@ -84,7 +84,7 @@ pub fn dup(fd: Fd) -> io::Result { /// [`stdio::dup2_stdin`]: crate::stdio::dup2_stdin /// [`stdio::dup2_stdout`]: crate::stdio::dup2_stdout /// [`stdio::dup2_stderr`]: crate::stdio::dup2_stderr -#[cfg(not(target_os = "wasi"))] +#[cfg(not(any(target_os = "hermit", target_os = "wasi")))] #[inline] pub fn dup2(fd: Fd, new: &mut OwnedFd) -> io::Result<()> { backend::io::syscalls::dup2(fd.as_fd(), new) @@ -114,6 +114,7 @@ pub fn dup2(fd: Fd, new: &mut OwnedFd) -> io::Result<()> { #[cfg(not(any( target_os = "aix", target_os = "espidf", + target_os = "hermit", target_os = "horizon", target_os = "nto", target_os = "vita", diff --git a/src/io/fcntl.rs b/src/io/fcntl.rs index fcb63a3ba..b09b31ffd 100644 --- a/src/io/fcntl.rs +++ b/src/io/fcntl.rs @@ -35,6 +35,7 @@ pub use backend::io::types::FdFlags; /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=fcntl§ion=2 /// [illumos]: https://illumos.org/man/2/fcntl /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Control-Operations.html#index-fcntl-function +#[cfg(not(target_os = "hermit"))] #[inline] #[doc(alias = "F_GETFD")] pub fn fcntl_getfd(fd: Fd) -> io::Result { @@ -63,6 +64,7 @@ pub fn fcntl_getfd(fd: Fd) -> io::Result { /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=fcntl§ion=2 /// [illumos]: https://illumos.org/man/2/fcntl /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Control-Operations.html#index-fcntl-function +#[cfg(not(target_os = "hermit"))] #[inline] #[doc(alias = "F_SETFD")] pub fn fcntl_setfd(fd: Fd, flags: FdFlags) -> io::Result<()> { @@ -99,7 +101,7 @@ pub fn fcntl_setfd(fd: Fd, flags: FdFlags) -> io::Result<()> { /// [illumos]: https://illumos.org/man/2/fcntl /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Control-Operations.html#index-fcntl-function /// [file description]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_258 -#[cfg(not(any(target_os = "espidf", target_os = "wasi")))] +#[cfg(not(any(target_os = "espidf", target_os = "hermit", target_os = "wasi")))] #[inline] #[doc(alias = "F_DUPFD_CLOEXEC")] pub fn fcntl_dupfd_cloexec(fd: Fd, min: RawFd) -> io::Result { diff --git a/src/io/ioctl.rs b/src/io/ioctl.rs index 33bf07cf5..52c125030 100644 --- a/src/io/ioctl.rs +++ b/src/io/ioctl.rs @@ -86,7 +86,12 @@ pub fn ioctl_fionbio(fd: Fd, value: bool) -> io::Result<()> { /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=ioctl&sektion=2#GENERIC%09IOCTLS /// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS /// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS -#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))] +#[cfg(not(any( + target_os = "espidf", + target_os = "hermit", + target_os = "horizon", + target_os = "vita" +)))] #[inline] #[doc(alias = "FIONREAD")] pub fn ioctl_fionread(fd: Fd) -> io::Result { diff --git a/src/io/read_write.rs b/src/io/read_write.rs index 0e0969103..aeeb1f84c 100644 --- a/src/io/read_write.rs +++ b/src/io/read_write.rs @@ -92,7 +92,7 @@ pub fn write(fd: Fd, buf: &[u8]) -> io::Result { /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pread§ion=2 /// [illumos]: https://illumos.org/man/2/pread /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-pread64 -#[cfg(not(windows))] +#[cfg(not(any(windows, target_os = "hermit")))] #[inline] pub fn pread>( fd: Fd, @@ -131,7 +131,7 @@ pub fn pread>( /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pwrite§ion=2 /// [illumos]: https://illumos.org/man/2/pwrite /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-pwrite64 -#[cfg(not(windows))] +#[cfg(not(any(windows, target_os = "hermit")))] #[inline] pub fn pwrite(fd: Fd, buf: &[u8], offset: u64) -> io::Result { backend::io::syscalls::pwrite(fd.as_fd(), buf, offset) @@ -217,6 +217,7 @@ pub fn writev(fd: Fd, bufs: &[IoSlice<'_>]) -> io::Result { target_os = "cygwin", target_os = "espidf", target_os = "haiku", + target_os = "hermit", target_os = "horizon", target_os = "nto", target_os = "redox", @@ -256,6 +257,7 @@ pub fn preadv(fd: Fd, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io: target_os = "cygwin", target_os = "espidf", target_os = "haiku", + target_os = "hermit", target_os = "horizon", target_os = "nto", target_os = "redox", diff --git a/src/ioctl/mod.rs b/src/ioctl/mod.rs index 70c690530..a2d62d46b 100644 --- a/src/ioctl/mod.rs +++ b/src/ioctl/mod.rs @@ -330,6 +330,7 @@ type _Opcode = c::c_ulong; target_os = "aix", target_os = "cygwin", target_os = "fuchsia", + target_os = "hermit", target_os = "emscripten", target_os = "nto", target_os = "wasi", diff --git a/src/lib.rs b/src/lib.rs index c8d000332..40e6ba206 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -185,7 +185,15 @@ pub(crate) mod msan; // versions of libc and not others. #[cfg(any( all(linux_raw, feature = "use-libc-auxv"), - all(libc, not(any(windows, target_os = "espidf", target_os = "wasi"))) + all( + libc, + not(any( + windows, + target_os = "espidf", + target_os = "hermit", + target_os = "wasi" + )) + ) ))] #[macro_use] mod weak; diff --git a/src/maybe_polyfill/no_std/os/fd/owned.rs b/src/maybe_polyfill/no_std/os/fd/owned.rs index ca9b05f31..c3991fbd0 100644 --- a/src/maybe_polyfill/no_std/os/fd/owned.rs +++ b/src/maybe_polyfill/no_std/os/fd/owned.rs @@ -101,7 +101,12 @@ impl BorrowedFd<'_> { impl OwnedFd { /// Creates a new `OwnedFd` instance that shares the same underlying file handle /// as the existing `OwnedFd` instance. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(any( + target_os = "hermit", + target_os = "motor", + target_os = "trusty", + target_os = "wasi" + )))] pub fn try_clone(&self) -> crate::io::Result { // We want to atomically duplicate this file descriptor and set the // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This @@ -121,7 +126,12 @@ impl OwnedFd { /// Creates a new `OwnedFd` instance that shares the same underlying file handle /// as the existing `OwnedFd` instance. - #[cfg(target_arch = "wasm32")] + #[cfg(any( + target_os = "hermit", + target_os = "motor", + target_os = "trusty", + target_os = "wasi" + ))] pub fn try_clone(&self) -> crate::io::Result { Err(crate::io::Errno::NOSYS) } @@ -130,7 +140,12 @@ impl OwnedFd { impl BorrowedFd<'_> { /// Creates a new `OwnedFd` instance that shares the same underlying file /// description as the existing `BorrowedFd` instance. - #[cfg(not(any(target_arch = "wasm32", target_os = "hermit")))] + #[cfg(not(any( + target_os = "hermit", + target_os = "motor", + target_os = "trusty", + target_os = "wasi" + )))] #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] pub fn try_clone_to_owned(&self) -> crate::io::Result { // Avoid using file descriptors below 3 as they are used for stdio @@ -153,7 +168,12 @@ impl BorrowedFd<'_> { /// Creates a new `OwnedFd` instance that shares the same underlying file /// description as the existing `BorrowedFd` instance. - #[cfg(any(target_arch = "wasm32", target_os = "hermit"))] + #[cfg(any( + target_os = "hermit", + target_os = "motor", + target_os = "trusty", + target_os = "wasi" + ))] #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] pub fn try_clone_to_owned(&self) -> crate::io::Result { Err(crate::io::Errno::NOSYS) diff --git a/src/maybe_polyfill/no_std/os/mod.rs b/src/maybe_polyfill/no_std/os/mod.rs index 67f41f5b3..29d55c747 100644 --- a/src/maybe_polyfill/no_std/os/mod.rs +++ b/src/maybe_polyfill/no_std/os/mod.rs @@ -1,4 +1,4 @@ -#[cfg(any(unix, target_os = "wasi"))] +#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))] pub mod fd; #[cfg(windows)] pub mod windows; diff --git a/src/maybe_polyfill/std/mod.rs b/src/maybe_polyfill/std/mod.rs index 17b280959..41a126b38 100644 --- a/src/maybe_polyfill/std/mod.rs +++ b/src/maybe_polyfill/std/mod.rs @@ -21,7 +21,12 @@ pub mod os { pub mod fd { // Change to use `std::os::fd` when MSRV becomes Rust 1.66 or higher. - #[cfg(target_os = "wasi")] + #[cfg(any( + target_os = "hermit", + target_os = "motor", + target_os = "trusty", + target_os = "wasi" + ))] pub use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; #[cfg(unix)] pub use std::os::unix::io::{ From 3e64577fbd203f3b1eaa6e23c9b81543ac7860ae Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Thu, 3 Sep 2026 17:45:18 +0100 Subject: [PATCH 8/9] Fix std tests for Hermit OS --- tests/backends.rs | 2 +- tests/io/ioctl.rs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/backends.rs b/tests/backends.rs index 3ded514ff..b6c9435d6 100644 --- a/tests/backends.rs +++ b/tests/backends.rs @@ -82,7 +82,7 @@ fn test_backends() { #[cfg(windows)] let libc_dep = "windows-sys"; - #[cfg(any(unix, target_os = "wasi"))] + #[cfg(not(windows))] let libc_dep = "libc"; // Test the use-libc crate, which enables the "use-libc" cargo feature. diff --git a/tests/io/ioctl.rs b/tests/io/ioctl.rs index 77b0a76f0..e6c3d3900 100644 --- a/tests/io/ioctl.rs +++ b/tests/io/ioctl.rs @@ -1,5 +1,10 @@ // `ioctl_fionread` on Windows doesn't work on files. -#[cfg(not(any(windows, target_os = "cygwin", target_os = "haiku")))] +#[cfg(not(any( + windows, + target_os = "cygwin", + target_os = "hermit", + target_os = "haiku" +)))] #[test] fn test_ioctls() { let file = std::fs::File::open("Cargo.toml").unwrap(); From 6a5bdd4a3476a87543097b2b39439876ccc1af41 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sat, 5 Sep 2026 23:12:59 +0100 Subject: [PATCH 9/9] fixup! Add support for Hermit OS in libs --- Cargo.toml | 3 +++ src/backend/libc/c.rs | 9 --------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 816f54519..8942dd86d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -274,3 +274,6 @@ check-cfg = [ 'cfg(target_arch, values("xtensa"))', 'cfg(target_os, values("cygwin"))', ] + +[patch.crates-io] +libc = { git = "https://github.com/rust-lang/libc", branch = "libc-0.2" } diff --git a/src/backend/libc/c.rs b/src/backend/libc/c.rs index dac4be811..fb748979f 100644 --- a/src/backend/libc/c.rs +++ b/src/backend/libc/c.rs @@ -168,15 +168,6 @@ pub(super) use {pread64 as pread, pwrite64 as pwrite}; #[cfg(any(target_os = "linux", target_os = "hurd", target_os = "emscripten"))] pub(super) use {preadv64 as preadv, pwritev64 as pwritev}; -// TODO: https://github.com/rust-lang/libc/pull/5460 -#[cfg(target_os = "hermit")] -#[repr(C)] -#[derive(Clone, Copy, Debug)] -pub(crate) struct iovec { - pub iov_base: *mut c_void, - pub iov_len: usize, -} - #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))] pub(super) unsafe fn prlimit( pid: pid_t,