Skip to main content

relibc/header/bits_uio/
mod.rs

1//! `preadv` and `pwritev` implementation for `sys/uio.h`.
2//!
3//! Non-POSIX extensions, see <https://man7.org/linux/man-pages/man2/readv.2.html>.
4
5use core::slice;
6
7use crate::{
8    header::{
9        bits_iovec::{gather, iovec, scatter},
10        errno,
11        limits::IOV_MAX,
12        unistd,
13    },
14    platform::{
15        self,
16        types::{c_int, c_void, off_t, ssize_t},
17    },
18};
19
20/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/readv.2.html>.
21///
22/// Combines the functionality of `readv()` and `pread()`.
23///
24/// When successful, returns a non-negative number indicating the number of
25/// bytes actually read. Upon failure, returns `-1`.
26#[unsafe(no_mangle)]
27pub unsafe extern "C" fn preadv(
28    fd: c_int,
29    iov: *const iovec,
30    iovcnt: c_int,
31    offset: off_t,
32) -> ssize_t {
33    if !(0..=IOV_MAX).contains(&iovcnt) {
34        platform::ERRNO.set(errno::EINVAL);
35        return -1;
36    }
37
38    let iovs = unsafe { slice::from_raw_parts(iov, iovcnt as usize) };
39    let mut vec = unsafe { gather(iovs) };
40
41    let ret = unsafe { unistd::pread(fd, vec.as_mut_ptr().cast::<c_void>(), vec.len(), offset) };
42
43    unsafe { scatter(iovs, vec) };
44
45    ret
46}
47
48/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/readv.2.html>.
49///
50/// Combined the functionality of `writev()` and `pwrite()`.
51///
52/// When successful, returns a non-negative number indicating the number of
53/// bytes actually written. Upon failure, returns `-1`.
54#[unsafe(no_mangle)]
55pub unsafe extern "C" fn pwritev(
56    fd: c_int,
57    iov: *const iovec,
58    iovcnt: c_int,
59    offset: off_t,
60) -> ssize_t {
61    if !(0..=IOV_MAX).contains(&iovcnt) {
62        platform::ERRNO.set(errno::EINVAL);
63        return -1;
64    }
65
66    let iovs = unsafe { slice::from_raw_parts(iov, iovcnt as usize) };
67    let vec = unsafe { gather(iovs) };
68
69    unsafe { unistd::pwrite(fd, vec.as_ptr().cast::<c_void>(), vec.len(), offset) }
70}