Skip to content

Commit 4927ec8

Browse files
committed
cat: fix usage on FUSE
1 parent 5d6d5cb commit 4927ec8

File tree

2 files changed

+15
-3
lines changed

2 files changed

+15
-3
lines changed

src/uu/cat/src/splice.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::{CatResult, FdReadable, InputHandle};
77
use rustix::io::{read, write};
88
use std::os::{fd::AsFd, unix::io::AsRawFd};
99

10-
use uucore::pipes::{MAX_ROOTLESS_PIPE_SIZE, pipe, splice, splice_exact};
10+
use uucore::pipes::{MAX_ROOTLESS_PIPE_SIZE, pipe, send_one_byte, splice, splice_exact};
1111

1212
const BUF_SIZE: usize = 1024 * 16;
1313

@@ -30,15 +30,15 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
3030
loop {
3131
match splice(&handle.reader, &write_fd, MAX_ROOTLESS_PIPE_SIZE) {
3232
Ok(1..) => {}
33-
Ok(0) => return Ok(false),
33+
Ok(0) => return Ok(send_one_byte(&handle.reader, &write_fd)),
3434
Err(_) => return Ok(true),
3535
}
3636
}
3737
} else if let Ok((pipe_rd, pipe_wr)) = pipe() {
3838
// both of in/output are not pipe. needs broker to use splice() with additional costs
3939
loop {
4040
match splice(&handle.reader, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) {
41-
Ok(0) => return Ok(false),
41+
Ok(0) => return Ok(send_one_byte(&handle.reader, &write_fd)),
4242
Ok(n) => {
4343
if splice_exact(&pipe_rd, write_fd, n).is_err() {
4444
// If the first splice manages to copy to the intermediate

src/uucore/src/lib/features/pipes.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ pub fn splice(source: &impl AsFd, target: &impl AsFd, len: usize) -> std::io::Re
5050
)?)
5151
}
5252

53+
/// check that splice reached to end of file
54+
/// try to send 1 byte and return true if succeed
55+
/// a workaround for kernel's bug with FUSE reporting wrong size
56+
/// https://github.com/uutils/coreutils/issues/9609
57+
#[inline]
58+
#[cfg(any(target_os = "linux", target_os = "android"))]
59+
pub fn send_one_byte(source: &impl AsFd, target: &impl AsFd) -> bool {
60+
use rustix::io::{read, write};
61+
let mut b = [0u8; 1];
62+
read(source, &mut b).is_ok_and(|n| n > 0 && write(target, &b).is_ok())
63+
}
64+
5365
/// Splice wrapper which fully finishes the write.
5466
///
5567
/// Exactly `len` bytes are moved from `source` into `target`.

0 commit comments

Comments
 (0)