77
88use clap:: { crate_version, Arg , ArgAction , ArgMatches , Command } ;
99use std:: ffi:: OsString ;
10- use std:: io:: { self , ErrorKind , Read , Seek , SeekFrom , Write } ;
10+ use std:: io:: { self , Read , Seek , SeekFrom , Write } ;
1111use std:: num:: TryFromIntError ;
1212use thiserror:: Error ;
1313use uucore:: display:: Quotable ;
@@ -239,10 +239,7 @@ impl HeadOptions {
239239 }
240240}
241241
242- fn read_n_bytes < R > ( input : R , n : u64 ) -> std:: io:: Result < ( ) >
243- where
244- R : Read ,
245- {
242+ fn read_n_bytes ( input : impl Read , n : u64 ) -> std:: io:: Result < ( ) > {
246243 // Read the first `n` bytes from the `input` reader.
247244 let mut reader = input. take ( n) ;
248245
@@ -287,48 +284,18 @@ fn catch_too_large_numbers_in_backwards_bytes_or_lines(n: u64) -> Option<usize>
287284 }
288285}
289286
290- /// Print to stdout all but the last `n` bytes from the given reader.
291- fn read_but_last_n_bytes ( input : & mut impl std:: io:: BufRead , n : u64 ) -> std:: io:: Result < ( ) > {
292- if n == 0 {
293- //prints everything
294- return read_n_bytes ( input, u64:: MAX ) ;
295- }
296-
287+ fn read_but_last_n_bytes ( input : impl std:: io:: BufRead , n : u64 ) -> std:: io:: Result < ( ) > {
297288 if let Some ( n) = catch_too_large_numbers_in_backwards_bytes_or_lines ( n) {
298289 let stdout = std:: io:: stdout ( ) ;
299290 let mut stdout = stdout. lock ( ) ;
300-
301- let mut ring_buffer = Vec :: new ( ) ;
302-
303- let mut buffer = [ 0u8 ; BUF_SIZE ] ;
304- let mut total_read = 0 ;
305-
306- loop {
307- let read = match input. read ( & mut buffer) {
308- Ok ( 0 ) => break ,
309- Ok ( read) => read,
310- Err ( e) => match e. kind ( ) {
311- ErrorKind :: Interrupted => continue ,
312- _ => return Err ( e) ,
313- } ,
314- } ;
315-
316- total_read += read;
317-
318- if total_read <= n {
319- // Fill the ring buffer without exceeding n bytes
320- let overflow = n - total_read;
321- ring_buffer. extend_from_slice ( & buffer[ ..read - overflow] ) ;
322- } else {
323- // Write the ring buffer and the part of the buffer that exceeds n
324- stdout. write_all ( & ring_buffer) ?;
325- stdout. write_all ( & buffer[ ..read - n + ring_buffer. len ( ) ] ) ?;
326- ring_buffer. clear ( ) ;
327- ring_buffer. extend_from_slice ( & buffer[ read - n + ring_buffer. len ( ) ..read] ) ;
328- }
291+ for bytes in take_all_but ( input. bytes ( ) , n) {
292+ stdout. write_all ( & [ bytes?] ) ?;
329293 }
294+ // Make sure we finish writing everything to the target before
295+ // exiting. Otherwise, when Rust is implicitly flushing, any
296+ // error will be silently ignored.
297+ stdout. flush ( ) ?;
330298 }
331-
332299 Ok ( ( ) )
333300}
334301
@@ -343,6 +310,10 @@ fn read_but_last_n_lines(
343310 for bytes in take_all_but ( lines ( input, separator) , n) {
344311 stdout. write_all ( & bytes?) ?;
345312 }
313+ // Make sure we finish writing everything to the target before
314+ // exiting. Otherwise, when Rust is implicitly flushing, any
315+ // error will be silently ignored.
316+ stdout. flush ( ) ?;
346317 }
347318 Ok ( ( ) )
348319}
@@ -440,8 +411,7 @@ fn head_backwards_without_seek_file(
440411 input : & mut std:: fs:: File ,
441412 options : & HeadOptions ,
442413) -> std:: io:: Result < ( ) > {
443- let reader = & mut std:: io:: BufReader :: with_capacity ( BUF_SIZE , & * input) ;
444-
414+ let reader = std:: io:: BufReader :: with_capacity ( BUF_SIZE , & * input) ;
445415 match options. mode {
446416 Mode :: AllButLastBytes ( n) => read_but_last_n_bytes ( reader, n) ?,
447417 Mode :: AllButLastLines ( n) => read_but_last_n_lines ( reader, n, options. line_ending . into ( ) ) ?,
0 commit comments