use std::os::fd::{FromRawFd, OwnedFd};
use std::{io, ptr};
use crate::fd::{self, AsyncFd};
use crate::op::{OpState, operation};
use crate::{SubmissionQueue, man_link, new_flag, sys, syscall};
#[doc = man_link!(pipe(2))]
pub fn pipe(sq: SubmissionQueue) -> Pipe {
let resources = ([-1, -1], fd::Kind::File);
Pipe::new(sq, resources, PipeFlag(0))
}
new_flag!(
pub struct PipeFlag(u32) {
#[cfg(any(target_os = "android", target_os = "linux"))]
DIRECT = libc::O_DIRECT,
}
);
operation!(
pub struct Pipe(sys::pipe::PipeOp) -> io::Result<[AsyncFd; 2]>;
);
impl Pipe {
pub fn kind(mut self, kind: fd::Kind) -> Self {
if let Some(resources) = self.state.resources_mut() {
resources.1 = kind;
}
self
}
pub fn flags(mut self, flags: PipeFlag) -> Self {
if let Some(f) = self.state.args_mut() {
*f = flags;
}
self
}
}
pub fn sync_pipe() -> io::Result<[OwnedFd; 2]> {
sync_pipe2(PipeFlag(0))
}
pub fn sync_pipe2(flags: PipeFlag) -> io::Result<[OwnedFd; 2]> {
let mut fds = [-1, -1];
let flags = flags.0.cast_signed() | libc::O_CLOEXEC;
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
let flags = flags | libc::O_NONBLOCK;
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
))]
syscall!(pipe2(ptr::from_mut(&mut fds).cast(), flags))?;
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "visionos",
target_os = "watchos",
))]
syscall!(pipe(ptr::from_mut(&mut fds).cast()))?;
let owned_fds = unsafe { [OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1])] };
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "visionos",
target_os = "watchos",
))]
{
syscall!(fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK))?;
syscall!(fcntl(fds[0], libc::F_SETFD, libc::FD_CLOEXEC))?;
syscall!(fcntl(fds[1], libc::F_SETFL, libc::O_NONBLOCK))?;
syscall!(fcntl(fds[1], libc::F_SETFD, libc::FD_CLOEXEC))?;
let _ = flags;
}
Ok(owned_fds)
}