diff --git a/src/uu/cat/src/splice.rs b/src/uu/cat/src/splice.rs index 3b75b315b16..867a32df929 100644 --- a/src/uu/cat/src/splice.rs +++ b/src/uu/cat/src/splice.rs @@ -22,16 +22,10 @@ pub(super) fn write_fast_using_splice( write_fd: &mut S, ) -> CatResult { if splice(&handle.reader, &write_fd, MAX_ROOTLESS_PIPE_SIZE).is_ok() { - // fcntl improves throughput - // todo: avoid fcntl overhead for small input, but don't fcntl inside of the loop - let _ = rustix::pipe::fcntl_setpipe_size(&mut *write_fd, MAX_ROOTLESS_PIPE_SIZE); - loop { - match splice(&handle.reader, &write_fd, MAX_ROOTLESS_PIPE_SIZE) { - Ok(1..) => {} - Ok(0) => return Ok(might_fuse(&handle.reader)), - Err(_) => return Ok(true), - } - } + Ok( + uucore::pipes::splice_unbounded(&handle.reader, write_fd)? + || might_fuse(&handle.reader), + ) } else { Ok( uucore::pipes::splice_unbounded_broker(&handle.reader, write_fd)? diff --git a/src/uucore/src/lib/features/pipes.rs b/src/uucore/src/lib/features/pipes.rs index 1faf0f9229a..5716fde60f8 100644 --- a/src/uucore/src/lib/features/pipes.rs +++ b/src/uucore/src/lib/features/pipes.rs @@ -86,6 +86,31 @@ pub fn might_fuse(source: &impl AsFd) -> bool { rustix::fs::fstatfs(source).map_or(true, |stats| stats.f_type == 0x6573_5546) // FUSE magic number, too many platform specific clippy warning with const } +/// splice all of source to dest +/// return true if we need read/write fallback +/// fails if one of in/output should be pipe +#[inline] +#[cfg(any(target_os = "linux", target_os = "android"))] +pub fn splice_unbounded(source: &R, dest: &mut S) -> std::io::Result +where + R: Read + AsFd, + S: AsFd + std::io::Write, +{ + // improve throughput + // todo: avoid fcntl overhead for small input, but don't fcntl inside of the loop + // no need to increase pipe size of input fd since + // - sender with splice probably increased size already + // - sender without splice is bottleneck + let _ = fcntl_setpipe_size(&mut *dest, MAX_ROOTLESS_PIPE_SIZE); + loop { + match splice(&source, &dest, MAX_ROOTLESS_PIPE_SIZE) { + Ok(1..) => {} + Ok(0) => return Ok(false), + Err(_) => return Ok(true), + } + } +} + /// force-splice source to dest even both of them are not pipe /// return true if we need read/write fallback ///