1
0
Fork 0
forked from wry/wry

all: simplify handling of Errno values

This commit is contained in:
Julian Orth 2026-04-02 18:34:12 +02:00
parent 9c605df692
commit 34914eccb0
58 changed files with 443 additions and 464 deletions

View file

@ -2,7 +2,7 @@ use {
crate::{
forker::ForkerError,
pr_caps::drop_all_pr_caps,
utils::{errorfmt::ErrorFmt, process_name::set_process_name},
utils::{errorfmt::ErrorFmt, oserror::OsErrorExt2, process_name::set_process_name},
},
run_on_drop::on_drop,
std::{env, mem::MaybeUninit, process, slice, str::FromStr},
@ -22,9 +22,9 @@ pub fn fork_with_pidfd(pidfd_for_child: bool) -> Result<Forked, ForkerError> {
child_pidfd = Some(uapi::pidfd_open(uapi::getpid(), 0).unwrap());
}
let (p, c) = uapi::socketpair(c::AF_UNIX, c::SOCK_DGRAM | c::SOCK_CLOEXEC, 0)
.map_err(|e| ForkerError::Socketpair(e.into()))?;
.map_os_err(ForkerError::Socketpair)?;
unsafe {
let pid = uapi::fork().map_err(|e| ForkerError::Fork(e.into()))?;
let pid = uapi::fork().map_os_err(ForkerError::Fork)?;
let res = if pid == 0 {
drop(p);
env::remove_var(REAPER_VAR);
@ -44,7 +44,7 @@ pub fn fork_with_pidfd(pidfd_for_child: bool) -> Result<Forked, ForkerError> {
pub fn double_fork() -> Result<Option<OwnedFd>, ForkerError> {
let (p, c) = uapi::socketpair(c::AF_UNIX, c::SOCK_DGRAM | c::SOCK_CLOEXEC, 0)
.map_err(|e| ForkerError::Socketpair(e.into()))?;
.map_os_err(ForkerError::Socketpair)?;
match fork_with_pidfd(false)? {
Forked::Parent { pid, .. } => {
drop(c);
@ -150,8 +150,8 @@ fn recv_pidfd(socket: &OwnedFd) -> Result<OwnedFd, ForkerError> {
flags: 0,
};
let (_, _, mut ctrl) = uapi::recvmsg(socket.raw(), &mut msghdr, c::MSG_CMSG_CLOEXEC)
.map_err(|e| ForkerError::RecvPidfd(e.into()))?;
let (_, hdr, data) = uapi::cmsg_read(&mut ctrl).map_err(|e| ForkerError::CmsgRead(e.into()))?;
.map_os_err(ForkerError::RecvPidfd)?;
let (_, hdr, data) = uapi::cmsg_read(&mut ctrl).map_os_err(ForkerError::CmsgRead)?;
if hdr.cmsg_level != c::SOL_SOCKET || hdr.cmsg_type != c::SCM_RIGHTS {
return Err(ForkerError::InvalidCmsg);
}

View file

@ -1,13 +1,16 @@
use {crate::utils::oserror::OsError, uapi::c};
use {
crate::utils::oserror::{OsError, OsErrorExt},
uapi::c,
};
pub fn set_nonblock(fd: c::c_int) -> Result<(), OsError> {
let fl = uapi::fcntl_getfl(fd)?;
uapi::fcntl_setfl(fd, fl | c::O_NONBLOCK)?;
let fl = uapi::fcntl_getfl(fd).to_os_error()?;
uapi::fcntl_setfl(fd, fl | c::O_NONBLOCK).to_os_error()?;
Ok(())
}
pub fn set_block(fd: c::c_int) -> Result<(), OsError> {
let fl = uapi::fcntl_getfl(fd)?;
uapi::fcntl_setfl(fd, fl & !c::O_NONBLOCK)?;
let fl = uapi::fcntl_getfl(fd).to_os_error()?;
uapi::fcntl_setfl(fd, fl & !c::O_NONBLOCK).to_os_error()?;
Ok(())
}

View file

@ -1,17 +1,17 @@
use {
crate::utils::oserror::OsError,
crate::utils::oserror::{OsError, OsErrorExt},
smallvec::{SmallVec, smallvec_inline},
uapi::{Errno, c},
uapi::c,
};
#[cfg_attr(not(feature = "it"), expect(dead_code))]
pub fn num_cpus() -> Result<u32, OsError> {
let mut buf: SmallVec<[usize; 32]> = smallvec_inline![0; 32];
loop {
match uapi::sched_getaffinity(0, &mut buf) {
match uapi::sched_getaffinity(0, &mut buf).to_os_error() {
Ok(_) => return Ok(count(&buf)),
Err(Errno(c::EINVAL)) => buf.extend_from_slice(&[0; 32][..]),
Err(e) => return Err(e.into()),
Err(OsError(c::EINVAL)) => buf.extend_from_slice(&[0; 32][..]),
Err(e) => return Err(e),
}
}
}

View file

@ -169,12 +169,6 @@ static ERRORS: LazyLock<&'static [Option<&'static str>]> = LazyLock::new(|| {
#[derive(Debug, Eq, PartialEq)]
pub struct OsError(pub c::c_int);
impl From<Errno> for OsError {
fn from(e: Errno) -> Self {
Self(e.0)
}
}
impl From<c::c_int> for OsError {
fn from(v: c_int) -> Self {
Self(v)
@ -192,7 +186,7 @@ impl From<std::io::Error> for OsError {
impl Default for OsError {
fn default() -> Self {
Errno::default().into()
OsError(Errno::default().0)
}
}
@ -208,7 +202,6 @@ impl Display for OsError {
}
}
#[cfg_attr(not(feature = "it"), expect(dead_code))]
pub trait OsErrorExt {
type Container;
@ -219,6 +212,31 @@ impl<T> OsErrorExt for Result<T, Errno> {
type Container = Result<T, OsError>;
fn to_os_error(self) -> Self::Container {
self.map_err(|e| e.into())
match self {
Ok(v) => Ok(v),
Err(e) => Err(OsError(e.0)),
}
}
}
pub trait OsErrorExt2 {
type T;
fn map_os_err<F, O>(self, op: O) -> Result<Self::T, F>
where
O: FnOnce(OsError) -> F;
}
impl<T> OsErrorExt2 for Result<T, Errno> {
type T = T;
fn map_os_err<F, O>(self, op: O) -> Result<T, F>
where
O: FnOnce(OsError) -> F,
{
match self {
Ok(t) => Ok(t),
Err(e) => Err(op(OsError(e.0))),
}
}
}

View file

@ -1,5 +1,5 @@
use {
crate::utils::{errorfmt::ErrorFmt, oserror::OsError},
crate::utils::{errorfmt::ErrorFmt, oserror::OsErrorExt},
bstr::ByteSlice,
std::os::unix::ffi::OsStrExt,
uapi::{OwnedFd, c},
@ -46,12 +46,12 @@ pub fn get_socket_creds(socket: &OwnedFd) -> Option<(c::uid_t, c::pid_t)> {
uid: 0,
gid: 0,
};
match uapi::getsockopt(socket.raw(), c::SOL_SOCKET, c::SO_PEERCRED, &mut cred) {
match uapi::getsockopt(socket.raw(), c::SOL_SOCKET, c::SO_PEERCRED, &mut cred).to_os_error() {
Ok(_) => Some((cred.uid, cred.pid)),
Err(e) => {
log::error!(
"Cannot determine peer credentials of new connection: {:?}",
OsError::from(e)
"Cannot determine peer credentials of new connection: {}",
ErrorFmt(e),
);
None
}

View file

@ -1,5 +1,5 @@
use {
crate::utils::oserror::OsError,
crate::utils::oserror::{OsError, OsErrorExt},
c::{c_int, syscall},
std::{ptr, rc::Rc},
uapi::{
@ -19,5 +19,5 @@ pub fn pidfd_send_signal(pidfd: &Rc<OwnedFd>, signal: c_int) -> Result<(), OsErr
0,
)
};
map_err!(res).map(drop).map_err(|e| e.into())
map_err!(res).map(drop).to_os_error()
}

View file

@ -1,5 +1,5 @@
use {
crate::utils::oserror::OsError,
crate::utils::oserror::{OsError, OsErrorExt},
uapi::{OwnedFd, c, pipe2},
};
@ -9,7 +9,7 @@ pub struct Pipe<L, R> {
}
pub fn pipe() -> Result<Pipe<OwnedFd, OwnedFd>, OsError> {
let (read, write) = pipe2(c::O_CLOEXEC)?;
let (read, write) = pipe2(c::O_CLOEXEC).to_os_error()?;
Ok(Pipe { read, write })
}

View file

@ -1,7 +1,10 @@
use {
crate::{
io_uring::{IoUring, IoUringError},
utils::{buf::TypedBuf, oserror::OsError},
utils::{
buf::TypedBuf,
oserror::{OsError, OsErrorExt2},
},
},
std::{cell::RefCell, rc::Rc, time::Duration},
thiserror::Error,
@ -28,10 +31,9 @@ pub struct TimerFd {
impl TimerFd {
pub fn new(clock_id: c::c_int) -> Result<Self, TimerError> {
let fd = match uapi::timerfd_create(clock_id, c::TFD_CLOEXEC) {
Ok(fd) => Rc::new(fd),
Err(e) => return Err(TimerError::CreateTimer(e.into())),
};
let fd = uapi::timerfd_create(clock_id, c::TFD_CLOEXEC)
.map(Rc::new)
.map_os_err(TimerError::CreateTimer)?;
Ok(Self {
fd,
buf: Rc::new(RefCell::new(TypedBuf::new())),
@ -61,9 +63,7 @@ impl TimerFd {
timerspec.it_interval.tv_nsec = per.subsec_nanos() as _;
}
}
if let Err(e) = uapi::timerfd_settime(self.fd.raw(), 0, &timerspec) {
return Err(TimerError::SetTimer(e.into()));
}
uapi::timerfd_settime(self.fd.raw(), 0, &timerspec).map_os_err(TimerError::SetTimer)?;
Ok(())
}
}