cat: do not splice() on FUSE

This commit is contained in:
oech3
2026-04-12 16:33:58 +02:00
committed by Sylvestre Ledru
parent efd0f0cd10
commit bfdf580f0e
3 changed files with 14 additions and 3 deletions
+1
View File
@@ -367,6 +367,7 @@ uutils
# * function names
execfn
fstatfs
getcwd
setpipe
+3 -3
View File
@@ -7,7 +7,7 @@ use super::{CatResult, FdReadable, InputHandle};
use rustix::io::{read, write};
use std::os::{fd::AsFd, unix::io::AsRawFd};
use uucore::pipes::{MAX_ROOTLESS_PIPE_SIZE, pipe, splice, splice_exact};
use uucore::pipes::{MAX_ROOTLESS_PIPE_SIZE, might_fuse, pipe, splice, splice_exact};
const BUF_SIZE: usize = 1024 * 16;
@@ -30,7 +30,7 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
loop {
match splice(&handle.reader, &write_fd, MAX_ROOTLESS_PIPE_SIZE) {
Ok(1..) => {}
Ok(0) => return Ok(false),
Ok(0) => return Ok(might_fuse(&handle.reader)),
Err(_) => return Ok(true),
}
}
@@ -38,7 +38,7 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
// both of in/output are not pipe. needs broker to use splice() with additional costs
loop {
match splice(&handle.reader, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) {
Ok(0) => return Ok(false),
Ok(0) => return Ok(might_fuse(&handle.reader)),
Ok(n) => {
if splice_exact(&pipe_rd, write_fd, n).is_err() {
// If the first splice manages to copy to the intermediate
+10
View File
@@ -62,6 +62,16 @@ pub fn splice_exact(source: &impl AsFd, target: &impl AsFd, len: usize) -> std::
Ok(())
}
/// check that source is FUSE
/// we fallback to read() at FUSE <https://github.com/uutils/coreutils/issues/9609>
#[inline]
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn might_fuse(source: &impl AsFd) -> bool {
rustix::fs::fstatfs(source)
.map(|stats| stats.f_type == 0x6573_5546) // FUSE magic number, too many platform specific clippy warning with const
.unwrap_or(true)
}
/// Return verified /dev/null
///
/// `splice` to /dev/null is faster than `read` when we skip or count the non-seekable input