diff --git a/src/uu/tee/src/cli.rs b/src/uu/tee/src/cli.rs index 9ad54405061..68fe5f4f1c0 100644 --- a/src/uu/tee/src/cli.rs +++ b/src/uu/tee/src/cli.rs @@ -18,7 +18,7 @@ pub mod options { pub const OUTPUT_ERROR: &str = "output-error"; } -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub enum OutputErrorMode { /// Diagnose write error on any output Warn, diff --git a/src/uu/tee/src/tee.rs b/src/uu/tee/src/tee.rs index f5e51039868..95030e79319 100644 --- a/src/uu/tee/src/tee.rs +++ b/src/uu/tee/src/tee.rs @@ -84,7 +84,7 @@ fn tee(options: &Options) -> Result<()> { }, ); - let mut output = MultiWriter::new(writers, options.output_error.clone()); + let mut output = MultiWriter::new(writers, options.output_error); let input = NamedReader { inner: stdin() }; #[cfg(target_os = "linux")] @@ -164,7 +164,6 @@ impl MultiWriter { Ok(0) => return Ok(()), // end of file Ok(received) => { self.write_all(&buffer[..received])?; - self.flush()?; // avoid buffering } Err(e) if e.kind() != ErrorKind::Interrupted => return Err(e), _ => {} @@ -177,8 +176,6 @@ impl MultiWriter { Ok(0) => return Ok(()), // end of file Ok(received) => { self.write_all(&buffer[..received])?; - // avoid buffering - self.flush()?; } Err(e) if e.kind() != ErrorKind::Interrupted => return Err(e), _ => {} @@ -200,8 +197,8 @@ impl MultiWriter { } fn process_error( - mode: Option<&OutputErrorMode>, - f: Error, + mode: Option, + e: Error, writer: &NamedWriter, ignored_errors: &mut usize, ) -> Result<()> { @@ -210,12 +207,12 @@ fn process_error( None | Some(OutputErrorMode::WarnNoPipe) | Some(OutputErrorMode::ExitNoPipe) ); - if ignore_pipe && f.kind() == ErrorKind::BrokenPipe { + if ignore_pipe && e.kind() == ErrorKind::BrokenPipe { return Ok(()); } - let _ = writeln!(stderr(), "{}: {f}", writer.name.maybe_quote()); + let _ = writeln!(stderr(), "{}: {e}", writer.name.maybe_quote()); if let Some(OutputErrorMode::Exit | OutputErrorMode::ExitNoPipe) = mode { - Err(f) + Err(e) } else { *ignored_errors += 1; Ok(()) @@ -225,45 +222,39 @@ fn process_error( impl Write for MultiWriter { fn write(&mut self, buf: &[u8]) -> Result { let mut aborted = None; - let mode = self.output_error_mode.clone(); let mut errors = 0; + let mode = self.output_error_mode; self.writers.retain_mut(|writer| { - writer - .write_all(buf) - .map_err(|f| { - let _ = process_error(mode.as_ref(), f, writer, &mut errors) - .map_err(|e| aborted.get_or_insert(e)); - }) - .is_ok() + let res = (|| { + writer.write_all(buf)?; + writer.flush() + })(); + match res { + Ok(()) => true, + Err(e) => { + if let Err(e) = process_error(mode, e, writer, &mut errors) { + aborted.get_or_insert(e); + } + false + } + } }); self.ignored_errors += errors; - if let Some(e) = aborted { - Err(e) - } else if self.writers.is_empty() { - // This error kind will never be raised by the standard - // library, so we can use it for early termination of - // `copy` - Err(Error::from(ErrorKind::Other)) - } else { - Ok(buf.len()) - } + aborted.map_or( + if self.writers.is_empty() { + // This error kind will never be raised by the standard + // library, so we can use it for early termination of + // `copy` + Err(Error::from(ErrorKind::Other)) + } else { + Ok(buf.len()) + }, + Err, + ) } fn flush(&mut self) -> Result<()> { - let mut aborted = None; - let mode = self.output_error_mode.clone(); - let mut errors = 0; - self.writers.retain_mut(|writer| { - writer - .flush() - .map_err(|f| { - let _ = process_error(mode.as_ref(), f, writer, &mut errors) - .map_err(|e| aborted.get_or_insert(e)); - }) - .is_ok() - }); - self.ignored_errors += errors; - aborted.map_or(Ok(()), Err) + Ok(()) } }