diff --git a/src/uu/tr/src/operation.rs b/src/uu/tr/src/operation.rs index ae01c61ec..d28a3a189 100644 --- a/src/uu/tr/src/operation.rs +++ b/src/uu/tr/src/operation.rs @@ -23,7 +23,7 @@ use std::{ io::{BufRead, Write}, ops::Not, }; -use uucore::error::{UError, UResult, USimpleError}; +use uucore::error::{FromIo, UError, UResult}; use uucore::show_warning; #[derive(Debug, Clone)] @@ -669,12 +669,9 @@ where let filtered = buf.iter().filter_map(|&c| translator.translate(c)); output_buf.extend(filtered); - if let Err(e) = output.write_all(&output_buf) { - return Err(USimpleError::new( - 1, - format!("{}: write error: {}", uucore::util_name(), e), - )); - } + output + .write_all(&output_buf) + .map_err_context(|| "write error".into())?; buf.clear(); output_buf.clear(); diff --git a/src/uu/tr/src/tr.rs b/src/uu/tr/src/tr.rs index 068d3bd03..96d3f0d49 100644 --- a/src/uu/tr/src/tr.rs +++ b/src/uu/tr/src/tr.rs @@ -14,9 +14,9 @@ use operation::{ Sequence, SqueezeOperation, SymbolTranslator, TranslateOperation, translate_input, }; use std::ffi::OsString; -use std::io::{BufWriter, stdin, stdout}; +use std::io::{BufWriter, Write, stdin, stdout}; use uucore::display::Quotable; -use uucore::error::{UResult, USimpleError, UUsageError}; +use uucore::error::{FromIo, UResult, USimpleError, UUsageError}; use uucore::fs::is_stdin_directory; use uucore::{format_usage, help_about, help_section, help_usage, os_str_as_bytes, show}; @@ -110,9 +110,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let stdin = stdin(); let mut locked_stdin = stdin.lock(); - let stdout = stdout(); - let locked_stdout = stdout.lock(); - let mut buffered_stdout = BufWriter::new(locked_stdout); + let mut buffered_stdout = BufWriter::new(stdout().lock()); // According to the man page: translating only happens if deleting or if a second set is given let translating = !delete_flag && sets.len() > 1; @@ -155,6 +153,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let op = TranslateOperation::new(set1, set2)?; translate_input(&mut locked_stdin, &mut buffered_stdout, op)?; } + + buffered_stdout + .flush() + .map_err_context(|| "write error".into())?; + Ok(()) } diff --git a/tests/by-util/test_tr.rs b/tests/by-util/test_tr.rs index 964fb5df2..847211192 100644 --- a/tests/by-util/test_tr.rs +++ b/tests/by-util/test_tr.rs @@ -1545,3 +1545,14 @@ fn test_non_digit_repeat() { .fails() .stderr_only("tr: invalid repeat count 'c' in [c*n] construct\n"); } + +#[cfg(target_os = "linux")] +#[test] +fn test_failed_write_is_reported() { + new_ucmd!() + .pipe_in("hello") + .args(&["e", "a"]) + .set_stdout(std::fs::File::create("/dev/full").unwrap()) + .fails() + .stderr_is("tr: write error: No space left on device\n"); +}