aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/bhash.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/bhash.rs')
-rw-r--r--src/bin/bhash.rs95
1 files changed, 74 insertions, 21 deletions
diff --git a/src/bin/bhash.rs b/src/bin/bhash.rs
index b5d2937..819d9d0 100644
--- a/src/bin/bhash.rs
+++ b/src/bin/bhash.rs
@@ -12,18 +12,68 @@ extern crate tree_magic;
extern crate flate2;
extern crate tar;
extern crate crypto;
+extern crate zip;
use clap::App;
use bad_hashish::Result;
use std::path::Path;
-use std::io::BufReader;
+use std::io::{Read, BufReader};
use std::io::prelude::*;
use std::fs::File;
use flate2::read::GzDecoder;
use tar::Archive;
use crypto::digest::Digest;
use crypto::sha1::Sha1;
+use crypto::sha2::Sha256;
+use crypto::blake2b::Blake2b;
+use zip::read::ZipArchive;
+fn hash_stream<T: Read>(mut stream: T, name: &str, total_size: u64) -> Result<()> {
+
+ let mut hash_sha1 = Sha1::new();
+ let mut hash_sha256 = Sha256::new();
+ let mut hash_blake2b = Blake2b::new(32);
+ let mut buf: [u8; 1*1024*1024] = [0; 1*1024*1024];
+ loop {
+ let got = stream.read(&mut buf[..])?;
+ if got <= 0 { break };
+ hash_sha1.input(&buf[0..got]);
+ //hash_sha256.input(&buf[0..got]);
+ //hash_blake2b.input(&buf[0..got]);
+ }
+ /*
+ println!("{} {} {} {} {}",
+ hash_sha1.result_str(),
+ hash_sha256.result_str(),
+ hash_blake2b.result_str(),
+ total_size,
+ name);
+ */
+ println!("{} {}",
+ hash_sha1.result_str(),
+ name);
+ Ok(())
+}
+
+fn do_tar<T: Read>(stream: T) -> Result<()> {
+ //println!("It's a tar inside");
+ let mut a = Archive::new(stream);
+ for inner in a.entries().unwrap() {
+ let mut inner = inner.unwrap();
+ let (inner_name, inner_size) = {
+ let header = inner.header();
+ // Only do actual files ("regular", not directories, fifo, etc)
+ if header.entry_type() != tar::EntryType::Regular {
+ continue;
+ }
+ let inner_name = header.path()?.to_string_lossy().to_string();
+ let inner_size = header.entry_size()?;
+ (inner_name, inner_size)
+ };
+ hash_stream(&mut inner, &inner_name, inner_size)?;
+ }
+ Ok(())
+}
fn run() -> Result<()> {
@@ -38,7 +88,22 @@ fn run() -> Result<()> {
println!("{} ({})", f, tree_magic::from_filepath(path));
if tree_magic::match_filepath("application/zip", path) {
- //println!("It's a zip.");
+ let f = File::open(path)?;
+ let mut zip = ZipArchive::new(f)?;
+
+ for i in 0..zip.len() {
+ let mut inner = zip.by_index(i).unwrap();
+ if (0o40000u32 & inner.unix_mode().unwrap()) != 0 {
+ // This is a directory
+ continue
+ }
+ let (name, size) = (inner.name().to_string(), inner.size());
+ hash_stream(&mut inner, &name, size)?;
+ }
+
+ } else if tree_magic::match_filepath("application/x-tar", path) {
+ let f = File::open(path)?;
+ do_tar(f)?;
} else if tree_magic::match_filepath("application/gzip", path) {
//println!("It's gzip.");
let f = File::open(path)?;
@@ -52,26 +117,14 @@ fn run() -> Result<()> {
};
if is_tar {
- //println!("It's a tar inside");
- let mut a = Archive::new(reader);
- for inner in a.entries().unwrap() {
- let mut inner = inner.unwrap();
- // Only do actual files ("regular", not directories, fifo, etc)
- if inner.header().entry_type() != tar::EntryType::Regular {
- continue;
- }
- let mut hasher = Sha1::new();
- let mut buf: [u8; 1*1024*1024] = [0; 1*1024*1024];
- loop {
- let got = inner.read(&mut buf[..])?;
- if got <= 0 { break };
- hasher.input(&buf[0..got]);
- }
- println!("{} {}",
- hasher.result_str(),
- inner.header().path()?.to_str().unwrap());
- }
+ do_tar(reader)?;
}
+ } else if path.is_dir() {
+ continue
+ } else {
+ let mut f = File::open(path)?;
+ let (name, size) = (&path.to_string_lossy().to_string(), f.metadata()?.len());
+ hash_stream(&mut f, name, size)?;
}
}