@@ -193,7 +193,16 @@ fn print_n_bytes(input: impl Read, n: u64) -> io::Result<u64> {
193193 Ok ( bytes_written)
194194}
195195
196- fn print_n_lines ( input : & mut impl io:: BufRead , n : u64 , separator : u8 ) -> io:: Result < u64 > {
196+ enum HeadFileError {
197+ Read ( io:: Error ) ,
198+ WriteStdout ( io:: Error ) ,
199+ }
200+
201+ fn print_n_lines (
202+ input : & mut impl io:: BufRead ,
203+ n : u64 ,
204+ separator : u8 ,
205+ ) -> Result < u64 , HeadFileError > {
197206 // Read the first `n` lines from the `input` reader.
198207 let mut reader = take_lines ( input, n, separator) ;
199208
@@ -205,21 +214,27 @@ fn print_n_lines(input: &mut impl io::BufRead, n: u64, separator: u8) -> io::Res
205214 let mut bytes_written = 0 ;
206215 let mut buf = [ 0 ; BUF_SIZE ] ;
207216 loop {
208- let n = match reader. read ( & mut buf) {
209- Ok ( 0 ) => break ,
210- Ok ( n ) => n ,
211- Err ( e ) => return Err ( e ) ,
212- } ;
217+ let bytes_read = reader. read ( & mut buf) . map_err ( HeadFileError :: Read ) ? ;
218+
219+ if bytes_read == 0 {
220+ break ;
221+ }
213222
214- writer. write_all ( & buf[ ..n] ) . map_err ( wrap_in_stdout_error) ?;
223+ writer
224+ . write_all ( & buf[ ..bytes_read] )
225+ . map_err ( wrap_in_stdout_error)
226+ . map_err ( HeadFileError :: WriteStdout ) ?;
215227
216- bytes_written += n as u64 ;
228+ bytes_written += bytes_read as u64 ;
217229 }
218230
219231 // Make sure we finish writing everything to the target before
220232 // exiting. Otherwise, when Rust is implicitly flushing, any
221233 // error will be silently ignored.
222- writer. flush ( ) . map_err ( wrap_in_stdout_error) ?;
234+ writer
235+ . flush ( )
236+ . map_err ( wrap_in_stdout_error)
237+ . map_err ( HeadFileError :: WriteStdout ) ?;
223238
224239 Ok ( bytes_written)
225240}
@@ -400,15 +415,17 @@ fn head_backwards_on_seekable_file(input: &mut File, options: &HeadOptions) -> i
400415 }
401416}
402417
403- fn head_file ( input : & mut File , options : & HeadOptions ) -> io :: Result < u64 > {
418+ fn head_file ( input : & mut File , options : & HeadOptions ) -> Result < u64 , HeadFileError > {
404419 match options. mode {
405- Mode :: FirstBytes ( n) => print_n_bytes ( input, n) ,
420+ Mode :: FirstBytes ( n) => print_n_bytes ( input, n) . map_err ( HeadFileError :: WriteStdout ) ,
406421 Mode :: FirstLines ( n) => print_n_lines (
407422 & mut io:: BufReader :: with_capacity ( BUF_SIZE , input) ,
408423 n,
409424 options. line_ending . into ( ) ,
410425 ) ,
411- Mode :: AllButLastBytes ( _) | Mode :: AllButLastLines ( _) => head_backwards_file ( input, options) ,
426+ Mode :: AllButLastBytes ( _) | Mode :: AllButLastLines ( _) => {
427+ head_backwards_file ( input, options) . map_err ( HeadFileError :: WriteStdout )
428+ }
412429 }
413430}
414431
@@ -436,10 +453,30 @@ fn uu_head(options: &HeadOptions) -> UResult<()> {
436453 // last byte read so that any tools that parse the remainder of
437454 // the stdin stream read from the correct place.
438455
439- let bytes_read = head_file ( & mut stdin_file, options) ?;
456+ let bytes_read = match head_file ( & mut stdin_file, options) {
457+ Ok ( bytes_read) => bytes_read,
458+ Err ( HeadFileError :: Read ( err) ) => {
459+ return Err ( HeadError :: Io {
460+ name : "standard input" . into ( ) ,
461+ err,
462+ }
463+ . into ( ) ) ;
464+ }
465+ Err ( HeadFileError :: WriteStdout ( err) ) => return Err ( err. into ( ) ) ,
466+ } ;
440467 stdin_file. seek ( SeekFrom :: Start ( current_pos + bytes_read) ) ?;
441468 } else {
442- let _bytes_read = head_file ( & mut stdin_file, options) ?;
469+ match head_file ( & mut stdin_file, options) {
470+ Ok ( _) => { }
471+ Err ( HeadFileError :: Read ( err) ) => {
472+ return Err ( HeadError :: Io {
473+ name : "standard input" . into ( ) ,
474+ err,
475+ }
476+ . into ( ) ) ;
477+ }
478+ Err ( HeadFileError :: WriteStdout ( err) ) => return Err ( err. into ( ) ) ,
479+ }
443480 }
444481 }
445482
@@ -507,13 +544,14 @@ fn uu_head(options: &HeadOptions) -> UResult<()> {
507544 } ;
508545 match head_file ( & mut file_handle, options) {
509546 Ok ( _) => { }
510- Err ( err) => {
547+ Err ( HeadFileError :: Read ( err) ) => {
511548 show ! ( HeadError :: Io {
512549 name: file. into( ) ,
513550 err
514551 } ) ;
515552 continue ;
516553 }
554+ Err ( HeadFileError :: WriteStdout ( err) ) => return Err ( err. into ( ) ) ,
517555 }
518556 Ok ( ( ) )
519557 } ;
0 commit comments