1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

tr: Flush BufWriter, fix double error context

Write errors led with `tr: tr: write error:`.
This commit is contained in:
Jan Verbeek 2025-03-31 13:23:45 +02:00
parent cf50952325
commit 181844eafa
3 changed files with 23 additions and 12 deletions

View file

@ -23,7 +23,7 @@ use std::{
io::{BufRead, Write}, io::{BufRead, Write},
ops::Not, ops::Not,
}; };
use uucore::error::{UError, UResult, USimpleError}; use uucore::error::{FromIo, UError, UResult};
use uucore::show_warning; use uucore::show_warning;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -669,12 +669,9 @@ where
let filtered = buf.iter().filter_map(|&c| translator.translate(c)); let filtered = buf.iter().filter_map(|&c| translator.translate(c));
output_buf.extend(filtered); output_buf.extend(filtered);
if let Err(e) = output.write_all(&output_buf) { output
return Err(USimpleError::new( .write_all(&output_buf)
1, .map_err_context(|| "write error".into())?;
format!("{}: write error: {}", uucore::util_name(), e),
));
}
buf.clear(); buf.clear();
output_buf.clear(); output_buf.clear();

View file

@ -14,9 +14,9 @@ use operation::{
Sequence, SqueezeOperation, SymbolTranslator, TranslateOperation, translate_input, Sequence, SqueezeOperation, SymbolTranslator, TranslateOperation, translate_input,
}; };
use std::ffi::OsString; use std::ffi::OsString;
use std::io::{BufWriter, stdin, stdout}; use std::io::{BufWriter, Write, stdin, stdout};
use uucore::display::Quotable; 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::fs::is_stdin_directory;
use uucore::{format_usage, help_about, help_section, help_usage, os_str_as_bytes, show}; 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 stdin = stdin();
let mut locked_stdin = stdin.lock(); let mut locked_stdin = stdin.lock();
let stdout = stdout(); let mut buffered_stdout = BufWriter::new(stdout().lock());
let locked_stdout = stdout.lock();
let mut buffered_stdout = BufWriter::new(locked_stdout);
// According to the man page: translating only happens if deleting or if a second set is given // According to the man page: translating only happens if deleting or if a second set is given
let translating = !delete_flag && sets.len() > 1; 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)?; let op = TranslateOperation::new(set1, set2)?;
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?; translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
} }
buffered_stdout
.flush()
.map_err_context(|| "write error".into())?;
Ok(()) Ok(())
} }

View file

@ -1545,3 +1545,14 @@ fn test_non_digit_repeat() {
.fails() .fails()
.stderr_only("tr: invalid repeat count 'c' in [c*n] construct\n"); .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");
}