use ax_errno::{AxError, AxResult};
use bitflags::bitflags;
use linux_raw_sys::general::{O_CLOEXEC, O_NONBLOCK};
use starry_signal::SignalSet;
use starry_vm::VmPtr;
use crate::{
file::{FileLike, add_file_like, signalfd::Signalfd},
syscall::signal::check_sigset_size,
};
const SFD_CLOEXEC: u32 = O_CLOEXEC;
const SFD_NONBLOCK: u32 = O_NONBLOCK;
bitflags! {
#[derive(Debug, Clone, Copy, Default)]
pub struct SignalfdFlags: u32 {
const CLOEXEC = SFD_CLOEXEC;
const NONBLOCK = SFD_NONBLOCK;
}
}
pub fn sys_signalfd4(
fd: i32,
mask: *const SignalSet,
sigsetsize: usize,
flags: u32,
) -> AxResult<isize> {
check_sigset_size(sigsetsize)?;
let flags = SignalfdFlags::from_bits(flags).ok_or(AxError::InvalidInput)?;
if fd != -1 && flags.contains(SignalfdFlags::CLOEXEC) {
return Err(AxError::InvalidInput);
}
let mask = unsafe { mask.vm_read_uninit()?.assume_init() };
if fd != -1 {
let signalfd = Signalfd::from_fd(fd)?;
signalfd.update_mask(mask);
signalfd.set_nonblocking(flags.contains(SignalfdFlags::NONBLOCK))?;
return Ok(fd as _);
}
let signalfd = Signalfd::new(mask);
signalfd.set_nonblocking(flags.contains(SignalfdFlags::NONBLOCK))?;
add_file_like(signalfd as _, flags.contains(SignalfdFlags::CLOEXEC)).map(|fd| fd as _)
}