Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/cspell.dictionaries/workspace.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ weblate
algs
wasm
wasip
SETPIPE

# * stty terminal flags
brkint
Expand Down
11 changes: 8 additions & 3 deletions src/uu/cat/src/splice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ use super::{CatResult, FdReadable, InputHandle};
use nix::unistd;
use std::os::{fd::AsFd, unix::io::AsRawFd};

use uucore::pipes::{pipe, splice, splice_exact};
use uucore::pipes::{MAX_ROOTLESS_PIPE_SIZE, pipe, splice, splice_exact};

const SPLICE_SIZE: usize = 1024 * 128;
const BUF_SIZE: usize = 1024 * 16;

/// This function is called from `write_fast()` on Linux and Android. The
Expand All @@ -24,10 +23,16 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
handle: &InputHandle<R>,
write_fd: &S,
) -> CatResult<bool> {
use nix::fcntl::{FcntlArg, fcntl};
let (pipe_rd, pipe_wr) = pipe()?;
// improve performance
let _ = fcntl(
write_fd,
FcntlArg::F_SETPIPE_SZ(MAX_ROOTLESS_PIPE_SIZE as i32),
);

loop {
match splice(&handle.reader, &pipe_wr, SPLICE_SIZE) {
match splice(&handle.reader, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) {
Ok(n) => {
if n == 0 {
return Ok(false);
Expand Down
11 changes: 9 additions & 2 deletions src/uucore/src/lib/features/pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,28 @@

//! Thin pipe-related wrappers around functions from the `nix` crate.

#[cfg(any(target_os = "linux", target_os = "android"))]
use nix::fcntl::{FcntlArg, SpliceFFlags, fcntl};
#[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"))]
use nix::fcntl::SpliceFFlags;
pub const MAX_ROOTLESS_PIPE_SIZE: usize = 1024 * 1024;

pub use nix::{Error, Result};

/// A wrapper around [`nix::unistd::pipe`] that ensures the pipe is cleaned up.
///
/// Returns two `File` objects: everything written to the second can be read
/// from the first.
/// This is used only for resolving the limitation for splice: one of a input or output should be pipe
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn pipe() -> Result<(File, File)> {
let (read, write) = nix::unistd::pipe()?;
// improve performance for splice
let _ = fcntl(&read, FcntlArg::F_SETPIPE_SZ(MAX_ROOTLESS_PIPE_SIZE as i32));

Ok((File::from(read), File::from(write)))
}

Expand Down
Loading