//! `sys/uio.h` implementation. //! //! See . use alloc::vec::Vec; use core::slice; use crate::{ header::{errno, unistd}, platform::{ self, types::{c_int, c_void, off_t, size_t, ssize_t}, }, }; pub const IOV_MAX: c_int = 1024; /// See . #[repr(C)] #[derive(Debug, CheckVsLibcCrate)] pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } impl iovec { unsafe fn to_slice(&self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self.iov_base.cast::(), self.iov_len) } } } unsafe fn gather(iovs: &[iovec]) -> Vec { let mut vec = Vec::new(); for iov in iovs.iter() { vec.extend_from_slice(unsafe { iov.to_slice() }); } vec } unsafe fn scatter(iovs: &[iovec], vec: Vec) { let mut i = 0; for iov in iovs.iter() { let slice = unsafe { iov.to_slice() }; slice.copy_from_slice(&vec[i..][..slice.len()]); i += slice.len(); } } /// Non-POSIX, see . #[unsafe(no_mangle)] pub unsafe extern "C" fn preadv( fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off_t, ) -> ssize_t { if !(0..=IOV_MAX).contains(&iovcnt) { platform::ERRNO.set(errno::EINVAL); return -1; } let iovs = unsafe { slice::from_raw_parts(iov, iovcnt as usize) }; let mut vec = unsafe { gather(iovs) }; let ret = unsafe { unistd::pread(fd, vec.as_mut_ptr().cast::(), vec.len(), offset) }; unsafe { scatter(iovs, vec) }; ret } /// Non-POSIX, see . #[unsafe(no_mangle)] pub unsafe extern "C" fn pwritev( fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off_t, ) -> ssize_t { if !(0..=IOV_MAX).contains(&iovcnt) { platform::ERRNO.set(errno::EINVAL); return -1; } let iovs = unsafe { slice::from_raw_parts(iov, iovcnt as usize) }; let vec = unsafe { gather(iovs) }; unsafe { unistd::pwrite(fd, vec.as_ptr().cast::(), vec.len(), offset) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn readv(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t { if !(0..=IOV_MAX).contains(&iovcnt) { platform::ERRNO.set(errno::EINVAL); return -1; } let iovs = unsafe { slice::from_raw_parts(iov, iovcnt as usize) }; let mut vec = unsafe { gather(iovs) }; let ret = unsafe { unistd::read(fd, vec.as_mut_ptr().cast::(), vec.len()) }; unsafe { scatter(iovs, vec) }; ret } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn writev(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t { if !(0..=IOV_MAX).contains(&iovcnt) { platform::ERRNO.set(errno::EINVAL); return -1; } let iovs = unsafe { slice::from_raw_parts(iov, iovcnt as usize) }; let vec = unsafe { gather(iovs) }; unsafe { unistd::write(fd, vec.as_ptr().cast::(), vec.len()) } }