summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/backend/libc/io/syscalls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/backend/libc/io/syscalls.rs')
-rw-r--r--vendor/rustix/src/backend/libc/io/syscalls.rs226
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)) }
+}