c-scape 0.22.3

A libc bottom-half implementation in Rust
Documentation
use crate::{convert_res, set_errno, Errno};
use libc::c_int;
use rustix::fd::{BorrowedFd, IntoRawFd};
use rustix::time::{TimerfdClockId, TimerfdFlags, TimerfdTimerFlags};

#[no_mangle]
unsafe extern "C" fn timerfd_create(clockid: c_int, flags: c_int) -> c_int {
    libc!(libc::timerfd_create(clockid, flags));

    let clockid = match clockid {
        libc::CLOCK_REALTIME => TimerfdClockId::Realtime,
        libc::CLOCK_MONOTONIC => TimerfdClockId::Monotonic,
        libc::CLOCK_BOOTTIME => TimerfdClockId::Boottime,
        libc::CLOCK_REALTIME_ALARM => TimerfdClockId::RealtimeAlarm,
        libc::CLOCK_BOOTTIME_ALARM => TimerfdClockId::BoottimeAlarm,
        _ => {
            set_errno(Errno(libc::EINVAL));
            return -1;
        }
    };
    let flags = TimerfdFlags::from_bits(flags.try_into().unwrap()).unwrap();
    match convert_res(rustix::time::timerfd_create(clockid, flags)) {
        Some(fd) => fd.into_raw_fd(),
        None => -1,
    }
}

#[no_mangle]
unsafe extern "C" fn timerfd_settime(
    fd: c_int,
    flags: c_int,
    new_value: *const libc::itimerspec,
    old_value: *mut libc::itimerspec,
) -> c_int {
    libc!(libc::timerfd_settime(fd, flags, new_value, old_value));

    let new_value = new_value.read();
    let new_value = rustix::time::Itimerspec {
        it_interval: rustix::time::Timespec {
            tv_sec: new_value.it_interval.tv_sec.into(),
            tv_nsec: new_value.it_interval.tv_nsec as _,
        },
        it_value: rustix::time::Timespec {
            tv_sec: new_value.it_value.tv_sec.into(),
            tv_nsec: new_value.it_value.tv_nsec as _,
        },
    };
    let flags = TimerfdTimerFlags::from_bits(flags.try_into().unwrap()).unwrap();
    match convert_res(rustix::time::timerfd_settime(
        BorrowedFd::borrow_raw(fd),
        flags,
        &new_value,
    )) {
        Some(value) => {
            if !old_value.is_null() {
                let value = libc::itimerspec {
                    it_interval: libc::timespec {
                        tv_sec: value.it_interval.tv_sec as _,
                        tv_nsec: value.it_interval.tv_nsec as _,
                    },
                    it_value: libc::timespec {
                        tv_sec: value.it_value.tv_sec as _,
                        tv_nsec: value.it_value.tv_nsec as _,
                    },
                };
                old_value.write(value);
            }
            0
        }
        None => -1,
    }
}