Skip to content

Commit 115235b

Browse files
committed
cat: fix usage on FUSE
1 parent c409373 commit 115235b

3 files changed

Lines changed: 25 additions & 4 deletions

File tree

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, is_end_of_file, pipe, 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(!is_end_of_file(&handle.reader)),
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(!is_end_of_file(&handle.reader)),
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/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jiff = { workspace = true, optional = true, features = [
3737
"tzdb-concatenated",
3838
] }
3939
rustc-hash = { workspace = true }
40-
rustix = { workspace = true, features = ["fs", "pipe"] }
40+
rustix = { workspace = true, features = ["event", "fs", "time", "pipe"] }
4141
time = { workspace = true, optional = true, features = [
4242
"formatting",
4343
"local-offset",

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,27 @@ pub fn splice(source: &impl AsFd, target: &impl AsFd, len: usize) -> std::io::Re
5252
)?)
5353
}
5454

55+
/// check that splice reached to end of file
56+
/// ignore 2nd Ctrl + D
57+
/// <https://github.com/uutils/coreutils/issues/9609>
58+
#[inline]
59+
#[cfg(any(target_os = "linux", target_os = "android"))]
60+
pub fn is_end_of_file(source: &impl AsFd) -> bool {
61+
use rustix::event::{PollFd, PollFlags, poll};
62+
use rustix::time::Timespec;
63+
let mut pfd = [PollFd::new(source, PollFlags::IN)];
64+
matches!(
65+
poll(
66+
&mut pfd,
67+
Some(&Timespec {
68+
tv_sec: 0,
69+
tv_nsec: 0
70+
})
71+
),
72+
Ok(0)
73+
)
74+
}
75+
5576
/// Splice wrapper which fully finishes the write.
5677
///
5778
/// Exactly `len` bytes are moved from `source` into `target`.

0 commit comments

Comments
 (0)