diff --git a/src/uu/tee/src/tee.rs b/src/uu/tee/src/tee.rs index 29409fff26..8743889bf1 100644 --- a/src/uu/tee/src/tee.rs +++ b/src/uu/tee/src/tee.rs @@ -160,58 +160,20 @@ impl MultiWriter { let input = rustix::stdio::stdin(); #[cfg(not(any(unix, target_os = "wasi")))] let mut input = io::stdin(); - // needs 2 pipes to duplicate input multiple times - // freeze by max size since system allocates pipe smaller than default size when user has pages more than fs.pipe-user-pages-soft #[cfg(any(target_os = "linux", target_os = "android"))] - if let Ok((mut pipe_read, mut pipe_write)) = uucore::pipes::pipe::() - && let Ok((mut pipe2_read, mut pipe2_write)) = uucore::pipes::pipe::() - { - use uucore::pipes::MAX_ROOTLESS_PIPE_SIZE; - // improve throughput when stdout is pipe, but no needed to be same size with broker. - let _ = rustix::pipe::fcntl_setpipe_size(&self.writers[0], MAX_ROOTLESS_PIPE_SIZE); - macro_rules! splice_or_detach { - ($pipe_read:ident, $pipe_write:ident, $writer:expr, $len:expr) => { - if let Err(e) = uucore::pipes::drain_pipe(&$pipe_read, &$writer, $len) { - self.aborted |= process_error( - self.output_error_mode, - e, - &$writer, - &mut self.ignored_errors, - ).is_err(); - $writer.name.clear(); //mark as exited - // the failed write can leave bytes in the pipe: replace it with an empty one. - // Free it first, so that the new one does not need more file descriptors. - drop($pipe_read); - drop($pipe_write); - match uucore::pipes::pipe::() { - Ok(pipe) => ($pipe_read, $pipe_write) = pipe, - Err(e) => { - show_error!("{}", strip_errno(&e)); - return Err(()); - } - } - } - }; - } - while let Ok(s) = uucore::pipes::splice(&input, &pipe_write, MAX_ROOTLESS_PIPE_SIZE) { - if s == 0 { - return Ok(()); - } - let Some((last, others)) = self.writers.split_last_mut() else { - // all writers exited - return Ok(()); - }; - for other in others { - // do not consume input - let tee_res = uucore::pipes::tee(&pipe_read, &pipe2_write, s); - assert_eq!(tee_res, Ok(s), "2nd pipe should have enough spare"); - splice_or_detach!(pipe2_read, pipe2_write, *other, s); - } - // last one consumes input - splice_or_detach!(pipe_read, pipe_write, *last, s); - self.writers.retain(|w| !w.name.is_empty()); - if self.aborted { - return Err(()); + // There is no possible fast-path for multiple writers otherwise input is reliable. + if let [writer] = &mut self.writers[..] { + match uucore::pipes::splice_unbounded_auto(&input, writer) { + Ok(Ok(())) => return Ok(()), + Ok(Err(())) => {} // no splice support + Err(e) => { + return process_error( + self.output_error_mode, + e.into(), + writer, + &mut self.ignored_errors, + ) + .map_err(|_| ()); } } }