shitbox/hashbox/hash/mod.rs

74 lines
2.0 KiB
Rust

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<T>(file: &str, mut hasher: T) -> Result<String, Box<dyn Error>>
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<dyn Error>> {
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>(io::Error::new(
io::ErrorKind::Other,
"invalid checksum file",
))?;
let file = split.next().ok_or::<io::Error>(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(())
}