83 lines
2.2 KiB
Rust
83 lines
2.2 KiB
Rust
|
use sha2::{Sha256, Digest};
|
||
|
use std::ops::Deref;
|
||
|
use std::path::PathBuf;
|
||
|
use std::thread;
|
||
|
use std::thread::available_parallelism;
|
||
|
use std::fs::File;
|
||
|
use std::io;
|
||
|
use clap::Parser;
|
||
|
use std::sync::Arc;
|
||
|
use std::sync::Mutex;
|
||
|
use std::collections::VecDeque;
|
||
|
use std::fs;
|
||
|
|
||
|
#[derive(Parser)]
|
||
|
#[command(name = "psha")]
|
||
|
#[command(version = option_env!("CARGO_PKG_VERSION"))]
|
||
|
#[command(long_about = None)]
|
||
|
struct Args {
|
||
|
#[arg(
|
||
|
trailing_var_arg = true,
|
||
|
)]
|
||
|
files: Vec<PathBuf>,
|
||
|
}
|
||
|
|
||
|
fn checksum(thread_id: usize, filenames: Arc<Mutex<VecDeque<PathBuf>>>) -> Result<(), String> {
|
||
|
let running = true;
|
||
|
while running {
|
||
|
let filename = match filenames.lock().unwrap().pop_front() {
|
||
|
Some(f) => f,
|
||
|
None => return Ok(())
|
||
|
};
|
||
|
let mut hasher = Sha256::new();
|
||
|
let mut file = File::open(&filename).unwrap();
|
||
|
|
||
|
io::copy(&mut file, &mut hasher);
|
||
|
let hash = hasher.finalize();
|
||
|
// println!("thread {} result: {:x}\t{}", thread_id, hash, filename.as_path().display());
|
||
|
println!("{:x}\t{}", hash, filename.as_path().display());
|
||
|
}
|
||
|
|
||
|
println!("thread {} has ran out of work", thread_id);
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
fn main() {
|
||
|
let args = Args::parse();
|
||
|
let cpus = available_parallelism().unwrap().get();
|
||
|
let mut buffer = VecDeque::new();
|
||
|
let mut handles = vec![];
|
||
|
for file in args.files {
|
||
|
// match fs::canonicalize(file.as_path()) {
|
||
|
// Ok(p) => buffer.push_back(p),
|
||
|
// Err(e) => panic!("unable to canonicalize {}: {}", file.as_path().display(), e)
|
||
|
// };
|
||
|
buffer.push_back(file);
|
||
|
}
|
||
|
let arc_buf = Arc::new(Mutex::new(buffer));
|
||
|
// let mut handles = vec![];
|
||
|
// let chunks = Arc::new(Mutex::new(args.files.chunks(args.files.len()/ cpus).clone()));
|
||
|
/* let threads = chunks.into_iter().map(|chunk| {
|
||
|
thread::spawn(move || checksum(0, chunk.to_vec()))
|
||
|
}).collect::<Vec<_>>(); */
|
||
|
|
||
|
/* threads.into_iter().for_each(|i| { i.join().unwrap(); });
|
||
|
// for file in args.files {
|
||
|
// if let Err(e) = checksum(0, file) { */
|
||
|
// println!("{}", e);
|
||
|
// break;
|
||
|
// };
|
||
|
// }
|
||
|
for i in 0..cpus {
|
||
|
let safe = Arc::clone(&arc_buf);
|
||
|
handles.push(thread::spawn(move || checksum(i, safe)))
|
||
|
}
|
||
|
|
||
|
for handle in handles {
|
||
|
handle.join().unwrap();
|
||
|
}
|
||
|
|
||
|
// println!("{}", available_parallelism().unwrap().get());
|
||
|
}
|