diff options
author | Lars Wirzenius <liw@sequoia-pgp.org> | 2022-03-13 10:14:14 +0200 |
---|---|---|
committer | Lars Wirzenius <liw@sequoia-pgp.org> | 2022-03-13 10:14:14 +0200 |
commit | f633203f255f9fabc726ab4939984e083cb95c0f (patch) | |
tree | 644b586d0f72f8322faa7d343e9b9da0b98de706 | |
parent | a794dd3f525fa27f618e64b97b5c0122dc14d0a0 (diff) | |
download | checksums-f633203f255f9fabc726ab4939984e083cb95c0f.tar.gz |
single-threaded
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/main.rs | 72 |
2 files changed, 74 insertions, 1 deletions
@@ -6,3 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1.0.56" +clap = { version = "3.1.6", features = ["derive"] } +sha2 = "0.10.2" diff --git a/src/main.rs b/src/main.rs index e7a11a9..408b697 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,73 @@ +use clap::Parser; +use sha2::{Digest, Sha256}; +use std::fs::File; +use std::io::{BufReader, Read}; +use std::path::{Path, PathBuf}; + +const BUF_SIZE: usize = 4096; + fn main() { - println!("Hello, world!"); + let args = Args::parse(); + if let Err(e) = checksums_main(&args.filenames) { + eprintln!("ERROR: {e}"); + std::process::exit(1); + } +} + +fn checksums_main(filenames: &[PathBuf]) -> anyhow::Result<()> { + let x: Result<Vec<()>, std::io::Error> = filenames + .iter() + .map(|filename| checksum(filename)) + .map(|x| print_checksum_result(x)) + .collect(); + let _ = x?; + Ok(()) +} + +fn checksum(filename: &Path) -> Result<FileChecksum, std::io::Error> { + let mut checksum = Sha256::new(); + + let file = File::open(filename)?; + let mut reader = BufReader::new(file); + loop { + let mut buf = vec![0; BUF_SIZE]; + let n = reader.read(&mut buf)?; + if n == 0 { + break; + } + checksum.update(&buf[..n]); + } + + let checksum = checksum.finalize(); + let checksum = format!("{checksum:x}"); + Ok(FileChecksum::new(filename, checksum)) +} + +#[derive(Parser)] +struct Args { + filenames: Vec<PathBuf>, +} + +#[derive(Debug)] +struct FileChecksum { + filename: PathBuf, + checksum: String, +} + +impl FileChecksum { + fn new(filename: &Path, checksum: String) -> Self { + Self { + filename: filename.to_path_buf(), + checksum, + } + } +} + +fn print_checksum_result(x: Result<FileChecksum, std::io::Error>) -> Result<(), std::io::Error> { + if let Ok(x) = x { + println!("{} {}", x.checksum, x.filename.display()); + Ok(()) + } else { + Err(x.unwrap_err()) + } } |