X-Git-Url: https://code.octet-stream.net/hashgood/blobdiff_plain/1dec1ec82f55d639d9fad0d0933545aa509c4272..69d73a1e6ca6798d880d79d0e5687c7a86019dd8:/src/main.rs diff --git a/src/main.rs b/src/main.rs index 2f1e7f3..cc9c570 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use std::error::Error; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process; use structopt::StructOpt; @@ -12,13 +12,14 @@ mod display; /// Collect candidate hashes based on options and match them against a calculated hash mod verify; +/// Problem running the program +const EXIT_ERR: i32 = 1; +/// Verification was performed and was not a match +const EXIT_MISMATCH: i32 = 2; + #[derive(StructOpt)] #[structopt(name = "hashgood")] pub struct Opt { - /// Read the hash from the clipboard - #[structopt(short = "p", long = "paste")] - paste: bool, - /// Disable ANSI colours in output #[structopt(short = "C", long = "no-colour")] no_colour: bool, @@ -42,6 +43,7 @@ pub enum Algorithm { Md5, Sha1, Sha256, + Sha512, } impl Algorithm { @@ -51,17 +53,18 @@ impl Algorithm { 16 => Ok(Algorithm::Md5), 20 => Ok(Algorithm::Sha1), 32 => Ok(Algorithm::Sha256), + 64 => Ok(Algorithm::Sha512), _ => Err(format!("Unrecognised hash length: {} bytes", len)), } } } /// The method by which one or more hashes were supplied to verify the calculated digest +#[derive(Debug, PartialEq)] pub enum VerificationSource { CommandArgument, - Clipboard, - RawFile(PathBuf), - DigestsFile(PathBuf), + RawFile(String), + DigestsFile(String), } /// A complete standalone hash result @@ -72,7 +75,7 @@ pub struct Hash { } impl Hash { - pub fn new(alg: Algorithm, bytes: Vec, path: &PathBuf) -> Self { + pub fn new(alg: Algorithm, bytes: Vec, path: &Path) -> Self { // Taking the filename component should always work? // If not, just fall back to the full path let filename = match path.file_name() { @@ -88,6 +91,7 @@ impl Hash { } /// A possible hash to match against. The algorithm is assumed. +#[derive(Debug, PartialEq)] pub struct CandidateHash { bytes: Vec, filename: Option, @@ -95,6 +99,7 @@ pub struct CandidateHash { /// A list of candidate hashes that our input could potentially match. At this point it is /// assumed that we will be verifying a digest of a particular, single algorithm. +#[derive(Debug, PartialEq)] pub struct CandidateHashes { alg: Algorithm, hashes: Vec, @@ -102,6 +107,7 @@ pub struct CandidateHashes { } /// Summary of an atetmpt to match the calculated digest against candidates +#[derive(PartialEq)] pub enum MatchLevel { Ok, Maybe, @@ -130,7 +136,7 @@ pub struct Verification<'a> { fn main() { hashgood().unwrap_or_else(|e| { eprintln!("Error: {}", e); - process::exit(1); + process::exit(EXIT_ERR); }); } @@ -138,7 +144,7 @@ fn main() { fn hashgood() -> Result<(), Box> { let opt = get_verified_options()?; let candidates = verify::get_candidate_hashes(&opt)?; - let input = calculate::get_input_reader(&opt.input)?; + let input = calculate::get_input_reader(opt.input.as_path())?; if let Some(c) = candidates { // If we have a candidate hash of a particular type, use that specific algorithm let hashes = calculate::create_digests(&[c.alg], input)?; @@ -147,6 +153,7 @@ fn hashgood() -> Result<(), Box> { if c.alg == alg { let hash = Hash::new(alg, bytes, &opt.input); let verification = verify::verify_hash(&hash, &c); + let successful_match = verification.match_level == MatchLevel::Ok; display::print_hash( &hash, verification.comparison_hash, @@ -155,12 +162,20 @@ fn hashgood() -> Result<(), Box> { )?; display::print_messages(verification.messages, opt.no_colour)?; display::print_match_level(verification.match_level, opt.no_colour)?; + if !successful_match { + process::exit(EXIT_MISMATCH); + } } } } else { // If no candidate, calculate all three common digest types for output let hashes = calculate::create_digests( - &[Algorithm::Md5, Algorithm::Sha1, Algorithm::Sha256], + &[ + Algorithm::Md5, + Algorithm::Sha1, + Algorithm::Sha256, + Algorithm::Sha512, + ], input, )?; for (alg, bytes) in hashes { @@ -178,15 +193,11 @@ fn hashgood() -> Result<(), Box> { /// Parse the command line options and check for ambiguous or inconsistent settings fn get_verified_options() -> Result { let opt = Opt::from_args(); - let hash_methods = - opt.hash.is_some() as i32 + opt.paste as i32 + opt.hash_file.is_some() as i32; + let hash_methods = opt.hash.is_some() as i32 + opt.hash_file.is_some() as i32; if hash_methods > 1 { if opt.hash.is_some() { eprintln!("* specified as command line argument"); } - if opt.paste { - eprintln!("* paste from clipboard (-p)") - } if opt.hash_file.is_some() { eprintln!("* check hash from file (-c)") }