summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexis Bourget <alexis.bourget@gmail.com>2020-10-25 16:13:37 +0100
committerAlexis Bourget <alexis.bourget@gmail.com>2020-10-25 16:13:37 +0100
commit8f27699ffa8475b8f8988d7da5d682967e342f4b (patch)
treef7ec5d5f97d85700b4687c64df053f34ce3d1d1d
parent887fe53ab33097ee92131c560e85a54e2ed63307 (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.rs91
1 files changed, 55 insertions, 36 deletions
diff --git a/src/lib.rs b/src/lib.rs
index e978e56..8d7e594 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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.