use { digest::{Digest, FixedOutput, HashMarker}, md5::Md5, sha1::Sha1, sha2::{Sha224, Sha256, Sha384, Sha512}, std::{ error::Error, fmt::Write, fs::File, io::{self, BufRead, BufReader, Read}, }, }; pub enum HashType { Md5, Sha1, Sha224, Sha256, Sha384, Sha512, } pub fn compute_hash(file: &str, mut hasher: T) -> Result> where T: Default + FixedOutput + HashMarker, { let mut buf = vec![]; if file == "-" { let _s = io::stdin().read_to_end(&mut buf)?; } else { let mut fd = File::open(file)?; let _s = fd.read_to_end(&mut buf)?; } let mut s = String::new(); hasher.update(&buf); let res = hasher.finalize(); for c in res { write!(s, "{c:02x}")?; } Ok(s) } pub fn check_sums(file: &str, hashtype: HashType, erred: &mut usize) -> Result<(), Box> { let fd = File::open(file)?; let reader = BufReader::new(fd); for line in reader.lines() { let line = line?; let mut split = line.split_whitespace(); let sum = split.next().ok_or::(io::Error::new( io::ErrorKind::Other, "invalid checksum file", ))?; let file = split.next().ok_or::(io::Error::new( io::ErrorKind::Other, "invalid checksum file", ))?; let s = match hashtype { HashType::Md5 => compute_hash(file, Md5::new())?, HashType::Sha1 => compute_hash(file, Sha1::new())?, HashType::Sha224 => compute_hash(file, Sha224::new())?, HashType::Sha256 => compute_hash(file, Sha256::new())?, HashType::Sha384 => compute_hash(file, Sha384::new())?, HashType::Sha512 => compute_hash(file, Sha512::new())?, }; if s.as_str() == sum { println!("{file}: OK"); } else { println!("{file}: FAILED"); *erred += 1; } } Ok(()) }