Merge branch 'bits-uio' into 'master'

split out non-POSIX preadv and pwritev to a bits header

See merge request redox-os/relibc!1490
This commit is contained in:
Mathew John Roberts
2026-06-24 06:35:37 +01:00
5 changed files with 93 additions and 58 deletions
+18
View File
@@ -0,0 +1,18 @@
# Non-POSIX spec: https://man7.org/linux/man-pages/man2/readv.2.html
#
# These functions have been split out to prevent namespace pollution in sys/uio.h.
after_includes = """
#include <bits/off-t.h> // for off_t from sys/types.h
#include <bits/ssize-t.h> // for ssize_t from sys/types.h
#include <bits/iovec.h> // for iovec from sys/uio.h
"""
include_guard = "_RELIBC_BITS_SYS_UIO_H"
language = "C"
no_includes = true
cpp_compat = true
[enum]
prefix_with_name = true
[export.rename]
"iovec" = "struct iovec"
+70
View File
@@ -0,0 +1,70 @@
//! `preadv` and `pwritev` implementation for `sys/uio.h`.
//!
//! Non-POSIX extensions, see <https://man7.org/linux/man-pages/man2/readv.2.html>.
use core::slice;
use crate::{
header::{
bits_iovec::{gather, iovec, scatter},
errno,
limits::IOV_MAX,
unistd,
},
platform::{
self,
types::{c_int, c_void, off_t, ssize_t},
},
};
/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/readv.2.html>.
///
/// Combines the functionality of `readv()` and `pread()`.
///
/// When successful, returns a non-negative number indicating the number of
/// bytes actually read. Upon failure, returns `-1`.
#[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::<c_void>(), vec.len(), offset) };
unsafe { scatter(iovs, vec) };
ret
}
/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/readv.2.html>.
///
/// Combined the functionality of `writev()` and `pwrite()`.
///
/// When successful, returns a non-negative number indicating the number of
/// bytes actually written. Upon failure, returns `-1`.
#[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::<c_void>(), vec.len(), offset) }
}
+1
View File
@@ -64,6 +64,7 @@ pub mod bits_ucred;
pub mod bits_uid_t;
#[path = "bits_uint32-t/mod.rs"]
pub mod bits_uint32_t;
pub mod bits_uio;
#[path = "bits_useconds-t/mod.rs"]
pub mod bits_useconds_t;
pub mod bits_valist;
+3 -3
View File
@@ -8,9 +8,9 @@ after_includes = """
#include <bits/ssize-t.h> // for ssize_t from sys/types.h
#include <bits/iovec.h> // for iovec
// TODO should be guarded by _DEFAULT_SOURCE or _BSD_SOURCE
// for Non-POSIX functions preadv and pwritev
#include <bits/off-t.h> // for off_t from sys/types.h
#if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
#include <bits/uio.h> // for Non-POSIX functions preadv and pwritev
#endif
"""
include_guard = "_RELIBC_SYS_UIO_H"
language = "C"
+1 -55
View File
@@ -8,66 +8,12 @@ use crate::{
header::{errno, limits::IOV_MAX, unistd},
platform::{
self,
types::{c_int, c_void, off_t, ssize_t},
types::{c_int, c_void, ssize_t},
},
};
pub use crate::header::bits_iovec::{gather, iovec, scatter};
// TODO should be guarded by _DEFAULT_SOURCE or _BSD_SOURCE
/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/readv.2.html>.
///
/// Combines the functionality of `readv()` and `pread()`.
///
/// When successful, returns a non-negative number indicating the number of
/// bytes actually read. Upon failure, returns `-1`.
#[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::<c_void>(), vec.len(), offset) };
unsafe { scatter(iovs, vec) };
ret
}
// TODO should be guarded by _DEFAULT_SOURCE or _BSD_SOURCE
/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/readv.2.html>.
///
/// Combined the functionality of `writev()` and `pwrite()`.
///
/// When successful, returns a non-negative number indicating the number of
/// bytes actually written. Upon failure, returns `-1`.
#[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::<c_void>(), vec.len(), offset) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/readv.html>.
///
/// Equivalent to `read()` but places the input data into the `iovcnt` buffers