diff --git a/.gitignore b/.gitignore index fb1121f..37b0f7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea/ # ---> Rust # Generated by Cargo # will have compiled files and executables diff --git a/Cargo.lock b/Cargo.lock index bd9c93e..2a67268 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,7 +48,7 @@ dependencies = [ [[package]] name = "digest-tool" -version = "0.1.3" +version = "0.1.4" dependencies = [ "argparse", "hex", diff --git a/Cargo.toml b/Cargo.toml index 0f991ae..d402afe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "digest-tool" -version = "0.1.3" +version = "0.1.4" authors = ["Hatter Jiang "] edition = "2018" description = "Digest cli tool" diff --git a/src/main.rs b/src/main.rs index 8f855f3..983e03a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,31 +1,33 @@ #[macro_use] extern crate rust_util; -mod opt; - -use rust_util::{ - XResult, - new_box_ioerror, -}; use std::{ fs::File, - io::{ self, Read, ErrorKind }, + io::{self, ErrorKind, Read}, }; + use crypto::{ - digest::Digest, - ripemd160::Ripemd160, - whirlpool::Whirlpool, - blake2s::Blake2s, blake2b::Blake2b, + blake2s::Blake2s, + digest::Digest, md5::Md5, + ripemd160::Ripemd160, sha1::Sha1, - sha2::{ Sha224, Sha256, Sha384, Sha512, Sha512Trunc224, Sha512Trunc256, }, + sha2::{Sha224, Sha256, Sha384, Sha512, Sha512Trunc224, Sha512Trunc256}, sha3::Sha3, + whirlpool::Whirlpool, }; -use indicatif::{ ProgressBar, ProgressStyle }; +use indicatif::{ProgressBar, ProgressStyle}; use libsm::sm3::hash::Sm3Hash; +use rust_util::{ + new_box_ioerror, + XResult, +}; + use opt::Options; +mod opt; + const FILE_SIZE_1GB: u64 = 1024 * 1024 * 1024; const BUFF_SIZE: usize = 512 * 1024; const PB_PROGRESS: &str = "#-"; @@ -64,16 +66,24 @@ fn main() -> XResult<()> { }; } else { for file in &options.file_name_list { - match get_digest_by_algorithm(the_algo, &options) { - Some(mut digest) => println!("{} - {} ({})", calc_file_digest(&mut *digest, file)?, file, the_algo), - None => match the_algo { - "SM3" => println!("{} - {} ({})", hex::encode(Sm3Hash::new(&read_file_full(file)?).get_hash()), file, the_algo), - _ => { - failure!("Unknown algorithm: {}", options.algorithm); - return Ok(()); + if options.verbose { + information!("Processing file: {}", file); + } + let r = || -> XResult<()> { + match get_digest_by_algorithm(the_algo, &options) { + Some(mut digest) => println!("{} - {} ({})", calc_file_digest(&mut *digest, file)?, file, the_algo), + None => match the_algo { + "SM3" => println!("{} - {} ({})", hex::encode(Sm3Hash::new(&read_file_full(file)?).get_hash()), file, the_algo), + _ => failure!("Unknown algorithm: {}", options.algorithm), }, - }, + } + Ok(()) }; + if let Err(e) = r() { + if !options.ignore_errors || options.verbose { + failure!("{} - {}", file, e); + } + } } } @@ -91,7 +101,7 @@ Supported algorithms: MD5, SHA1, SHA224, SHA256, SHA512, SHA512-224, SHA512-256, SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE-128, SHAKE-256, KECCAK-224, KECCAK-256, KECCAK-384, KECCAK-512, -SM3, RIPEMD160, WHIRLPOOL, BLAKE2S, BLAKE2B"#, VERSION, &GIT_HASH[0..7]); +SM3, RIPEMD160, WHIRLPOOL, BLAKE2S, BLAKE2B"#, VERSION, iff!(GIT_HASH.is_empty(), "n/a", &GIT_HASH[0..7])); if options.verbose { debugging!("Full git hash: {}", &GIT_HASH); } @@ -142,7 +152,10 @@ fn read_file_full(file_name: &str) -> XResult> { let mut read = 0_u64; loop { let len = match f.read(&mut buf) { - Ok(0) => { pb.finish_and_clear(); return Ok(ret); }, + Ok(0) => { + pb.finish_and_clear(); + return Ok(ret); + } Ok(len) => len, Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(Box::new(e)), @@ -161,13 +174,16 @@ fn calc_file_digest(digest: &mut dyn Digest, file_name: &str) -> XResult let pb = ProgressBar::new(file_len); pb.set_style(ProgressStyle::default_bar().template(PB_TEMPLATE).progress_chars(PB_PROGRESS)); - + loop { let len = match f.read(&mut buf) { - Ok(0) => { pb.finish_and_clear(); return Ok(digest.result_str()); }, + Ok(0) => { + pb.finish_and_clear(); + return Ok(digest.result_str()); + } Ok(len) => len, Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, - Err(e) => return Ok(format!("ERROR: {}", e)), + Err(e) => return Err(Box::new(e)), }; digest.input(&buf[..len]); processed += len as u64; diff --git a/src/opt.rs b/src/opt.rs index 6eca5bd..3b4985b 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -4,6 +4,7 @@ use argparse::{ArgumentParser, StoreTrue, Store, List}; pub struct Options { pub version: bool, pub verbose: bool, + pub ignore_errors: bool, pub algorithm: String, pub file_name_list: Vec, pub blake_len: usize, @@ -14,6 +15,7 @@ impl Options { Options { version: false, verbose: false, + ignore_errors: false, algorithm: "SHA256".to_string(), file_name_list: Vec::new(), blake_len: 0_usize, @@ -28,6 +30,7 @@ impl Options { ap.refer(&mut self.blake_len).add_option(&["-l", "--blake-len"], Store, "Blake2s/b length, 1~32/64"); ap.refer(&mut self.version).add_option(&["-V", "--version"], StoreTrue, "Print version"); ap.refer(&mut self.verbose).add_option(&["-v", "--verbose"], StoreTrue, "Verbose"); + ap.refer(&mut self.ignore_errors).add_option(&["--ignore-errors"], StoreTrue, "Ignore errors"); ap.refer(&mut self.file_name_list).add_argument("File names", List, "File names to be digested"); ap.parse_args_or_exit(); }