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},
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();

View file

@ -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(())
}

View file

@ -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");
}