7
7
8
8
use clap:: { Arg , ArgAction , Command , builder:: PossibleValue } ;
9
9
use std:: fs:: OpenOptions ;
10
- use std:: io:: { Error , ErrorKind , Read , Result , Write , copy , stdin, stdout} ;
10
+ use std:: io:: { Error , ErrorKind , Read , Result , Write , stdin, stdout} ;
11
11
use std:: path:: PathBuf ;
12
12
use uucore:: display:: Quotable ;
13
13
use uucore:: error:: UResult ;
@@ -190,6 +190,7 @@ fn tee(options: &Options) -> Result<()> {
190
190
return Ok ( ( ) ) ;
191
191
}
192
192
193
+ // We cannot use std::io::copy here as it doesn't flush the output buffer
193
194
let res = match copy ( input, & mut output) {
194
195
// ErrorKind::Other is raised by MultiWriter when all writers
195
196
// have exited, so that copy will abort. It's equivalent to
@@ -207,6 +208,46 @@ fn tee(options: &Options) -> Result<()> {
207
208
}
208
209
}
209
210
211
+ /// Copies all bytes from the input buffer to the output buffer.
212
+ ///
213
+ /// Returns the number of written bytes.
214
+ fn copy ( mut input : impl Read , mut output : impl Write ) -> Result < usize > {
215
+ // The implementation for this function is adopted from the generic buffer copy implementation from
216
+ // the standard library:
217
+ // https://github.com/rust-lang/rust/blob/2feb91181882e525e698c4543063f4d0296fcf91/library/std/src/io/copy.rs#L271-L297
218
+
219
+ // Use buffer size from std implementation:
220
+ // https://github.com/rust-lang/rust/blob/2feb91181882e525e698c4543063f4d0296fcf91/library/std/src/sys/io/mod.rs#L44
221
+ // spell-checker:ignore espidf
222
+ const DEFAULT_BUF_SIZE : usize = if cfg ! ( target_os = "espidf" ) {
223
+ 512
224
+ } else {
225
+ 8 * 1024
226
+ } ;
227
+
228
+ let mut buffer = [ 0u8 ; DEFAULT_BUF_SIZE ] ;
229
+ let mut len = 0 ;
230
+
231
+ loop {
232
+ let received = match input. read ( & mut buffer) {
233
+ Ok ( bytes_count) => bytes_count,
234
+ Err ( e) if e. kind ( ) == ErrorKind :: Interrupted => continue ,
235
+ Err ( e) => return Err ( e) ,
236
+ } ;
237
+
238
+ if received == 0 {
239
+ return Ok ( len) ;
240
+ }
241
+
242
+ output. write_all ( & buffer[ 0 ..received] ) ?;
243
+
244
+ // We need to flush the buffer here to comply with POSIX requirement that
245
+ // `tee` does not buffer the input.
246
+ output. flush ( ) ?;
247
+ len += received;
248
+ }
249
+ }
250
+
210
251
/// Tries to open the indicated file and return it. Reports an error if that's not possible.
211
252
/// If that error should lead to program termination, this function returns Some(Err()),
212
253
/// otherwise it returns None.
0 commit comments