From 5056050fca3900d452cd8605e12f65537e70a341 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Thu, 1 May 2025 18:35:10 -0300 Subject: [PATCH] feat: Make bzip3 optout Fixes #812 --- Cargo.toml | 4 ++-- src/archive/bzip3_stub.rs | 7 +++++++ src/archive/mod.rs | 2 ++ src/commands/compress.rs | 14 ++++++++++---- src/commands/decompress.rs | 11 ++++++++++- src/commands/list.rs | 12 +++++++++--- src/error.rs | 1 + src/utils/fs.rs | 2 +- 8 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 src/archive/bzip3_stub.rs diff --git a/Cargo.toml b/Cargo.toml index 835e55f..3577a2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ brotli = "7.0.0" bstr = { version = "1.10.0", default-features = false, features = ["std"] } bytesize = "1.3.0" bzip2 = "0.4.4" -bzip3 = { version = "0.9.0", features = ["bundled"] } +bzip3 = { version = "0.9.0", features = ["bundled"] , optional = true } clap = { version = "4.5.20", features = ["derive", "env"] } filetime_creation = "0.2" flate2 = { version = "1.0.30", default-features = false } @@ -70,7 +70,7 @@ regex = "1.10.4" test-strategy = "0.4.0" [features] -default = ["unrar", "use_zlib", "use_zstd_thin"] +default = ["unrar", "use_zlib", "use_zstd_thin", "bzip3"] use_zlib = ["flate2/zlib", "gzp/deflate_zlib", "zip/deflate-zlib"] use_zstd_thin = ["zstd/thin"] allow_piped_choice = [] diff --git a/src/archive/bzip3_stub.rs b/src/archive/bzip3_stub.rs new file mode 100644 index 0000000..2de3534 --- /dev/null +++ b/src/archive/bzip3_stub.rs @@ -0,0 +1,7 @@ +use crate::Error; + +pub fn no_support() -> Error { + Error::UnsupportedFormat { + reason: "BZip3 support is disabled for this build, possibly due to missing bindgen-cli dependency.".into(), + } +} diff --git a/src/archive/mod.rs b/src/archive/mod.rs index 4cfacc0..897b952 100644 --- a/src/archive/mod.rs +++ b/src/archive/mod.rs @@ -7,3 +7,5 @@ pub mod rar_stub; pub mod sevenz; pub mod tar; pub mod zip; +#[cfg(not(feature = "bzip3"))] +pub mod bzip3_stub; diff --git a/src/commands/compress.rs b/src/commands/compress.rs index b6f7042..83c18a5 100644 --- a/src/commands/compress.rs +++ b/src/commands/compress.rs @@ -57,10 +57,16 @@ pub fn compress_files( encoder, level.map_or_else(Default::default, |l| bzip2::Compression::new((l as u32).clamp(1, 9))), )), - Bzip3 => Box::new( - // Use block size of 16 MiB - bzip3::write::Bz3Encoder::new(encoder, 16 * 2_usize.pow(20))?, - ), + Bzip3 => { + #[cfg(not(feature = "bzip3"))] + return Err(archive::bzip3_stub::no_support()); + + #[cfg(feature = "bzip3")] + Box::new( + // Use block size of 16 MiB + bzip3::write::Bz3Encoder::new(encoder, 16 * 2_usize.pow(20))?, + ) + }, Lz4 => Box::new(lz4_flex::frame::FrameEncoder::new(encoder).auto_finish()), Lzma => Box::new(xz2::write::XzEncoder::new( encoder, diff --git a/src/commands/decompress.rs b/src/commands/decompress.rs index 36c8658..ed0acf7 100644 --- a/src/commands/decompress.rs +++ b/src/commands/decompress.rs @@ -23,6 +23,9 @@ use crate::{ QuestionAction, QuestionPolicy, BUFFER_CAPACITY, }; +#[cfg(not(feature = "bzip3"))] +use crate::archive; + trait ReadSeek: Read + io::Seek {} impl ReadSeek for T {} @@ -118,7 +121,13 @@ pub fn decompress_file(options: DecompressOptions) -> crate::Result<()> { let decoder: Box = match format { Gzip => Box::new(flate2::read::GzDecoder::new(decoder)), Bzip => Box::new(bzip2::read::BzDecoder::new(decoder)), - Bzip3 => Box::new(bzip3::read::Bz3Decoder::new(decoder)?), + Bzip3 => { + #[cfg(not(feature = "bzip3"))] + return Err(archive::bzip3_stub::no_support()); + + #[cfg(feature = "bzip3")] + Box::new(bzip3::read::Bz3Decoder::new(decoder)?) + }, Lz4 => Box::new(lz4_flex::frame::FrameDecoder::new(decoder)), Lzma => Box::new(xz2::read::XzDecoder::new(decoder)), Snappy => Box::new(snap::read::FrameDecoder::new(decoder)), diff --git a/src/commands/list.rs b/src/commands/list.rs index a64c55c..5b3c804 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -6,7 +6,7 @@ use std::{ use fs_err as fs; use crate::{ - archive::sevenz, + archive, commands::warn_user_about_loading_zip_in_memory, extension::CompressionFormat::{self, *}, list::{self, FileInArchive, ListOptions}, @@ -50,7 +50,13 @@ pub fn list_archive_contents( let decoder: Box = match format { Gzip => Box::new(flate2::read::GzDecoder::new(decoder)), Bzip => Box::new(bzip2::read::BzDecoder::new(decoder)), - Bzip3 => Box::new(bzip3::read::Bz3Decoder::new(decoder).unwrap()), + Bzip3 => { + #[cfg(not(feature = "bzip3"))] + return Err(archive::bzip3_stub::no_support()); + + #[cfg(feature = "bzip3")] + Box::new(bzip3::read::Bz3Decoder::new(decoder).unwrap()) + }, Lz4 => Box::new(lz4_flex::frame::FrameDecoder::new(decoder)), Lzma => Box::new(xz2::read::XzDecoder::new(decoder)), Snappy => Box::new(snap::read::FrameDecoder::new(decoder)), @@ -111,7 +117,7 @@ pub fn list_archive_contents( } } - Box::new(sevenz::list_archive(archive_path, password)?) + Box::new(archive::sevenz::list_archive(archive_path, password)?) } Gzip | Bzip | Bzip3 | Lz4 | Lzma | Snappy | Zstd | Brotli => { panic!("Not an archive! This should never happen, if it does, something is wrong with `CompressionFormat::is_archive()`. Please report this error!"); diff --git a/src/error.rs b/src/error.rs index 3f5bc3e..b3c33df 100644 --- a/src/error.rs +++ b/src/error.rs @@ -200,6 +200,7 @@ impl From for Error { } } +#[cfg(feature = "bzip3")] impl From for Error { fn from(err: bzip3::Error) -> Self { use bzip3::Error as Bz3Error; diff --git a/src/utils/fs.rs b/src/utils/fs.rs index eb40625..f65f152 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -133,7 +133,7 @@ pub fn try_infer_extension(path: &Path) -> Option { buf.starts_with(&[0x42, 0x5A, 0x68]) } fn is_bz3(buf: &[u8]) -> bool { - buf.starts_with(bzip3::MAGIC_NUMBER) + buf.starts_with(b"BZ3v1") } fn is_xz(buf: &[u8]) -> bool { buf.starts_with(&[0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00])