use core::ffi::c_int;
use bitflags::bitflags;
use linux_raw_sys::general::{O_CLOEXEC, O_NONBLOCK};
use crate::{
StarryError,
file::{FileLike, Pipe, close_file_like},
mm::VmMutPtr,
};
bitflags! {
#[derive(Debug, Clone, Copy, Default)]
pub struct PipeFlags: u32 {
const CLOEXEC = O_CLOEXEC;
const NONBLOCK = O_NONBLOCK;
}
}
pub fn sys_pipe2(
current: &crate::task::UserTaskRef,
fds: *mut [c_int; 2],
flags: u32,
) -> crate::StarryResult<isize> {
let flags = PipeFlags::from_bits(flags).ok_or_else(|| {
warn!("sys_pipe2 <= unrecognized flags: {flags}");
StarryError::InvalidInput
})?;
let cloexec = flags.contains(PipeFlags::CLOEXEC);
let (read_end, write_end) = Pipe::new();
if flags.contains(PipeFlags::NONBLOCK) {
read_end.set_nonblocking(true)?;
write_end.set_nonblocking(true)?;
}
let read_fd = read_end.add_to_fd_table(cloexec)?;
let write_fd = write_end
.add_to_fd_table(cloexec)
.inspect_err(|_| close_file_like(read_fd).unwrap())?;
if let Err(err) = fds.vm_write(current, [read_fd, write_fd]) {
close_file_like(read_fd).ok();
close_file_like(write_fd).ok();
return Err(err.into());
}
debug!(
"sys_pipe2 <= fds: {:?}, flags: {:?}",
[read_fd, write_fd],
flags
);
Ok(0)
}