Skip to content

Commit c93b9ed

Browse files
julian-klodedrinkcat
authored andcommitted
tr: use an unbuffered stdout
Our stdin that we transform already is buffered (using 8192 byte buffers in the previous commit), so avoid buffering our output needlessly. This effectively changes the code to write complete lines immediately, for example, in `( echo a; sleep 1 ) | tr a b` we receive read(0, "a\n", 8192) = 2 write(1, "b\n", 2) = 2 read(0, "", 8192) = 0 instead of read(0, "a\n", 8192) = 2 read(0, "", 8192) = 0 write(1, "b\n", 2) = 2 which matches the GNU coreutils behavior.
1 parent ef40c47 commit c93b9ed

File tree

1 file changed

+9
-9
lines changed

1 file changed

+9
-9
lines changed

src/uu/tr/src/tr.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use operation::{
1212
translate_input,
1313
};
1414
use std::ffi::OsString;
15-
use std::io::{BufWriter, Write, stdin, stdout};
15+
use std::io::{Write, stdin, stdout};
1616
use uucore::display::Quotable;
1717
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
1818
use uucore::fs::is_stdin_directory;
@@ -107,7 +107,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
107107

108108
let stdin = stdin();
109109
let mut locked_stdin = stdin.lock();
110-
let mut buffered_stdout = BufWriter::new(stdout().lock());
110+
let mut locked_stdout = stdout().lock();
111111

112112
// According to the man page: translating only happens if deleting or if a second set is given
113113
let translating = !delete_flag && sets.len() > 1;
@@ -131,34 +131,34 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
131131
let delete_op = DeleteOperation::new(set1);
132132
let squeeze_op = SqueezeOperation::new(set2);
133133
let op = delete_op.chain(squeeze_op);
134-
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
134+
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
135135
} else {
136136
let op = DeleteOperation::new(set1);
137-
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
137+
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
138138
}
139139
} else if squeeze_flag {
140140
if sets_len == 1 {
141141
let op = SqueezeOperation::new(set1);
142-
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
142+
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
143143
} else {
144144
let translate_op = TranslateOperation::new(set1, set2.clone())?;
145145
let squeeze_op = SqueezeOperation::new(set2);
146146
let op = translate_op.chain(squeeze_op);
147-
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
147+
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
148148
}
149149
} else {
150150
let op = TranslateOperation::new(set1, set2)?;
151-
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
151+
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
152152
}
153153

154154
#[cfg(not(target_os = "windows"))]
155-
buffered_stdout
155+
locked_stdout
156156
.flush()
157157
.map_err_context(|| translate!("tr-error-write-error"))?;
158158

159159
// SIGPIPE is not available on Windows.
160160
#[cfg(target_os = "windows")]
161-
match buffered_stdout.flush() {
161+
match locked_stdout.flush() {
162162
Ok(()) => {}
163163
Err(err) if err.kind() == std::io::ErrorKind::BrokenPipe => std::process::exit(13),
164164
Err(err) => return Err(err.map_err_context(|| translate!("tr-error-write-error"))),

0 commit comments

Comments
 (0)