diff --git a/Makefile b/Makefile index 84501e3..8508c8f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ build: cargo build --release --target x86_64-unknown-linux-gnu --package zsdiff_all --bin zspatch cargo build --release --target x86_64-unknown-linux-gnu --package zsdiff_all --bin zsdiff - #cargo build --release --target x86_64-apple-darwin --package zdiff_all --bin zpatch - #cargo build --release --target x86_64-pc-windows-gnu --package zdiff_all --bin zpatch \ No newline at end of file + cargo build --release --target x86_64-pc-windows-gnu --package zsdiff_all --bin zspatch + cargo build --release --target x86_64-pc-windows-gnu --package zsdiff_all --bin zsdiff diff --git a/src/utils.rs b/src/utils.rs index c565b53..12500e5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,4 @@ +use md5; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::{fs, io}; @@ -9,7 +10,7 @@ pub struct Zsdiff { } impl Zsdiff { - pub async fn from_vec(_data: Vec>) -> Result { + pub async fn from_vec(_data: Vec>) -> Result { let mut content = HashMap::new(); for part in _data { let filename_size = u32::from_be_bytes(part[0..4].try_into().unwrap()) as usize; @@ -56,7 +57,7 @@ pub struct Metadata { pub remove_files: Vec, } -pub async fn get_hash(data: &Vec) -> String { +pub async fn get_hash(data: Vec) -> String { let hash = md5::compute(&data[..]); format!("{:x}", hash) } diff --git a/src/zsdiff.rs b/src/zsdiff.rs index e257c59..805c477 100644 --- a/src/zsdiff.rs +++ b/src/zsdiff.rs @@ -2,6 +2,7 @@ mod utils; use clap::Parser; use std::collections::HashMap; +use std::io::Write; use std::{fs, io}; use utils::{Metadata, Zsdiff, get_hash}; use walkdir::WalkDir; @@ -21,7 +22,7 @@ async fn walk_dir(dir: String) -> HashMap { continue; } let content = fs::read(path).unwrap(); - let hash = get_hash(&content).await; + let hash = get_hash(content).await; let path_str = path.display().to_string(); let file_info = FileInfo { relative_path: path_str[dir.len() + 1..].to_string(), @@ -76,12 +77,10 @@ pub async fn zsdiff( let new_hashes = walk_dir(new).await; let compare_hashes = compare_hashes(old_hashes, new_hashes).await; let parts = compare_hashes.to_vec().await; - let file = fs::File::create(output_filename)?; - utils::compress_parts(parts, &file, level).await; - // let mut buf = Vec::new(); - // file.read(&mut buf)?; - // let output_hash = get_hash(&buf).await; - // println!("{}", output_hash); + utils::compress_parts(parts, &fs::File::create(output_filename)?, level).await; + let output_hash = get_hash(fs::read(output_filename)?).await; + fs::File::create(format!("{}.md5", output_filename))?.write_all(output_hash.as_bytes())?; + println!("Zsdiff hash: {}", output_hash); Ok(()) } @@ -100,6 +99,5 @@ struct Args { #[tokio::main] async fn main() -> io::Result<()> { let args = Args::parse(); - zsdiff(args.filename, args.old, args.new, args.compress_level).await?; - Ok(()) + zsdiff(args.filename, args.old, args.new, args.compress_level).await } diff --git a/src/zspatch.rs b/src/zspatch.rs index 6a08264..d12beac 100644 --- a/src/zspatch.rs +++ b/src/zspatch.rs @@ -26,7 +26,17 @@ async fn extract_files(zsdiff: &Zsdiff, filename: &String) -> Result Result<(), io::Error> { +async fn check_hash(filename: String) -> Result<(), io::Error> { + let file_data = read(format!("{}.zdiff", filename))?; + let hash_file = read(format!("{}.zdiff.md5", filename))?; + let hash = utils::get_hash(file_data).await; + if !String::from_utf8(hash_file).unwrap().eq(&hash) { + return Err(io::Error::new(io::ErrorKind::Other, "Hash mismatch")); + } + Ok(()) +} + +async fn zspatch(filename: String, dest_dir: String) -> Result<(), io::Error> { let filename = &format!("{}.zdiff", filename); let parts = utils::decompress_parts(read(filename)?).await?; let diff = Zsdiff::from_vec(parts).await?; @@ -46,11 +56,12 @@ async fn zpatch(filename: String, dest_dir: String) -> Result<(), io::Error> { for (k, hash) in diff.metadata.hashes { let path = Path::new(&dest_dir).join(k); let content = read(path)?; - let fs_hash = utils::get_hash(&content).await; + let fs_hash = utils::get_hash(content).await; if !fs_hash.eq(&hash) { Err(io::Error::new(io::ErrorKind::Other, "Hash mismatch"))? } } + fs::remove_dir_all(tmp_dir_name).ok(); Ok(()) } @@ -60,11 +71,16 @@ struct Args { filename: String, #[arg(short, long)] dest_dir: String, + #[arg(short, long)] + hash_check: bool, } #[tokio::main] async fn main() -> io::Result<()> { let args = Args::parse(); - zpatch(args.filename, args.dest_dir).await?; - Ok(()) + println!("{}", args.hash_check); + if args.hash_check { + check_hash(args.filename.clone()).await?; + } + zspatch(args.filename, args.dest_dir).await }