diff --git a/.envrc b/.envrc deleted file mode 100644 index 8392d15..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use flake \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index b178713..3b12320 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,26 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aho-corasick" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -58,6 +78,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bitflags" version = "1.3.2" @@ -70,12 +96,49 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cc" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" dependencies = [ + "jobserver", "libc", ] @@ -85,6 +148,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "2.34.0" @@ -140,6 +213,30 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -208,6 +305,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deranged" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + [[package]] name = "either" version = "1.9.0" @@ -231,6 +355,9 @@ dependencies = [ "indicatif", "rayon", "tar", + "unrar", + "xz2", + "zip", ] [[package]] @@ -255,6 +382,26 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "flate2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gimli" version = "0.27.3" @@ -276,6 +423,15 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "indenter" version = "0.3.3" @@ -295,6 +451,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -304,6 +469,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -332,6 +506,17 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "memchr" version = "2.5.0" @@ -428,18 +613,71 @@ dependencies = [ "windows-targets 0.48.3", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] + [[package]] name = "pin-project-lite" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + [[package]] name = "portable-atomic" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + [[package]] name = "rayon" version = "1.7.0" @@ -471,6 +709,35 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "regex" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -483,6 +750,48 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -534,6 +843,23 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "2.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tar" version = "0.4.40" @@ -564,6 +890,23 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" +dependencies = [ + "deranged", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + [[package]] name = "tracing" version = "0.1.37" @@ -606,12 +949,47 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + [[package]] name = "unicode-width" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unrar" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850dc99da3a3c12a9400a52a3c510057bf2b16c6c9a495492850d25ed9d757ab" +dependencies = [ + "bitflags 1.3.2", + "regex", + "unrar_sys", + "widestring", +] + +[[package]] +name = "unrar_sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e536227cb6a91f8e88adb0219912e004a107c9724a094f90baad9229281efa" +dependencies = [ + "cc", + "libc", + "winapi", +] + [[package]] name = "valuable" version = "0.1.0" @@ -624,12 +1002,24 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + [[package]] name = "winapi" version = "0.3.9" @@ -792,3 +1182,62 @@ checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" dependencies = [ "libc", ] + +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 5db2c5f..d1fc806 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,7 @@ crossterm = "0.27.0" eyre = "0.6.8" indicatif = "0.17.6" rayon = "1.7.0" -tar = "0.4.40" \ No newline at end of file +tar = "0.4.40" +unrar = "0.5.1" +xz2 = "0.1.7" +zip = "0.6.6" diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 606a787..0000000 --- a/flake.lock +++ /dev/null @@ -1,26 +0,0 @@ -{ - "nodes": { - "nixpkgs": { - "locked": { - "lastModified": 1685566663, - "narHash": "sha256-btHN1czJ6rzteeCuE/PNrdssqYD2nIA4w48miQAFloM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "4ecab3273592f27479a583fb6d975d4aba3486fe", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "23.05", - "type": "indirect" - } - }, - "root": { - "inputs": { - "nixpkgs": "nixpkgs" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 3c709cb..0000000 --- a/flake.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ - description = "A tool for solving my inability to remember the right args to extract all the damnd formats"; - - inputs={ - nixpkgs.url = "nixpkgs/23.05"; - }; - - outputs = {self, nixpkgs}: let - system = "x86_64-linux"; - pkgs = nixpkgs.legacyPackages.${system}; - - in { - defaultPackage.${system} = with pkgs; stdenv.mkDerivation { - name = "extract_rs"; - src = self; - - buildInputs = [ - openssl - pkgconfig - rustc - cargo - cargo-watch - just - ]; - - shellHook = '' - export OPENSSL_DIR=${openssl.dev} - export OPENSSL_LIB_DIR=${openssl.out}/lib - export OPENSSL_INCLUDE_DIR=${openssl.dev}/include - ''; - }; - }; -} diff --git a/src/extractors.rs b/src/extractors.rs new file mode 100644 index 0000000..1e75d67 --- /dev/null +++ b/src/extractors.rs @@ -0,0 +1,121 @@ +use std::{fs, io, path::Path}; +use unrar::Archive; +use xz2::bufread::XzDecoder; + +// pub fn extract_xz(xz_file: &Path) -> io::Result<()> { +// let file = fs::File::open(xz_file)?; +// let decompressor = XzDecoder::new(file); +// let mut archive = tar::Archive::new(decompressor); + +// for entry in archive.entries()? { +// let mut entry = entry?; + +// let entry_path = entry.path()?; +// let full_path = Path::new("output_directory/").join(entry_path); + +// if entry.header().entry_type().is_dir() { +// fs::create_dir_all(&full_path)?; +// } else { +// fs::create_dir_all(&full_path.parent().unwrap())?; + +// let mut file = fs::File::create(&full_path)?; +// io::copy(&mut entry, &mut file)?; +// } +// } + +// Ok(()) +// } + +pub fn extract_zip(zip_file: &Path) -> io::Result<()> { + let file = fs::File::open(zip_file)?; + let mut archive = zip::ZipArchive::new(file)?; + + for i in 0..archive.len() { + let mut file = archive.by_index(i)?; + let outpath = match file.enclosed_name() { + Some(path) => path.to_owned(), + None => continue, + }; + + { + let comment = file.comment(); + if !comment.is_empty() { + println!("File {} comment: {}", i, comment); + } + } + + if (*file.name()).ends_with('/') { + println!("File {} extracted to \"{}\"", i, outpath.display()); + fs::create_dir_all(&outpath).unwrap(); + } else { + println!( + "File {} extracted to \"{}\" ({} bytes)", + i, + outpath.display(), + file.size() + ); + if let Some(p) = outpath.parent() { + if !p.exists() { + fs::create_dir_all(p).unwrap(); + } + } + let mut outfile = fs::File::create(&outpath).unwrap(); + io::copy(&mut file, &mut outfile).unwrap(); + } + + // Get and Set permissions + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + + if let Some(mode) = file.unix_mode() { + fs::set_permissions(&outpath, fs::Permissions::from_mode(mode)).unwrap(); + } + } + } + + Ok(()) +} + +pub fn extract_rar(rar_file: &Path) -> Result<(), Box> { + let mut archive = Archive::new(rar_file) + .open_for_processing() + .unwrap(); + + while let Some(header) = archive.read_header()? { + println!( + "{} bytes: {}", + header.entry().unpacked_size, + header.entry().filename.to_string_lossy(), + ); + archive = if header.entry().is_file() { + header.extract()? + } else { + header.skip()? + }; + } + + Ok(()) +} + + pub fn extract_tar(tar_file: &Path) -> io::Result<()> { + let tar_file = fs::File::open(tar_file)?; + let mut a = tar::Archive::new(tar_file); + + for i in a.entries()? { + let mut i = i?; + let entry_path = i.header().path()?; + let full_path = Path::new("output_directory/").join(entry_path); + + if i.header().entry_type().is_dir() { + fs::create_dir_all(&full_path)?; + } else { + fs::create_dir_all(&full_path.parent().unwrap())?; + + let mut file = fs::File::create(&full_path)?; + io::copy(&mut i, &mut file)?; + } + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index b46e22a..865bbda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,72 +1,84 @@ -use indicatif::{ProgressBar, ProgressStyle}; -use std::{ - io, - path::Path, - fs::{self, File}, -}; -use rayon::prelude::*; -use tar::Archive; - -fn main() -> color_eyre::eyre::Result<()> { - color_eyre::install()?; - - let app = clap::App::new("extract") - .arg( - clap::Arg::with_name("files") - .required(true) - .multiple(true) - .help("Files to be extracted"), - ); - - let matches = app.get_matches(); - let files: Vec<_> = matches.values_of("files").unwrap().collect(); - - let pb = ProgressBar::new(files.len() as u64); - pb.set_style( - ProgressStyle::default_bar() - .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})")?, - ); - - files.par_iter().for_each(|file| { - if let Err(err) = extract_file(file, "output_directory/") { - println!("Error extracting file '{}': {}", file, err); - } - pb.inc(1); - }); - - pb.finish_with_message("All files extracted successfully!"); - Ok(()) -} -fn extract_tar(file: &str, output_dir: &str) -> color_eyre::eyre::Result<()> { - let tar_file = File::open(file)?; - let mut a = Archive::new(tar_file); - - for i in a.entries()? { - let mut i = i?; - let entry_path = i.header().path()?; - let full_path = Path::new(output_dir).join(entry_path); - - if i.header().entry_type().is_dir() { - fs::create_dir_all(&full_path)?; - } else { - fs::create_dir_all(&full_path.parent().unwrap())?; - - let mut file = File::create(&full_path)?; - io::copy(&mut i, &mut file)?; - } - } - - Ok(()) +mod extractors; +use extractors::{extract_zip, extract_rar, extract_tar}; +fn main() { + std::process::exit(run()); } -fn extract_file(file: &str, output_dir: &str) -> color_eyre::eyre::Result<()> { - if !Path::new(file).exists() { - return Err(color_eyre::eyre::eyre!("'{}' - file does not exist", file)); + /* + TODO: [ ] setup rayon to handle concurrent file processsing when passed + more than one file + */ + /* + TODO: [ ] Write for loop to iter over all extensions of a file to handle + files that are tared and then compressed ex: foo.tar.gz, foo.tar.gz + */ + /* + TODO: [ ] add support for decompression of: + [ ] bz2 + [ ] tbz2 + [ ] tgz + [ ] txz + [ ] lzma + [ ] gz + [ ] z + [ ] 7z + [ ] arj + [ ] cab + [ ] arj + [ ] cab + [ ] chm + [ ] deb + [ ] dmg + [ ] iso + [ ] lzh + [ ] msi + [ ] rpm + [ ] udf + [ ] wim + [ ] xar + [ ] exe + */ +fn run() -> i32 { + let args: Vec<_> = std::env::args().collect(); + if args.len() < 2 { + println!("Usage: {} ", args[0]); + return 1; } - if let Some("tar") = Path::new(file).extension().and_then(|s| s.to_str()) { - extract_tar(file, output_dir)?; - } else { - println!("extract: '{}' - unknown archive method", file); + let fname = std::path::Path::new(&*args[1]); + if let Some(extension) = fname.extension().and_then(|s| s.to_str()) { + match extension { + "zip" => { + if let Err(err) = extract_zip(&fname) { + println!("Error extracting ZIP: {}", err); + return 1; + } + } + "rar" => { + if let Err(err) = extract_rar(&fname) { + println!("Error extracting RAR: {}", err); + return 1; + } + } + "tar" => { + if let Err(err) = extract_tar(&fname) { + println!("Error extracting TAR: {}", err); + return 1; + } + } + // "xz" => { + // if let Err(err) = extract_tar(&fname) { + // println!("Error extracting XZ: {}", err); + // return 1; + // } + // } + _ => { + println!("Unsupported file extension: {}", extension); + return 1; + } + } + return 0; } - Ok(()) + + println!("Unknown file format"); + return 1; } \ No newline at end of file