#[cfg(any(target_os = "linux", target_os = "android"))]
use rustix::pipe::{SpliceFlags, fcntl_setpipe_size};
#[cfg(any(target_os = "linux", target_os = "android"))]
use std::fs::File;
#[cfg(any(target_os = "linux", target_os = "android"))]
use std::os::fd::AsFd;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub const MAX_ROOTLESS_PIPE_SIZE: usize = 1024 * 1024;
#[inline]
#[cfg(any(target_os = "linux", target_os = "android", test))]
pub fn pipe() -> std::io::Result<(File, File)> {
let (read, write) = rustix::pipe::pipe()?;
#[cfg(any(target_os = "linux", target_os = "android"))]
let _ = fcntl_setpipe_size(&read, MAX_ROOTLESS_PIPE_SIZE);
Ok((File::from(read), File::from(write)))
}
#[inline]
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn splice(source: &impl AsFd, target: &impl AsFd, len: usize) -> std::io::Result<usize> {
Ok(rustix::pipe::splice(
source,
None,
target,
None,
len,
SpliceFlags::empty(),
)?)
}
#[inline]
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn splice_exact(source: &impl AsFd, target: &impl AsFd, len: usize) -> std::io::Result<()> {
let mut left = len;
while left > 0 {
let written = splice(source, target, left)?;
debug_assert_ne!(written, 0, "unexpected end of data");
left -= written;
}
Ok(())
}
#[inline]
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn dev_null() -> Option<File> {
let null = std::fs::OpenOptions::new()
.write(true)
.open("/dev/null")
.ok()?;
let stat = rustix::fs::fstat(&null).ok()?;
let dev = stat.st_rdev;
if (rustix::fs::major(dev), rustix::fs::minor(dev)) == (1, 3) {
Some(null)
} else {
None
}
}