Skip to content

Commit 87570f3

Browse files
committed
cat: avoid pipe() if stdout is pipe
1 parent ac58184 commit 87570f3

1 file changed

Lines changed: 30 additions & 19 deletions

File tree

src/uu/cat/src/splice.rs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,43 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
2424
write_fd: &S,
2525
) -> CatResult<bool> {
2626
use nix::fcntl::{FcntlArg, fcntl};
27-
let (pipe_rd, pipe_wr) = pipe()?;
2827
// improve performance
29-
let _ = fcntl(
28+
if fcntl(
3029
write_fd,
3130
FcntlArg::F_SETPIPE_SZ(MAX_ROOTLESS_PIPE_SIZE as i32),
32-
);
33-
34-
loop {
35-
match splice(&handle.reader, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) {
36-
Ok(n) => {
37-
if n == 0 {
38-
return Ok(false);
31+
)
32+
.is_ok()
33+
{
34+
loop {
35+
match splice(&handle.reader, &write_fd, MAX_ROOTLESS_PIPE_SIZE) {
36+
Ok(0) => return Ok(false),
37+
Ok(_) => {}
38+
Err(_) => return Ok(true),
39+
}
40+
}
41+
} else {
42+
// output is not pipe. Needs hihi cost pipe as broker to use splice()
43+
let (pipe_rd, pipe_wr) = pipe()?;
44+
loop {
45+
match splice(&handle.reader, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) {
46+
Ok(n) => {
47+
if n == 0 {
48+
return Ok(false);
49+
}
50+
if splice_exact(&pipe_rd, write_fd, n).is_err() {
51+
// If the first splice manages to copy to the intermediate
52+
// pipe, but the second splice to stdout fails for some reason
53+
// we can recover by copying the data that we have from the
54+
// intermediate pipe to stdout using normal read/write. Then
55+
// we tell the caller to fall back.
56+
copy_exact(&pipe_rd, write_fd, n)?;
57+
return Ok(true);
58+
}
3959
}
40-
if splice_exact(&pipe_rd, write_fd, n).is_err() {
41-
// If the first splice manages to copy to the intermediate
42-
// pipe, but the second splice to stdout fails for some reason
43-
// we can recover by copying the data that we have from the
44-
// intermediate pipe to stdout using normal read/write. Then
45-
// we tell the caller to fall back.
46-
copy_exact(&pipe_rd, write_fd, n)?;
60+
Err(_) => {
4761
return Ok(true);
4862
}
4963
}
50-
Err(_) => {
51-
return Ok(true);
52-
}
5364
}
5465
}
5566
}

0 commit comments

Comments
 (0)