diff options
Diffstat (limited to 'vendor/rustix/src/backend/libc/io/syscalls.rs')
-rw-r--r-- | vendor/rustix/src/backend/libc/io/syscalls.rs | 226 |
1 files changed, 185 insertions, 41 deletions
diff --git a/vendor/rustix/src/backend/libc/io/syscalls.rs b/vendor/rustix/src/backend/libc/io/syscalls.rs index 3774e700a..03f9294d9 100644 --- a/vendor/rustix/src/backend/libc/io/syscalls.rs +++ b/vendor/rustix/src/backend/libc/io/syscalls.rs @@ -12,15 +12,13 @@ use super::super::offset::{libc_preadv, libc_pwritev}; #[cfg(all(target_os = "linux", target_env = "gnu"))] use super::super::offset::{libc_preadv2, libc_pwritev2}; use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd}; +#[cfg(bsd)] +use crate::io::kqueue::Event; +#[cfg(solarish)] +use crate::io::port::Event; #[cfg(not(any(target_os = "aix", target_os = "wasi")))] use crate::io::DupFlags; -#[cfg(not(any( - target_os = "aix", - target_os = "haiku", - target_os = "ios", - target_os = "macos", - target_os = "wasi" -)))] +#[cfg(not(any(apple, target_os = "aix", target_os = "haiku", target_os = "wasi")))] use crate::io::PipeFlags; use crate::io::{self, FdFlags, IoSlice, IoSliceMut, PollFd}; #[cfg(any(target_os = "android", target_os = "linux"))] @@ -167,7 +165,7 @@ pub(crate) fn preadv2( } /// At present, `libc` only has `preadv2` defined for glibc. On other -/// ABIs, `ReadWriteFlags` has no flags defined, and we use plain `preadv`. +/// ABIs, use `libc::syscall`. #[cfg(any( target_os = "android", all(target_os = "linux", not(target_env = "gnu")), @@ -179,8 +177,19 @@ pub(crate) fn preadv2( offset: u64, flags: ReadWriteFlags, ) -> io::Result<usize> { - assert!(flags.is_empty()); - preadv(fd, bufs, offset) + // Silently cast; we'll get `EINVAL` if the value is negative. + let offset = offset as i64; + let nread = unsafe { + ret_ssize_t(libc::syscall( + libc::SYS_preadv2, + borrowed_fd(fd), + bufs.as_ptr().cast::<c::iovec>(), + min(bufs.len(), max_iov()) as c::c_int, + offset, + flags.bits(), + ) as c::ssize_t)? + }; + Ok(nread as usize) } #[cfg(all(target_os = "linux", target_env = "gnu"))] @@ -205,7 +214,7 @@ pub(crate) fn pwritev2( } /// At present, `libc` only has `pwritev2` defined for glibc. On other -/// ABIs, `ReadWriteFlags` has no flags defined, and we use plain `pwritev`. +/// ABIs, use `libc::syscall`. #[cfg(any( target_os = "android", all(target_os = "linux", not(target_env = "gnu")), @@ -217,12 +226,23 @@ pub(crate) fn pwritev2( offset: u64, flags: ReadWriteFlags, ) -> io::Result<usize> { - assert!(flags.is_empty()); - pwritev(fd, bufs, offset) + // Silently cast; we'll get `EINVAL` if the value is negative. + let offset = offset as i64; + let nwritten = unsafe { + ret_ssize_t(libc::syscall( + libc::SYS_pwritev2, + borrowed_fd(fd), + bufs.as_ptr().cast::<c::iovec>(), + min(bufs.len(), max_iov()) as c::c_int, + offset, + flags.bits(), + ) as c::ssize_t)? + }; + Ok(nwritten as usize) } // These functions are derived from Rust's library/std/src/sys/unix/fd.rs at -// revision a77da2d454e6caa227a85b16410b95f93495e7e0. +// revision 326ef470a8b379a180d6dc4bbef08990698a737a. // The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, with the // man page quoting that if the count of bytes to read is greater than @@ -237,33 +257,28 @@ const READ_LIMIT: usize = c::c_int::MAX as usize - 1; #[cfg(not(target_os = "macos"))] const READ_LIMIT: usize = c::ssize_t::MAX as usize; -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] +#[cfg(bsd)] const fn max_iov() -> usize { c::IOV_MAX as usize } -#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))] +#[cfg(any( + target_os = "android", + target_os = "emscripten", + target_os = "linux", + target_os = "nto" +))] const fn max_iov() -> usize { c::UIO_MAXIOV as usize } #[cfg(not(any( + bsd, target_os = "android", - target_os = "dragonfly", target_os = "emscripten", - target_os = "freebsd", - target_os = "ios", target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", + target_os = "nto", + target_os = "horizon", )))] const fn max_iov() -> usize { 16 // The minimum value required by POSIX. @@ -321,6 +336,33 @@ pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> { } } +#[cfg(any(target_os = "android", target_os = "linux"))] +pub(crate) fn ioctl_ficlone(fd: BorrowedFd<'_>, src_fd: BorrowedFd<'_>) -> io::Result<()> { + // TODO: Enable `ioctl_ficlone` for android when upstream is updated. + // TODO: Enable `ioctl_ficlone` for more architectures when upstream is + // updated. + #[cfg(all( + target_os = "linux", + any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64") + ))] + unsafe { + ret(c::ioctl( + borrowed_fd(fd), + c::FICLONE as _, + borrowed_fd(src_fd), + )) + } + #[cfg(not(all( + target_os = "linux", + any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64") + )))] + { + let _ = fd; + let _ = src_fd; + Err(io::Errno::NOSYS) + } +} + #[cfg(not(any(target_os = "redox", target_os = "wasi")))] #[cfg(all(feature = "fs", feature = "net"))] pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> { @@ -398,12 +440,11 @@ pub(crate) fn dup2(fd: BorrowedFd<'_>, new: &mut OwnedFd) -> io::Result<()> { } #[cfg(not(any( + apple, target_os = "aix", target_os = "android", target_os = "dragonfly", target_os = "haiku", - target_os = "ios", - target_os = "macos", target_os = "redox", target_os = "wasi", )))] @@ -418,11 +459,10 @@ pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, flags: DupFlags) -> io } #[cfg(any( + apple, target_os = "android", target_os = "dragonfly", target_os = "haiku", - target_os = "ios", - target_os = "macos", target_os = "redox", ))] pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, _flags: DupFlags) -> io::Result<()> { @@ -433,7 +473,7 @@ pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, _flags: DupFlags) -> i dup2(fd, new) } -#[cfg(any(target_os = "ios", target_os = "macos"))] +#[cfg(apple)] pub(crate) fn ioctl_fioclex(fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { ret(c::ioctl(borrowed_fd(fd), c::FIOCLEX)) } } @@ -448,6 +488,34 @@ pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd) -> io::Result<()> { unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCNXCL as _)) } } +#[cfg(bsd)] +pub(crate) fn kqueue() -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(c::kqueue()) } +} + +#[cfg(bsd)] +pub(crate) unsafe fn kevent( + kq: BorrowedFd<'_>, + changelist: &[Event], + eventlist: &mut [MaybeUninit<Event>], + timeout: Option<&c::timespec>, +) -> io::Result<c::c_int> { + ret_c_int(c::kevent( + borrowed_fd(kq), + changelist.as_ptr() as *const _, + changelist + .len() + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, + eventlist.as_mut_ptr() as *mut _, + eventlist + .len() + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, + timeout.map_or(core::ptr::null(), |t| t as *const _), + )) +} + #[cfg(not(target_os = "wasi"))] pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { unsafe { @@ -458,13 +526,7 @@ pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { } } -#[cfg(not(any( - target_os = "aix", - target_os = "haiku", - target_os = "ios", - target_os = "macos", - target_os = "wasi" -)))] +#[cfg(not(any(apple, target_os = "aix", target_os = "haiku", target_os = "wasi")))] pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { unsafe { let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); @@ -531,3 +593,85 @@ pub unsafe fn vmsplice( )) .map(|spliced| spliced as usize) } + +#[cfg(solarish)] +pub(crate) fn port_create() -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(c::port_create()) } +} + +#[cfg(solarish)] +pub(crate) unsafe fn port_associate( + port: BorrowedFd<'_>, + source: c::c_int, + object: c::uintptr_t, + events: c::c_int, + user: *mut c::c_void, +) -> io::Result<()> { + ret(c::port_associate( + borrowed_fd(port), + source, + object, + events, + user, + )) +} + +#[cfg(solarish)] +pub(crate) unsafe fn port_dissociate( + port: BorrowedFd<'_>, + source: c::c_int, + object: c::uintptr_t, +) -> io::Result<()> { + ret(c::port_dissociate(borrowed_fd(port), source, object)) +} + +#[cfg(solarish)] +pub(crate) fn port_get( + port: BorrowedFd<'_>, + timeout: Option<&mut c::timespec>, +) -> io::Result<Event> { + let mut event = MaybeUninit::<c::port_event>::uninit(); + let timeout = timeout.map_or(core::ptr::null_mut(), |t| t as *mut _); + + unsafe { + ret(c::port_get(borrowed_fd(port), event.as_mut_ptr(), timeout))?; + } + + // If we're done, initialize the event and return it. + Ok(Event(unsafe { event.assume_init() })) +} + +#[cfg(solarish)] +pub(crate) fn port_getn( + port: BorrowedFd<'_>, + timeout: Option<&mut c::timespec>, + events: &mut Vec<Event>, + mut nget: u32, +) -> io::Result<()> { + let timeout = timeout.map_or(core::ptr::null_mut(), |t| t as *mut _); + unsafe { + ret(c::port_getn( + borrowed_fd(port), + events.as_mut_ptr().cast(), + events.len().try_into().unwrap(), + &mut nget, + timeout, + ))?; + } + + // Update the vector length. + unsafe { + events.set_len(nget.try_into().unwrap()); + } + + Ok(()) +} + +#[cfg(solarish)] +pub(crate) fn port_send( + port: BorrowedFd<'_>, + events: c::c_int, + userdata: *mut c::c_void, +) -> io::Result<()> { + unsafe { ret(c::port_send(borrowed_fd(port), events, userdata)) } +} |