diff options
author | Alexis Bourget <alexis.bourget@gmail.com> | 2020-10-25 16:13:37 +0100 |
---|---|---|
committer | Alexis Bourget <alexis.bourget@gmail.com> | 2020-10-25 16:13:37 +0100 |
commit | 8f27699ffa8475b8f8988d7da5d682967e342f4b (patch) | |
tree | f7ec5d5f97d85700b4687c64df053f34ce3d1d1d | |
parent | 887fe53ab33097ee92131c560e85a54e2ed63307 (diff) |
Handle another type of invalid filenames: broken pipes
Fixes #23.
With this `hx` is now able to handle broken pipes as in the command
`dd if=/dev/random bs=512 count=10 | RUST_BACKTRACE=1 ./target/debug/hx | head -n 10`
and will exit with the correct error: `error = "Broken pipe (os error 32)"`
without crashing with a backtrace.
-rw-r--r-- | src/lib.rs | 91 |
1 files changed, 55 insertions, 36 deletions
@@ -21,7 +21,7 @@ use std::error::Error; use std::f64; use std::fs; use std::io::BufReader; -use std::io::{self, BufRead, Read}; +use std::io::{self, BufRead, Read, Write}; /// arg cols pub const ARG_COL: &str = "cols"; @@ -134,8 +134,8 @@ pub fn offset(b: u64) -> String { } /// print offset to std out -pub fn print_offset(b: u64) { - print!("{}: ", offset(b)); +pub fn print_offset(w: &mut impl Write, b: u64) -> io::Result<()> { + write!(w, "{}: ", offset(b)) } /// hex octal, takes u8 @@ -159,7 +159,7 @@ pub fn hex_binary(b: u8) -> String { } /// print byte to std out -pub fn print_byte(b: u8, format: Format, colorize: bool) { +pub fn print_byte(w: &mut impl Write, b: u8, format: Format, colorize: bool) -> io::Result<()> { let mut color: u8 = b; if color < 1 { color = 0x16; @@ -167,39 +167,43 @@ pub fn print_byte(b: u8, format: Format, colorize: bool) { if colorize { // note, for color testing: for (( i = 0; i < 256; i++ )); do echo "$(tput setaf $i)This is ($i) $(tput sgr0)"; done match format { - Format::Octal => print!( + Format::Octal => write!( + w, "{} ", ansi_term::Style::new() .fg(ansi_term::Color::Fixed(color)) .paint(hex_octal(b)) ), - Format::LowerHex => print!( + Format::LowerHex => write!( + w, "{} ", ansi_term::Style::new() .fg(ansi_term::Color::Fixed(color)) .paint(hex_lower_hex(b)) ), - Format::UpperHex => print!( + Format::UpperHex => write!( + w, "{} ", ansi_term::Style::new() .fg(ansi_term::Color::Fixed(color)) .paint(hex_upper_hex(b)) ), - Format::Binary => print!( + Format::Binary => write!( + w, "{} ", ansi_term::Style::new() .fg(ansi_term::Color::Fixed(color)) .paint(hex_binary(b)) ), - _ => print!("unk_fmt "), + _ => write!(w, "unk_fmt "), } } else { match format { - Format::Octal => print!("{} ", hex_octal(b)), - Format::LowerHex => print!("{} ", hex_lower_hex(b)), - Format::UpperHex => print!("{} ", hex_upper_hex(b)), - Format::Binary => print!("{} ", hex_binary(b)), - _ => print!("unk_fmt "), + Format::Octal => write!(w, "{} ", hex_octal(b)), + Format::LowerHex => write!(w, "{} ", hex_lower_hex(b)), + Format::UpperHex => write!(w, "{} ", hex_upper_hex(b)), + Format::Binary => write!(w, "{} ", hex_binary(b)), + _ => write!(w, "unk_fmt "), } } } @@ -274,7 +278,7 @@ pub fn run(matches: ArgMatches) -> Result<(), Box<dyn Error>> { // array output mode is mutually exclusive if let Some(array) = matches.value_of(ARG_ARR) { - output_array(array, buf, truncate_len, column_width); + output_array(array, buf, truncate_len, column_width)?; } else { // Transforms this Read instance to an Iterator over its bytes. // The returned type implements Iterator where the Item is @@ -287,13 +291,16 @@ pub fn run(matches: ArgMatches) -> Result<(), Box<dyn Error>> { let mut byte_column: u64 = 0x0; let page = buf_to_array(&mut buf, truncate_len, column_width)?; + let stdout = io::stdout(); + let mut locked = stdout.lock(); + for line in page.body.iter() { - print_offset(offset_counter); + print_offset(&mut locked, offset_counter)?; for hex in line.hex_body.iter() { offset_counter += 1; byte_column += 1; - print_byte(*hex, format_out, colorize); + print_byte(&mut locked, *hex, format_out, colorize)?; if *hex > 31 && *hex < 127 { ascii_line.ascii.push(*hex as char); @@ -303,17 +310,21 @@ pub fn run(matches: ArgMatches) -> Result<(), Box<dyn Error>> { } if byte_column < column_width { - print!("{:<1$}", "", 5 * (column_width - byte_column) as usize); + write!( + locked, + "{:<1$}", + "", + 5 * (column_width - byte_column) as usize + )?; } byte_column = 0x0; let ascii_string: String = ascii_line.ascii.iter().cloned().collect(); ascii_line = Line::new(); - print!("{}", ascii_string); // print ascii string - println!(); + write!(locked, "{}\n", ascii_string)?; // print ascii string } if true { - println!(" bytes: {}", page.bytes); + writeln!(locked, " bytes: {}", page.bytes)?; } } } @@ -367,33 +378,41 @@ pub fn output_array( mut buf: Box<dyn BufRead>, truncate_len: u64, column_width: u64, -) { +) -> io::Result<()> { + let stdout = io::stdout(); + let mut locked = stdout.lock(); + let page = buf_to_array(&mut buf, truncate_len, column_width).unwrap(); match array_format { - "r" => println!("let ARRAY: [u8; {}] = [", page.bytes), - "c" => println!("unsigned char ARRAY[{}] = {{", page.bytes), - "g" => println!("a := [{}]byte{{", page.bytes), - _ => println!("unknown array format"), + "r" => writeln!(locked, "let ARRAY: [u8; {}] = [", page.bytes)?, + "c" => writeln!(locked, "unsigned char ARRAY[{}] = {{", page.bytes)?, + "g" => writeln!(locked, "a := [{}]byte{{", page.bytes)?, + _ => writeln!(locked, "unknown array format")?, } let mut i: u64 = 0x0; for line in page.body.iter() { - print!(" "); + write!(locked, " ")?; for hex in line.hex_body.iter() { i += 1; if i == page.bytes && array_format != "g" { - print!("{}", hex_lower_hex(*hex)); + write!(locked, "{}", hex_lower_hex(*hex))?; } else { - print!("{}, ", hex_lower_hex(*hex)); + write!(locked, "{}, ", hex_lower_hex(*hex))?; } } - println!(); - } - match array_format { - "r" => println!("];"), - "c" => println!("}};"), - "g" => println!("}}"), - _ => println!("unknown array format"), + writeln!(locked, "")?; } + + writeln!( + locked, + "{}", + match array_format { + "r" => "];", + "c" => "};", + "g" => "}", + _ => "unknown array format", + } + ) } /// Function wave out. |