diff --git a/Cargo.lock b/Cargo.lock index 875c765..4a96139 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ dependencies = [ [[package]] name = "acridotheres_core" version = "0.1.1" -source = "git+https://github.com/acridotheres/core.git?tag=v0.1.1#451081afea0fb101834ee0da02351c2023833030" +source = "git+https://github.com/acridotheres/core.git?tag=v0.2.0#92b0704484fa38735249168fc6f23bfca066c3e1" dependencies = [ "chrono", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index d5ee0ba..3ce3af0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -acridotheres_core = { git = "https://github.com/acridotheres/core.git", tag="v0.1.1" } +acridotheres_core = { git = "https://github.com/acridotheres/core.git", tag="v0.2.0" } byte-unit = { version = "5.1.4", features = ["u128"] } clap = { version = "4.5.7", features = ["derive"] } diff --git a/src/commands.rs b/src/commands.rs new file mode 100644 index 0000000..f7d3d48 --- /dev/null +++ b/src/commands.rs @@ -0,0 +1,4 @@ +pub mod metadata; +pub mod version; +pub mod list; +pub mod extract; \ No newline at end of file diff --git a/src/commands/extract.rs b/src/commands/extract.rs new file mode 100644 index 0000000..ab40e82 --- /dev/null +++ b/src/commands/extract.rs @@ -0,0 +1,5 @@ +use corelib::{archive, formats}; + +pub fn extract(format: String, input: String, output: String, index: Option, path: Option, all: bool, check_integrity: bool, buffer_size: u64) { + archive::extract(formats::from_string(&format), input, output, index, path, all, check_integrity, buffer_size).unwrap(); +} \ No newline at end of file diff --git a/src/commands/list.rs b/src/commands/list.rs new file mode 100644 index 0000000..2cdf732 --- /dev/null +++ b/src/commands/list.rs @@ -0,0 +1,43 @@ +use corelib::{ + archive::{self, OriginalArchiveMetadata}, + formats::{self, Formats}, +}; + +pub fn list(format_string: String, input: String, check_integrity: bool, buffer_size: u64) { + let format = formats::from_string(&format_string); + let metadata = archive::metadata(format, input, check_integrity, buffer_size).unwrap(); + + match format { + Formats::Zip => { + let metadata = match *metadata { + OriginalArchiveMetadata::Zip(metadata) => metadata, + }; + + let mut i: u32 = 0; + println!(""); + for file in &metadata.files { + println!("{}", file.path); + println!("{}", "=".repeat(file.path.len())); + println!("Index: {}", i); + if file.is_directory { + println!("Directory\n"); + } else { + println!( + "Size: {} ({} compressed)", + byte_unit::Byte::from_u64(file.uncompressed_size.into()) + .get_appropriate_unit(byte_unit::UnitType::Decimal), + byte_unit::Byte::from_u64(file.size.into()) + .get_appropriate_unit(byte_unit::UnitType::Decimal) + ); + println!( + "Last modified: {}", + file.modified.format("%Y-%m-%d %H:%M:%S") + ); + println!("CRC-32 checksum: 0x{:x}", file.checksum); + println!("Compression method: {}\n", file.compression); + }; + i += 1; + } + } + } +} diff --git a/src/commands/metadata.rs b/src/commands/metadata.rs new file mode 100644 index 0000000..a2e45db --- /dev/null +++ b/src/commands/metadata.rs @@ -0,0 +1,44 @@ +use corelib::{ + archive::{self, OriginalArchiveMetadata}, + formats::{self, Formats}, +}; + +pub fn metadata(format_string: String, input: String, check_integrity: bool, buffer_size: u64) { + let format = formats::from_string(&format_string); + let metadata = archive::metadata(format, input, check_integrity, buffer_size).unwrap(); + + match format { + Formats::Zip => { + let metadata = match *metadata { + OriginalArchiveMetadata::Zip(metadata) => metadata, + }; + + println!("Type: {}", format_string); + let mut file_count: u32 = 0; + let mut dir_count: u32 = 0; + for file in &metadata.files { + if file.is_directory { + dir_count += 1; + continue; + } + file_count += 1; + } + println!("Files: {}", file_count); + println!("Directories: {}", dir_count); + let mut total_size = 0; + for file in &metadata.files { + total_size += file.uncompressed_size; + } + let total_size = byte_unit::Byte::from_u64(total_size.into()) + .get_appropriate_unit(byte_unit::UnitType::Decimal); + println!("Total size (uncompressed): {}", total_size); + let mut total_size = 0; + for file in &metadata.files { + total_size += file.size; + } + let total_size = byte_unit::Byte::from_u64(total_size.into()) + .get_appropriate_unit(byte_unit::UnitType::Decimal); + println!("Total size (compressed): {}", total_size); + } + } +} diff --git a/src/commands/version.rs b/src/commands/version.rs new file mode 100644 index 0000000..2e1d388 --- /dev/null +++ b/src/commands/version.rs @@ -0,0 +1,5 @@ +pub fn version() { + println!("Acridotheres\n"); + println!("cli v{}", env!("CARGO_PKG_VERSION")); + println!("core v{}", corelib::get_version()); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 20691e0..667fe04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ -mod text; +//mod text; +mod commands; use clap::Parser; @@ -44,6 +45,14 @@ struct Args { /// "all" (combine with -x or similar) #[arg(short, long)] all: bool, + + /// Skip integrity checks (not recommended, faster) + #[arg(long, default_value = "false")] + skip_integrity_checks: bool, + + /// Buffer size for file operations in bytes + #[arg(long, default_value = "16777216")] + buffer: u64, } fn get_command(args: &Args) -> &'static str { @@ -65,32 +74,30 @@ fn main() { let command = get_command(&args); - let format = args.input_type.unwrap_or_else(|| { - // add format detection here - "".to_string() - }); - let format = format.as_str(); - match command { - "version" => text::get_version(), - "metadata" => match format { - "zip" => text::zip_metadata(args.input.unwrap()), - _ => println!("Unknown format"), - }, - "list" => match format { - "zip" => text::zip_list(args.input.unwrap()), - _ => println!("Unknown format"), - }, - "extract" => match format { - "zip" => text::zip_extract( - args.input.unwrap(), - args.output.unwrap(), - args.index, - args.path, - args.all, - ), - _ => println!("Unknown format"), - }, + "version" => commands::version::version(), + "metadata" => commands::metadata::metadata( + args.input_type.unwrap(), + args.input.unwrap(), + !args.skip_integrity_checks, + args.buffer, + ), + "list" => commands::list::list( + args.input_type.unwrap(), + args.input.unwrap(), + !args.skip_integrity_checks, + args.buffer, + ), + "extract" => commands::extract::extract( + args.input_type.unwrap(), + args.input.unwrap(), + args.output.unwrap(), + args.index, + args.path, + args.all, + !args.skip_integrity_checks, + args.buffer, + ), _ => println!("Nothing to do, try --help"), } } diff --git a/src/text.rs b/src/text.rs deleted file mode 100644 index ef8ac46..0000000 --- a/src/text.rs +++ /dev/null @@ -1,148 +0,0 @@ -use byte_unit; -use corelib; - -pub fn get_version() { - println!("Acridotheres\n"); - println!("cli v{}", env!("CARGO_PKG_VERSION")); - println!("core v{}", corelib::get_version()); -} - -pub fn zip_metadata(path: String) { - let mut file = corelib::FileReader::new(&path); - - let metadata = corelib::formats::zip::parser::metadata(&mut file); - - println!("Type: {}", metadata.archive.format); - let mut file_count: u32 = 0; - let mut dir_count: u32 = 0; - for file in &metadata.files { - if file.file.is_directory { - dir_count += 1; - continue; - } - file_count += 1; - } - println!("Files: {}", file_count); - println!("Directories: {}", dir_count); - let mut total_size = 0; - for file in &metadata.files { - total_size += file.uncompressed_size; - } - let total_size = byte_unit::Byte::from_u64(total_size.into()) - .get_appropriate_unit(byte_unit::UnitType::Decimal); - println!("Total size (uncompressed): {}", total_size); - let mut total_size = 0; - for file in &metadata.files { - total_size += file.file.size; - } - let total_size = byte_unit::Byte::from_u64(total_size.into()) - .get_appropriate_unit(byte_unit::UnitType::Decimal); - println!("Total size (compressed): {}", total_size); -} - -pub fn zip_list(path: String) { - let mut file = corelib::FileReader::new(&path); - - let metadata = corelib::formats::zip::parser::metadata(&mut file); - - let mut i: u32 = 0; - println!(""); - for file in &metadata.files { - println!("{}", file.file.path); - println!("{}", "=".repeat(file.file.path.len())); - println!("Index: {}", i); - if file.file.is_directory { - println!("Directory\n"); - } else { - println!( - "Size: {} ({} compressed)", - byte_unit::Byte::from_u64(file.uncompressed_size.into()) - .get_appropriate_unit(byte_unit::UnitType::Decimal), - byte_unit::Byte::from_u64(file.file.size.into()) - .get_appropriate_unit(byte_unit::UnitType::Decimal) - ); - println!( - "Last modified: {}", - file.file.modified.format("%Y-%m-%d %H:%M:%S") - ); - println!("CRC-32 checksum: 0x{:x}", file.checksum); - println!("Compression method: {}\n", file.compression); - }; - i += 1; - } -} - -pub fn zip_extract( - input: String, - output: String, - index: Option, - path: Option, - all: bool, -) { - let mut file = corelib::FileReader::new(&input); - std::fs::create_dir_all(&output).unwrap(); - - let metadata = corelib::formats::zip::parser::metadata(&mut file); - - if all { - corelib::formats::zip::parser::extract(&mut file, &metadata.files, &1024, &|path| { - format!("{}/{}", &output, &path) - }); - } else { - if index != None { - let index = index.unwrap(); - if index >= metadata.files.len() as u32 { - println!("Index out of range"); - return; - } - let files = &vec![corelib::ZipFileEntry { - file: corelib::FileEntry { - path: metadata.files[index as usize].file.path.clone(), - size: metadata.files[index as usize].file.size, - offset: metadata.files[index as usize].file.offset, - modified: metadata.files[index as usize].file.modified, - is_directory: metadata.files[index as usize].file.is_directory, - }, - uncompressed_size: metadata.files[index as usize].uncompressed_size, - checksum: metadata.files[index as usize].checksum, - extra_field: metadata.files[index as usize].extra_field.clone(), - version: metadata.files[index as usize].version, - bit_flag: metadata.files[index as usize].bit_flag, - compression: metadata.files[index as usize].compression, - }]; - corelib::formats::zip::parser::extract(&mut file, files, &1024, &|path| { - format!("{}/{}", &output, &path) - }); - } else { - let path = path.unwrap(); - let files: Vec = metadata - .files - .iter() - .filter_map(|file| { - if file.file.path.starts_with(&path) { - Some(corelib::ZipFileEntry { - file: corelib::FileEntry { - path: file.file.path.clone(), - size: file.file.size, - offset: file.file.offset, - modified: file.file.modified, - is_directory: file.file.is_directory, - }, - uncompressed_size: file.uncompressed_size, - checksum: file.checksum, - extra_field: file.extra_field.clone(), - version: file.version, - bit_flag: file.bit_flag, - compression: file.compression, - }) - } else { - None - } - }) - .collect(); - corelib::formats::zip::parser::extract(&mut file, &files, &1024, &|path| { - format!("{}/{}", &output, &path) - }); - } - }; -}