diff options
Diffstat (limited to 'src')
| -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);          }      }  }  | 
