use bitflags::bitflags;
use linux_raw_sys::general::{O_CLOEXEC, O_NONBLOCK};
use starry_signal::SignalSet;
use crate::{
StarryError, StarryResult,
file::{FileLike, add_file_like, signalfd::Signalfd},
mm::VmPtr,
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(
current: &crate::task::UserTaskRef,
fd: i32,
mask: *const SignalSet,
sigsetsize: usize,
flags: u32,
) -> StarryResult<isize> {
check_sigset_size(sigsetsize)?;
let flags = SignalfdFlags::from_bits(flags).ok_or(StarryError::InvalidInput)?;
let mask = unsafe { mask.vm_read_uninit(current)?.assume_init() };
if fd != -1 {
let signalfd = Signalfd::from_fd(fd)?;
signalfd.update_mask(mask);
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 _)
}