diff options
author | bnewbold <bnewbold@robocracy.org> | 2017-05-26 15:10:52 -0700 |
---|---|---|
committer | bnewbold <bnewbold@robocracy.org> | 2017-05-26 15:10:52 -0700 |
commit | 6ed6757702eea4f775ad06e293550b99a499a415 (patch) | |
tree | 02ff48b5069c8bf3665c670d8d4d55502fb3b31b | |
parent | a2ca6a70cc0511f02dfffb29e298bf188d445836 (diff) | |
download | bad-hashish-master.tar.gz bad-hashish-master.zip |
-rw-r--r-- | src/bin/bhash.rs | 95 | ||||
-rw-r--r-- | src/lib.rs | 3 |
2 files changed, 77 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)?; } } @@ -8,12 +8,15 @@ extern crate log; #[macro_use] extern crate error_chain; +extern crate zip; + mod errors { // Create the Error, ErrorKind, ResultExt, and Result types error_chain! { foreign_links { Io(::std::io::Error); + Zip(::zip::result::ZipError); } } } |