Skip to main content

relibc/header/sys_uio/
mod.rs

1//! `sys/uio.h` implementation.
2//!
3//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_uio.h.html>.
4
5use core::slice;
6
7use crate::{
8    header::{errno, limits::IOV_MAX, unistd},
9    platform::{
10        self,
11        types::{c_int, c_void, ssize_t},
12    },
13};
14
15pub use crate::header::bits_iovec::{gather, iovec, scatter};
16
17/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/readv.html>.
18///
19/// Equivalent to `read()` but places the input data into the `iovcnt` buffers
20/// specified by the members of the `iov` array.
21///
22/// When successful, returns a non-negative number indicating the number of
23/// bytes actually read. Upon failure, returns `-1`.
24#[unsafe(no_mangle)]
25pub unsafe extern "C" fn readv(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t {
26    if !(0..=IOV_MAX).contains(&iovcnt) {
27        platform::ERRNO.set(errno::EINVAL);
28        return -1;
29    }
30
31    let iovs = unsafe { slice::from_raw_parts(iov, iovcnt as usize) };
32    let mut vec = unsafe { gather(iovs) };
33
34    let ret = unsafe { unistd::read(fd, vec.as_mut_ptr().cast::<c_void>(), vec.len()) };
35
36    unsafe { scatter(iovs, vec) };
37
38    ret
39}
40
41/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/writev.html>.
42///
43/// Equivalent to `write()` but shall gather output data from the `iovcnt`
44/// buffers specified by the members of the `iov` array.
45///
46/// When successful, returns a non-negative number indicating the number of
47/// bytes actually written to the file associated with `fildes`. Upon failure,
48/// returns `-1`.
49#[unsafe(no_mangle)]
50pub unsafe extern "C" fn writev(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t {
51    if !(0..=IOV_MAX).contains(&iovcnt) {
52        platform::ERRNO.set(errno::EINVAL);
53        return -1;
54    }
55
56    let iovs = unsafe { slice::from_raw_parts(iov, iovcnt as usize) };
57    let vec = unsafe { gather(iovs) };
58
59    unsafe { unistd::write(fd, vec.as_ptr().cast::<c_void>(), vec.len()) }
60}