omnizip 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +754 -0
- data/COPYING +502 -0
- data/Gemfile +17 -0
- data/LICENSE +12 -0
- data/README.adoc +1045 -0
- data/Rakefile +12 -0
- data/benchmark/README.md +260 -0
- data/benchmark/benchmark_suite.rb +125 -0
- data/benchmark/compression_bench.rb +181 -0
- data/benchmark/filter_bench.rb +180 -0
- data/benchmark/models/benchmark_result.rb +59 -0
- data/benchmark/models/comparison_result.rb +69 -0
- data/benchmark/profile_suite.rb +167 -0
- data/benchmark/reporter.rb +150 -0
- data/benchmark/run_benchmarks.rb +66 -0
- data/benchmark/test_data.rb +137 -0
- data/config/formats/rar3_spec.yml +91 -0
- data/config/formats/rar5_spec.yml +102 -0
- data/docs/.github/workflows/docs.yml +142 -0
- data/docs/.gitignore +21 -0
- data/docs/.lychee.toml +67 -0
- data/docs/Gemfile +13 -0
- data/docs/RAR_WRITE_SUPPORT.md +26 -0
- data/docs/README.md +101 -0
- data/docs/_config.yml +112 -0
- data/docs/assets/logo.svg +1 -0
- data/docs/assets/omnizip-logo.pdf +1540 -11
- data/docs/comparison/feature-matrix.adoc +694 -0
- data/docs/comparison/index.adoc +113 -0
- data/docs/comparison/vs-7zip.adoc +309 -0
- data/docs/comparison/vs-peazip.adoc +77 -0
- data/docs/comparison/vs-rubyzip.adoc +342 -0
- data/docs/comparison/vs-winrar.adoc +100 -0
- data/docs/compatibility.adoc +579 -0
- data/docs/concepts/index.adoc +129 -0
- data/docs/developer/architecture.adoc +256 -0
- data/docs/developer/contributing.adoc +158 -0
- data/docs/developer/index.adoc +25 -0
- data/docs/developer/testing.adoc +212 -0
- data/docs/getting-started/basic-usage.adoc +271 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +185 -0
- data/docs/getting-started/your-first-archive.adoc +218 -0
- data/docs/guides/advanced-features/encryption.adoc +300 -0
- data/docs/guides/advanced-features/index.adoc +49 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
- data/docs/guides/advanced-features/streaming.adoc +212 -0
- data/docs/guides/archive-formats/gzip-format.adoc +107 -0
- data/docs/guides/archive-formats/index.adoc +130 -0
- data/docs/guides/archive-formats/rar-format.adoc +104 -0
- data/docs/guides/archive-formats/rar5.adoc +521 -0
- data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
- data/docs/guides/archive-formats/tar-format.adoc +106 -0
- data/docs/guides/archive-formats/xz-format.adoc +118 -0
- data/docs/guides/archive-formats/zip-format.adoc +35 -0
- data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
- data/docs/guides/compression-algorithms/deflate.adoc +319 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +398 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
- data/docs/guides/creating-archives.adoc +354 -0
- data/docs/guides/extracting-archives.adoc +53 -0
- data/docs/guides/format-conversion.adoc +64 -0
- data/docs/guides/index.adoc +49 -0
- data/docs/guides/migration-rubyzip.adoc +217 -0
- data/docs/guides/parity-archives.adoc +605 -0
- data/docs/guides/performance-tuning.adoc +88 -0
- data/docs/index.adoc +218 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +188 -0
- data/docs/reference/cli/compress-command.adoc +114 -0
- data/docs/reference/cli/overview.adoc +140 -0
- data/docs/reference/index.adoc +26 -0
- data/docs/resources/faq.adoc +185 -0
- data/docs/resources/quick-reference.adoc +222 -0
- data/docs/troubleshooting/index.adoc +208 -0
- data/examples/api_comparison.rb +205 -0
- data/examples/deflate64_example.rb +96 -0
- data/examples/par2_demo.rb +121 -0
- data/examples/quick_start_native.rb +150 -0
- data/examples/quick_start_rubyzip.rb +115 -0
- data/examples/rubyzip_compatibility_demo.rb +194 -0
- data/exe/omnizip +27 -0
- data/lib/omnizip/algorithm.rb +130 -0
- data/lib/omnizip/algorithm_registry.rb +86 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
- data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
- data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
- data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
- data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
- data/lib/omnizip/algorithms/bzip2.rb +130 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
- data/lib/omnizip/algorithms/deflate.rb +128 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
- data/lib/omnizip/algorithms/deflate64.rb +109 -0
- data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
- data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
- data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
- data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
- data/lib/omnizip/algorithms/lzma/match.rb +32 -0
- data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
- data/lib/omnizip/algorithms/lzma.rb +238 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +141 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +116 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +82 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
- data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
- data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
- data/lib/omnizip/algorithms/zstandard.rb +138 -0
- data/lib/omnizip/buffer/memory_archive.rb +251 -0
- data/lib/omnizip/buffer/memory_extractor.rb +224 -0
- data/lib/omnizip/buffer.rb +176 -0
- data/lib/omnizip/checksum_registry.rb +114 -0
- data/lib/omnizip/checksums/crc32.rb +100 -0
- data/lib/omnizip/checksums/crc64.rb +101 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/verifier.rb +131 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +120 -0
- data/lib/omnizip/chunked.rb +129 -0
- data/lib/omnizip/cli/output_formatter.rb +104 -0
- data/lib/omnizip/cli.rb +572 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +427 -0
- data/lib/omnizip/commands/archive_extract_command.rb +272 -0
- data/lib/omnizip/commands/archive_list_command.rb +218 -0
- data/lib/omnizip/commands/archive_repair_command.rb +131 -0
- data/lib/omnizip/commands/archive_verify_command.rb +117 -0
- data/lib/omnizip/commands/compress_command.rb +117 -0
- data/lib/omnizip/commands/decompress_command.rb +120 -0
- data/lib/omnizip/commands/list_command.rb +53 -0
- data/lib/omnizip/commands/metadata_command.rb +153 -0
- data/lib/omnizip/commands/parity_create_command.rb +122 -0
- data/lib/omnizip/commands/parity_repair_command.rb +122 -0
- data/lib/omnizip/commands/parity_verify_command.rb +124 -0
- data/lib/omnizip/commands/profile_list_command.rb +56 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/convenience.rb +359 -0
- data/lib/omnizip/converter/conversion_registry.rb +49 -0
- data/lib/omnizip/converter/conversion_strategy.rb +121 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
- data/lib/omnizip/converter.rb +105 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/error.rb +106 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
- data/lib/omnizip/eta/rate_calculator.rb +104 -0
- data/lib/omnizip/eta/sample_history.rb +143 -0
- data/lib/omnizip/eta/time_estimator.rb +106 -0
- data/lib/omnizip/eta.rb +63 -0
- data/lib/omnizip/extraction/filter_chain.rb +177 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
- data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
- data/lib/omnizip/extraction/regex_pattern.rb +50 -0
- data/lib/omnizip/extraction/selective_extractor.rb +240 -0
- data/lib/omnizip/extraction.rb +111 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +113 -0
- data/lib/omnizip/filter.rb +139 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +166 -0
- data/lib/omnizip/filters/bcj.rb +279 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
- data/lib/omnizip/filters/bcj2.rb +99 -0
- data/lib/omnizip/filters/bcj_arm.rb +176 -0
- data/lib/omnizip/filters/bcj_arm64.rb +244 -0
- data/lib/omnizip/filters/bcj_ia64.rb +196 -0
- data/lib/omnizip/filters/bcj_ppc.rb +190 -0
- data/lib/omnizip/filters/bcj_sparc.rb +176 -0
- data/lib/omnizip/filters/bcj_x86.rb +193 -0
- data/lib/omnizip/filters/delta.rb +196 -0
- data/lib/omnizip/filters/filter_base.rb +72 -0
- data/lib/omnizip/filters/registry.rb +123 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/format_detector.rb +162 -0
- data/lib/omnizip/format_registry.rb +59 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +172 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +385 -0
- data/lib/omnizip/formats/cpio/reader.rb +196 -0
- data/lib/omnizip/formats/cpio/writer.rb +234 -0
- data/lib/omnizip/formats/cpio.rb +140 -0
- data/lib/omnizip/formats/format_spec_loader.rb +230 -0
- data/lib/omnizip/formats/gzip.rb +238 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
- data/lib/omnizip/formats/iso/directory_record.rb +152 -0
- data/lib/omnizip/formats/iso/joliet.rb +204 -0
- data/lib/omnizip/formats/iso/path_table.rb +125 -0
- data/lib/omnizip/formats/iso/reader.rb +197 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +530 -0
- data/lib/omnizip/formats/iso.rb +140 -0
- data/lib/omnizip/formats/lzip.rb +175 -0
- data/lib/omnizip/formats/lzma_alone.rb +171 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
- data/lib/omnizip/formats/rar/block_parser.rb +243 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +82 -0
- data/lib/omnizip/formats/rar/decompressor.rb +238 -0
- data/lib/omnizip/formats/rar/external_writer.rb +312 -0
- data/lib/omnizip/formats/rar/header.rb +192 -0
- data/lib/omnizip/formats/rar/license_validator.rb +109 -0
- data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
- data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
- data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
- data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
- data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
- data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
- data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
- data/lib/omnizip/formats/rar/reader.rb +366 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
- data/lib/omnizip/formats/rar/writer.rb +431 -0
- data/lib/omnizip/formats/rar.rb +205 -0
- data/lib/omnizip/formats/rar3/compressor.rb +73 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar3/reader.rb +386 -0
- data/lib/omnizip/formats/rar3/writer.rb +219 -0
- data/lib/omnizip/formats/rar5/compressor.rb +73 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar5/reader.rb +342 -0
- data/lib/omnizip/formats/rar5/writer.rb +214 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
- data/lib/omnizip/formats/seven_zip/header.rb +106 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
- data/lib/omnizip/formats/seven_zip.rb +93 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +94 -0
- data/lib/omnizip/formats/tar/header.rb +168 -0
- data/lib/omnizip/formats/tar/reader.rb +121 -0
- data/lib/omnizip/formats/tar/writer.rb +216 -0
- data/lib/omnizip/formats/tar.rb +84 -0
- data/lib/omnizip/formats/xz/reader.rb +116 -0
- data/lib/omnizip/formats/xz.rb +237 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
- data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
- data/lib/omnizip/formats/zip/reader.rb +250 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +375 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
- data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
- data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
- data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
- data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
- data/lib/omnizip/io/buffered_input.rb +146 -0
- data/lib/omnizip/io/buffered_output.rb +105 -0
- data/lib/omnizip/io/stream_manager.rb +115 -0
- data/lib/omnizip/link_handler/hard_link.rb +79 -0
- data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
- data/lib/omnizip/link_handler.rb +124 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +146 -0
- data/lib/omnizip/metadata/metadata_editor.rb +171 -0
- data/lib/omnizip/metadata/metadata_registry.rb +64 -0
- data/lib/omnizip/metadata/metadata_validator.rb +99 -0
- data/lib/omnizip/metadata.rb +57 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +73 -0
- data/lib/omnizip/models/compression_options.rb +71 -0
- data/lib/omnizip/models/conversion_options.rb +87 -0
- data/lib/omnizip/models/conversion_result.rb +135 -0
- data/lib/omnizip/models/eta_result.rb +46 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +144 -0
- data/lib/omnizip/models/filter_config.rb +183 -0
- data/lib/omnizip/models/match_result.rb +124 -0
- data/lib/omnizip/models/optimization_suggestion.rb +91 -0
- data/lib/omnizip/models/parallel_options.rb +104 -0
- data/lib/omnizip/models/performance_result.rb +79 -0
- data/lib/omnizip/models/profile_report.rb +82 -0
- data/lib/omnizip/models/progress_options.rb +38 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +81 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +203 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
- data/lib/omnizip/parallel/worker_pool.rb +223 -0
- data/lib/omnizip/parallel.rb +149 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +73 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
- data/lib/omnizip/parity/models/main_packet.rb +128 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +109 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
- data/lib/omnizip/parity/par2_creator.rb +531 -0
- data/lib/omnizip/parity/par2_repairer.rb +407 -0
- data/lib/omnizip/parity/par2_verifier.rb +364 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
- data/lib/omnizip/parity.rb +186 -0
- data/lib/omnizip/password/encryption_registry.rb +65 -0
- data/lib/omnizip/password/encryption_strategy.rb +96 -0
- data/lib/omnizip/password/password_validator.rb +129 -0
- data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
- data/lib/omnizip/password.rb +87 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
- data/lib/omnizip/pipe.rb +121 -0
- data/lib/omnizip/platform/ntfs_streams.rb +201 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +39 -0
- data/lib/omnizip/profile/balanced_profile.rb +33 -0
- data/lib/omnizip/profile/binary_profile.rb +36 -0
- data/lib/omnizip/profile/compression_profile.rb +158 -0
- data/lib/omnizip/profile/custom_profile.rb +157 -0
- data/lib/omnizip/profile/fast_profile.rb +33 -0
- data/lib/omnizip/profile/maximum_profile.rb +33 -0
- data/lib/omnizip/profile/profile_detector.rb +110 -0
- data/lib/omnizip/profile/profile_registry.rb +161 -0
- data/lib/omnizip/profile/text_profile.rb +36 -0
- data/lib/omnizip/profile.rb +190 -0
- data/lib/omnizip/profiler/memory_profiler.rb +66 -0
- data/lib/omnizip/profiler/method_profiler.rb +49 -0
- data/lib/omnizip/profiler/report_generator.rb +169 -0
- data/lib/omnizip/profiler.rb +204 -0
- data/lib/omnizip/progress/callback_reporter.rb +36 -0
- data/lib/omnizip/progress/console_reporter.rb +62 -0
- data/lib/omnizip/progress/log_reporter.rb +91 -0
- data/lib/omnizip/progress/operation_progress.rb +118 -0
- data/lib/omnizip/progress/progress_bar.rb +156 -0
- data/lib/omnizip/progress/progress_reporter.rb +40 -0
- data/lib/omnizip/progress/progress_tracker.rb +190 -0
- data/lib/omnizip/progress/silent_reporter.rb +24 -0
- data/lib/omnizip/progress.rb +127 -0
- data/lib/omnizip/rubyzip_compat.rb +63 -0
- data/lib/omnizip/temp/safe_extract.rb +168 -0
- data/lib/omnizip/temp/temp_file.rb +124 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +181 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +156 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +273 -0
- data/lib/omnizip/zip/output_stream.rb +324 -0
- data/lib/omnizip.rb +156 -0
- data/readme-docs/advanced-features.adoc +515 -0
- data/readme-docs/api-usage.adoc +444 -0
- data/readme-docs/architecture.adoc +449 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +442 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +325 -0
- data/readme-docs/installation.adoc +228 -0
- data/readme-docs/par2-archives.adoc +608 -0
- data/readme-docs/performance-profiler.adoc +389 -0
- data/readme-docs/preprocessing-filters.adoc +280 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +617 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
require_relative "../algorithm_registry"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Formats
|
|
8
|
+
# BZIP2 file format
|
|
9
|
+
#
|
|
10
|
+
# BZIP2 is a file compression format that uses the BZip2 algorithm
|
|
11
|
+
# with block-sorting compression (Burrows-Wheeler Transform).
|
|
12
|
+
#
|
|
13
|
+
# Format structure:
|
|
14
|
+
# - Magic bytes: "BZh" (0x42 0x5A 0x68)
|
|
15
|
+
# - Block size indicator: '1'-'9' (100KB - 900KB)
|
|
16
|
+
# - Compressed blocks
|
|
17
|
+
# - End-of-stream marker
|
|
18
|
+
#
|
|
19
|
+
# The format supports multiple compressed blocks, each with its own
|
|
20
|
+
# CRC32 checksum for data integrity verification.
|
|
21
|
+
module Bzip2File
|
|
22
|
+
# BZIP2 magic bytes
|
|
23
|
+
BZIP2_MAGIC = "BZh"
|
|
24
|
+
|
|
25
|
+
# Block size markers ('1' to '9')
|
|
26
|
+
BLOCK_SIZE_MIN = 1
|
|
27
|
+
BLOCK_SIZE_MAX = 9
|
|
28
|
+
|
|
29
|
+
# Stream markers
|
|
30
|
+
STREAM_MAGIC = 0x314159265359 # π in hex
|
|
31
|
+
BLOCK_MAGIC = 0x177245385090 # Block start marker
|
|
32
|
+
STREAM_END_MAGIC = 0x177245385090 # Stream end marker
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
# Compress a file with BZIP2
|
|
36
|
+
#
|
|
37
|
+
# @param input_path [String] Input file path
|
|
38
|
+
# @param output_path [String] Output BZIP2 file path
|
|
39
|
+
# @param options [Hash] Compression options
|
|
40
|
+
# @option options [Integer] :level Compression level (1-9)
|
|
41
|
+
def compress(input_path, output_path, options = {})
|
|
42
|
+
input_data = File.binread(input_path)
|
|
43
|
+
|
|
44
|
+
File.open(output_path, "wb") do |output|
|
|
45
|
+
compress_stream(StringIO.new(input_data), output, options)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Decompress a BZIP2 file
|
|
50
|
+
#
|
|
51
|
+
# @param input_path [String] Input BZIP2 file path
|
|
52
|
+
# @param output_path [String] Output file path
|
|
53
|
+
def decompress(input_path, output_path)
|
|
54
|
+
File.open(input_path, "rb") do |input|
|
|
55
|
+
File.open(output_path, "wb") do |output|
|
|
56
|
+
decompress_stream(input, output)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Compress data stream with BZIP2
|
|
62
|
+
#
|
|
63
|
+
# @param input_io [IO] Input stream
|
|
64
|
+
# @param output_io [IO] Output stream
|
|
65
|
+
# @param options [Hash] Compression options
|
|
66
|
+
def compress_stream(input_io, output_io, options = {})
|
|
67
|
+
level = options[:level] || 9
|
|
68
|
+
level = level.clamp(BLOCK_SIZE_MIN, BLOCK_SIZE_MAX)
|
|
69
|
+
|
|
70
|
+
input_data = input_io.read
|
|
71
|
+
|
|
72
|
+
# Write BZIP2 header
|
|
73
|
+
write_header(output_io, level)
|
|
74
|
+
|
|
75
|
+
# Get BZip2 algorithm
|
|
76
|
+
bzip2 = AlgorithmRegistry.get(:bzip2).new
|
|
77
|
+
|
|
78
|
+
# Compress data
|
|
79
|
+
compressed_io = StringIO.new
|
|
80
|
+
compressed_io.set_encoding(Encoding::BINARY)
|
|
81
|
+
|
|
82
|
+
bzip2.compress(
|
|
83
|
+
StringIO.new(input_data),
|
|
84
|
+
compressed_io,
|
|
85
|
+
build_compression_options(level),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Write compressed data
|
|
89
|
+
compressed_io.rewind
|
|
90
|
+
compressed_data = compressed_io.read
|
|
91
|
+
output_io.write(compressed_data)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Decompress BZIP2 stream
|
|
95
|
+
#
|
|
96
|
+
# @param input_io [IO] Input stream
|
|
97
|
+
# @param output_io [IO] Output stream
|
|
98
|
+
def decompress_stream(input_io, output_io)
|
|
99
|
+
# Read and verify header
|
|
100
|
+
read_header(input_io)
|
|
101
|
+
|
|
102
|
+
# Get BZip2 algorithm
|
|
103
|
+
bzip2 = AlgorithmRegistry.get(:bzip2).new
|
|
104
|
+
|
|
105
|
+
# Decompress data
|
|
106
|
+
decompressed_io = StringIO.new
|
|
107
|
+
decompressed_io.set_encoding(Encoding::BINARY)
|
|
108
|
+
|
|
109
|
+
bzip2.decompress(input_io, decompressed_io)
|
|
110
|
+
|
|
111
|
+
# Write decompressed data
|
|
112
|
+
decompressed_io.rewind
|
|
113
|
+
output_io.write(decompressed_io.read)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Register BZIP2 format when loaded
|
|
117
|
+
def register!
|
|
118
|
+
require_relative "../format_registry"
|
|
119
|
+
FormatRegistry.register(".bz2", Omnizip::Formats::Bzip2File)
|
|
120
|
+
FormatRegistry.register(".bzip2", Omnizip::Formats::Bzip2File)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
# Write BZIP2 header
|
|
126
|
+
#
|
|
127
|
+
# @param output [IO] Output stream
|
|
128
|
+
# @param level [Integer] Compression level (1-9)
|
|
129
|
+
def write_header(output, level)
|
|
130
|
+
# BZIP2 magic: "BZh" + block size
|
|
131
|
+
header = "#{BZIP2_MAGIC}#{level}"
|
|
132
|
+
output.write(header)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Read BZIP2 header
|
|
136
|
+
#
|
|
137
|
+
# @param input [IO] Input stream
|
|
138
|
+
# @return [Integer] Block size level
|
|
139
|
+
def read_header(input)
|
|
140
|
+
magic = input.read(3)
|
|
141
|
+
unless magic == BZIP2_MAGIC
|
|
142
|
+
raise Error, "Not a BZIP2 file (invalid magic bytes)"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
level_char = input.read(1)
|
|
146
|
+
level = level_char.to_i
|
|
147
|
+
|
|
148
|
+
unless level.between?(BLOCK_SIZE_MIN, BLOCK_SIZE_MAX)
|
|
149
|
+
raise Error, "Invalid BZIP2 block size: #{level_char}"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
level
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Build compression options
|
|
156
|
+
#
|
|
157
|
+
# @param level [Integer] Compression level
|
|
158
|
+
# @return [Object] Compression options
|
|
159
|
+
def build_compression_options(level)
|
|
160
|
+
require_relative "../models/compression_options"
|
|
161
|
+
|
|
162
|
+
Models::CompressionOptions.new.tap do |opts|
|
|
163
|
+
opts.level = level
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Auto-register on load
|
|
172
|
+
Omnizip::Formats::Bzip2File.register!
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module Cpio
|
|
6
|
+
# CPIO format constants
|
|
7
|
+
#
|
|
8
|
+
# Defines magic numbers, file types, and format specifications
|
|
9
|
+
# for different CPIO archive formats.
|
|
10
|
+
module Constants
|
|
11
|
+
# Magic numbers for different CPIO formats
|
|
12
|
+
MAGIC_BINARY = 0o070707 # Old binary format
|
|
13
|
+
MAGIC_ODC = "070707" # Old portable ASCII format
|
|
14
|
+
MAGIC_NEWC = "070701" # New ASCII format (SVR4, most common)
|
|
15
|
+
MAGIC_CRC = "070702" # New ASCII with CRC
|
|
16
|
+
|
|
17
|
+
# File type masks (from POSIX)
|
|
18
|
+
S_IFMT = 0o170000 # File type mask
|
|
19
|
+
S_IFSOCK = 0o140000 # Socket
|
|
20
|
+
S_IFLNK = 0o120000 # Symbolic link
|
|
21
|
+
S_IFREG = 0o100000 # Regular file
|
|
22
|
+
S_IFBLK = 0o060000 # Block device
|
|
23
|
+
S_IFDIR = 0o040000 # Directory
|
|
24
|
+
S_IFCHR = 0o020000 # Character device
|
|
25
|
+
S_IFIFO = 0o010000 # FIFO/pipe
|
|
26
|
+
|
|
27
|
+
# Permission bits
|
|
28
|
+
S_ISUID = 0o004000 # Set UID bit
|
|
29
|
+
S_ISGID = 0o002000 # Set GID bit
|
|
30
|
+
S_ISVTX = 0o001000 # Sticky bit
|
|
31
|
+
S_IRWXU = 0o000700 # User permissions
|
|
32
|
+
S_IRUSR = 0o000400 # User read
|
|
33
|
+
S_IWUSR = 0o000200 # User write
|
|
34
|
+
S_IXUSR = 0o000100 # User execute
|
|
35
|
+
S_IRWXG = 0o000070 # Group permissions
|
|
36
|
+
S_IRGRP = 0o000040 # Group read
|
|
37
|
+
S_IWGRP = 0o000020 # Group write
|
|
38
|
+
S_IXGRP = 0o000010 # Group execute
|
|
39
|
+
S_IRWXO = 0o000007 # Other permissions
|
|
40
|
+
S_IROTH = 0o000004 # Other read
|
|
41
|
+
S_IWOTH = 0o000002 # Other write
|
|
42
|
+
S_IXOTH = 0o000001 # Other execute
|
|
43
|
+
|
|
44
|
+
# CPIO newc header size (110 bytes for newc format)
|
|
45
|
+
NEWC_HEADER_SIZE = 110
|
|
46
|
+
|
|
47
|
+
# Trailer entry name
|
|
48
|
+
TRAILER_NAME = "TRAILER!!!"
|
|
49
|
+
|
|
50
|
+
# Alignment for newc format (4 bytes)
|
|
51
|
+
NEWC_ALIGNMENT = 4
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "constants"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Formats
|
|
7
|
+
module Cpio
|
|
8
|
+
# CPIO archive entry
|
|
9
|
+
#
|
|
10
|
+
# Represents a file, directory, or special file in a CPIO archive.
|
|
11
|
+
# Supports newc, CRC, and ODC formats.
|
|
12
|
+
class Entry
|
|
13
|
+
include Constants
|
|
14
|
+
|
|
15
|
+
# @return [String] Magic number identifying format
|
|
16
|
+
attr_accessor :magic
|
|
17
|
+
|
|
18
|
+
# @return [Integer] Inode number
|
|
19
|
+
attr_accessor :ino
|
|
20
|
+
|
|
21
|
+
# @return [Integer] File mode and type
|
|
22
|
+
attr_accessor :mode
|
|
23
|
+
|
|
24
|
+
# @return [Integer] User ID
|
|
25
|
+
attr_accessor :uid
|
|
26
|
+
|
|
27
|
+
# @return [Integer] Group ID
|
|
28
|
+
attr_accessor :gid
|
|
29
|
+
|
|
30
|
+
# @return [Integer] Number of hard links
|
|
31
|
+
attr_accessor :nlink
|
|
32
|
+
|
|
33
|
+
# @return [Integer] Modification time (Unix timestamp)
|
|
34
|
+
attr_accessor :mtime
|
|
35
|
+
|
|
36
|
+
# @return [Integer] File size in bytes
|
|
37
|
+
attr_accessor :filesize
|
|
38
|
+
|
|
39
|
+
# @return [Integer] Device major number
|
|
40
|
+
attr_accessor :dev_major
|
|
41
|
+
|
|
42
|
+
# @return [Integer] Device minor number
|
|
43
|
+
attr_accessor :dev_minor
|
|
44
|
+
|
|
45
|
+
# @return [Integer] Special device major number (for device files)
|
|
46
|
+
attr_accessor :rdev_major
|
|
47
|
+
|
|
48
|
+
# @return [Integer] Special device minor number (for device files)
|
|
49
|
+
attr_accessor :rdev_minor
|
|
50
|
+
|
|
51
|
+
# @return [Integer] Filename length (including null terminator)
|
|
52
|
+
attr_accessor :namesize
|
|
53
|
+
|
|
54
|
+
# @return [Integer] Checksum (CRC format only)
|
|
55
|
+
attr_accessor :checksum
|
|
56
|
+
|
|
57
|
+
# @return [String] Entry name/path
|
|
58
|
+
attr_accessor :name
|
|
59
|
+
|
|
60
|
+
# @return [String] File data
|
|
61
|
+
attr_accessor :data
|
|
62
|
+
|
|
63
|
+
# Initialize CPIO entry
|
|
64
|
+
#
|
|
65
|
+
# @param attributes [Hash] Entry attributes
|
|
66
|
+
def initialize(attributes = {})
|
|
67
|
+
@magic = attributes.fetch(:magic, MAGIC_NEWC)
|
|
68
|
+
@ino = attributes.fetch(:ino, 0)
|
|
69
|
+
@mode = attributes.fetch(:mode, S_IFREG | 0o644)
|
|
70
|
+
@uid = attributes.fetch(:uid, 0)
|
|
71
|
+
@gid = attributes.fetch(:gid, 0)
|
|
72
|
+
@nlink = attributes.fetch(:nlink, 1)
|
|
73
|
+
@mtime = attributes.fetch(:mtime, Time.now.to_i)
|
|
74
|
+
@filesize = attributes.fetch(:filesize, 0)
|
|
75
|
+
@dev_major = attributes.fetch(:dev_major, 0)
|
|
76
|
+
@dev_minor = attributes.fetch(:dev_minor, 0)
|
|
77
|
+
@rdev_major = attributes.fetch(:rdev_major, 0)
|
|
78
|
+
@rdev_minor = attributes.fetch(:rdev_minor, 0)
|
|
79
|
+
@namesize = attributes.fetch(:namesize, 0)
|
|
80
|
+
@checksum = attributes.fetch(:checksum, 0)
|
|
81
|
+
@name = attributes.fetch(:name, "")
|
|
82
|
+
@data = attributes.fetch(:data, "")
|
|
83
|
+
|
|
84
|
+
# Auto-calculate namesize if not provided
|
|
85
|
+
@namesize = @name.bytesize + 1 if @namesize.zero? && !@name.empty?
|
|
86
|
+
@filesize = @data.bytesize if @filesize.zero? && !@data.empty?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Check if entry is a directory
|
|
90
|
+
#
|
|
91
|
+
# @return [Boolean] true if directory
|
|
92
|
+
def directory?
|
|
93
|
+
(@mode & S_IFMT) == S_IFDIR
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Check if entry is a regular file
|
|
97
|
+
#
|
|
98
|
+
# @return [Boolean] true if regular file
|
|
99
|
+
def file?
|
|
100
|
+
(@mode & S_IFMT) == S_IFREG
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Check if entry is a symbolic link
|
|
104
|
+
#
|
|
105
|
+
# @return [Boolean] true if symlink
|
|
106
|
+
def symlink?
|
|
107
|
+
(@mode & S_IFMT) == S_IFLNK
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Check if entry is a device
|
|
111
|
+
#
|
|
112
|
+
# @return [Boolean] true if device (block or character)
|
|
113
|
+
def device?
|
|
114
|
+
type = @mode & S_IFMT
|
|
115
|
+
[S_IFBLK, S_IFCHR].include?(type)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Check if entry is the trailer
|
|
119
|
+
#
|
|
120
|
+
# @return [Boolean] true if trailer entry
|
|
121
|
+
def trailer?
|
|
122
|
+
@name == TRAILER_NAME
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Convert entry to binary format
|
|
126
|
+
#
|
|
127
|
+
# @param format [Symbol] CPIO format (:newc, :crc, :odc)
|
|
128
|
+
# @return [String] Binary representation
|
|
129
|
+
def to_binary(format: :newc)
|
|
130
|
+
case format
|
|
131
|
+
when :newc, :crc
|
|
132
|
+
to_newc_binary
|
|
133
|
+
when :odc
|
|
134
|
+
to_odc_binary
|
|
135
|
+
else
|
|
136
|
+
raise ArgumentError, "Unsupported CPIO format: #{format}"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Convert to newc format binary
|
|
141
|
+
#
|
|
142
|
+
# @return [String] Binary data in newc format
|
|
143
|
+
def to_newc_binary
|
|
144
|
+
# Build header (110 bytes, ASCII hex)
|
|
145
|
+
header = format(
|
|
146
|
+
"%06s%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
|
|
147
|
+
@magic,
|
|
148
|
+
@ino & 0xFFFFFFFF,
|
|
149
|
+
@mode & 0xFFFFFFFF,
|
|
150
|
+
@uid & 0xFFFFFFFF,
|
|
151
|
+
@gid & 0xFFFFFFFF,
|
|
152
|
+
@nlink & 0xFFFFFFFF,
|
|
153
|
+
@mtime & 0xFFFFFFFF,
|
|
154
|
+
@filesize & 0xFFFFFFFF,
|
|
155
|
+
@dev_major & 0xFFFFFFFF,
|
|
156
|
+
@dev_minor & 0xFFFFFFFF,
|
|
157
|
+
@rdev_major & 0xFFFFFFFF,
|
|
158
|
+
@rdev_minor & 0xFFFFFFFF,
|
|
159
|
+
@namesize & 0xFFFFFFFF,
|
|
160
|
+
@checksum & 0xFFFFFFFF,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Assemble complete entry
|
|
164
|
+
result = +""
|
|
165
|
+
result << header
|
|
166
|
+
result << @name
|
|
167
|
+
result << "\x00"
|
|
168
|
+
|
|
169
|
+
# Pad header+name to 4-byte boundary
|
|
170
|
+
header_name_size = header.bytesize + @name.bytesize + 1
|
|
171
|
+
padding = padding_to_align(header_name_size, NEWC_ALIGNMENT)
|
|
172
|
+
result << ("\x00" * padding) if padding.positive?
|
|
173
|
+
|
|
174
|
+
# Add file data
|
|
175
|
+
result << @data
|
|
176
|
+
|
|
177
|
+
# Pad data to 4-byte boundary
|
|
178
|
+
data_padding = padding_to_align(@data.bytesize, NEWC_ALIGNMENT)
|
|
179
|
+
result << ("\x00" * data_padding) if data_padding.positive?
|
|
180
|
+
|
|
181
|
+
result
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Convert to ODC format binary
|
|
185
|
+
#
|
|
186
|
+
# @return [String] Binary data in ODC format
|
|
187
|
+
def to_odc_binary
|
|
188
|
+
# ODC format uses 6-character octal fields
|
|
189
|
+
header = format(
|
|
190
|
+
"%06o%06o%06o%06o%06o%06o%06o%06o%011o%06o%011o",
|
|
191
|
+
MAGIC_BINARY,
|
|
192
|
+
(@dev_major << 8) | @dev_minor,
|
|
193
|
+
@ino & 0o777777,
|
|
194
|
+
@mode & 0o777777,
|
|
195
|
+
@uid & 0o777777,
|
|
196
|
+
@gid & 0o777777,
|
|
197
|
+
@nlink & 0o777777,
|
|
198
|
+
(@rdev_major << 8) | @rdev_minor,
|
|
199
|
+
@mtime & 0o77777777777,
|
|
200
|
+
@namesize & 0o777777,
|
|
201
|
+
@filesize & 0o77777777777,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
result = +""
|
|
205
|
+
result << header
|
|
206
|
+
result << @name
|
|
207
|
+
result << "\x00"
|
|
208
|
+
result << @data
|
|
209
|
+
|
|
210
|
+
result
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Parse entry from binary data
|
|
214
|
+
#
|
|
215
|
+
# @param io [IO] Input stream
|
|
216
|
+
# @param format [Symbol, nil] Format hint (:newc, :crc, :odc, nil=auto-detect)
|
|
217
|
+
# @return [Entry] Parsed entry
|
|
218
|
+
def self.parse(io, format: nil)
|
|
219
|
+
# Read magic to detect format
|
|
220
|
+
magic = io.read(6)
|
|
221
|
+
io.seek(-6, ::IO::SEEK_CUR) # Rewind
|
|
222
|
+
|
|
223
|
+
format ||= detect_format(magic)
|
|
224
|
+
|
|
225
|
+
case format
|
|
226
|
+
when :newc, :crc
|
|
227
|
+
parse_newc(io)
|
|
228
|
+
when :odc
|
|
229
|
+
parse_odc(io)
|
|
230
|
+
else
|
|
231
|
+
raise "Unknown CPIO format"
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Detect CPIO format from magic
|
|
236
|
+
#
|
|
237
|
+
# @param magic [String] Magic bytes
|
|
238
|
+
# @return [Symbol] Format type
|
|
239
|
+
def self.detect_format(magic)
|
|
240
|
+
case magic
|
|
241
|
+
when MAGIC_NEWC then :newc
|
|
242
|
+
when MAGIC_CRC then :crc
|
|
243
|
+
when MAGIC_ODC then :odc
|
|
244
|
+
else
|
|
245
|
+
# Try binary format
|
|
246
|
+
magic_int = magic.unpack1("n")
|
|
247
|
+
magic_int == MAGIC_BINARY ? :binary : nil
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Parse newc format entry
|
|
252
|
+
#
|
|
253
|
+
# @param io [IO] Input stream
|
|
254
|
+
# @return [Entry] Parsed entry
|
|
255
|
+
def self.parse_newc(io)
|
|
256
|
+
header = io.read(NEWC_HEADER_SIZE)
|
|
257
|
+
raise "Truncated CPIO header" unless header && header.bytesize == NEWC_HEADER_SIZE
|
|
258
|
+
|
|
259
|
+
# Parse ASCII hex fields
|
|
260
|
+
magic = header[0, 6]
|
|
261
|
+
ino = header[6, 8].to_i(16)
|
|
262
|
+
mode = header[14, 8].to_i(16)
|
|
263
|
+
uid = header[22, 8].to_i(16)
|
|
264
|
+
gid = header[30, 8].to_i(16)
|
|
265
|
+
nlink = header[38, 8].to_i(16)
|
|
266
|
+
mtime = header[46, 8].to_i(16)
|
|
267
|
+
filesize = header[54, 8].to_i(16)
|
|
268
|
+
dev_major = header[62, 8].to_i(16)
|
|
269
|
+
dev_minor = header[70, 8].to_i(16)
|
|
270
|
+
rdev_major = header[78, 8].to_i(16)
|
|
271
|
+
rdev_minor = header[86, 8].to_i(16)
|
|
272
|
+
namesize = header[94, 8].to_i(16)
|
|
273
|
+
checksum = header[102, 8].to_i(16)
|
|
274
|
+
|
|
275
|
+
# Read filename
|
|
276
|
+
name_data = io.read(namesize)
|
|
277
|
+
name = name_data.chomp("\x00")
|
|
278
|
+
|
|
279
|
+
# Skip padding to 4-byte boundary
|
|
280
|
+
header_name_size = NEWC_HEADER_SIZE + namesize
|
|
281
|
+
padding = padding_to_align(header_name_size, NEWC_ALIGNMENT)
|
|
282
|
+
io.read(padding) if padding.positive?
|
|
283
|
+
|
|
284
|
+
# Read file data
|
|
285
|
+
data = io.read(filesize)
|
|
286
|
+
|
|
287
|
+
# Skip padding to 4-byte boundary
|
|
288
|
+
data_padding = padding_to_align(filesize, NEWC_ALIGNMENT)
|
|
289
|
+
io.read(data_padding) if data_padding.positive?
|
|
290
|
+
|
|
291
|
+
new(
|
|
292
|
+
magic: magic,
|
|
293
|
+
ino: ino,
|
|
294
|
+
mode: mode,
|
|
295
|
+
uid: uid,
|
|
296
|
+
gid: gid,
|
|
297
|
+
nlink: nlink,
|
|
298
|
+
mtime: mtime,
|
|
299
|
+
filesize: filesize,
|
|
300
|
+
dev_major: dev_major,
|
|
301
|
+
dev_minor: dev_minor,
|
|
302
|
+
rdev_major: rdev_major,
|
|
303
|
+
rdev_minor: rdev_minor,
|
|
304
|
+
namesize: namesize,
|
|
305
|
+
checksum: checksum,
|
|
306
|
+
name: name,
|
|
307
|
+
data: data || "",
|
|
308
|
+
)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# Parse ODC format entry
|
|
312
|
+
#
|
|
313
|
+
# @param io [IO] Input stream
|
|
314
|
+
# @return [Entry] Parsed entry
|
|
315
|
+
def self.parse_odc(io)
|
|
316
|
+
header = io.read(76)
|
|
317
|
+
raise "Truncated CPIO header" unless header && header.bytesize == 76
|
|
318
|
+
|
|
319
|
+
# Parse octal fields
|
|
320
|
+
magic = header[0, 6]
|
|
321
|
+
dev = header[6, 6].to_i(8)
|
|
322
|
+
ino = header[12, 6].to_i(8)
|
|
323
|
+
mode = header[18, 6].to_i(8)
|
|
324
|
+
uid = header[24, 6].to_i(8)
|
|
325
|
+
gid = header[30, 6].to_i(8)
|
|
326
|
+
nlink = header[36, 6].to_i(8)
|
|
327
|
+
rdev = header[42, 6].to_i(8)
|
|
328
|
+
mtime = header[48, 11].to_i(8)
|
|
329
|
+
namesize = header[59, 6].to_i(8)
|
|
330
|
+
filesize = header[65, 11].to_i(8)
|
|
331
|
+
|
|
332
|
+
# Extract device numbers
|
|
333
|
+
dev_major = dev >> 8
|
|
334
|
+
dev_minor = dev & 0xFF
|
|
335
|
+
rdev_major = rdev >> 8
|
|
336
|
+
rdev_minor = rdev & 0xFF
|
|
337
|
+
|
|
338
|
+
# Read filename
|
|
339
|
+
name_data = io.read(namesize)
|
|
340
|
+
name = name_data.chomp("\x00")
|
|
341
|
+
|
|
342
|
+
# Read file data
|
|
343
|
+
data = io.read(filesize)
|
|
344
|
+
|
|
345
|
+
new(
|
|
346
|
+
magic: magic,
|
|
347
|
+
ino: ino,
|
|
348
|
+
mode: mode,
|
|
349
|
+
uid: uid,
|
|
350
|
+
gid: gid,
|
|
351
|
+
nlink: nlink,
|
|
352
|
+
mtime: mtime,
|
|
353
|
+
filesize: filesize,
|
|
354
|
+
dev_major: dev_major,
|
|
355
|
+
dev_minor: dev_minor,
|
|
356
|
+
rdev_major: rdev_major,
|
|
357
|
+
rdev_minor: rdev_minor,
|
|
358
|
+
namesize: namesize,
|
|
359
|
+
checksum: 0,
|
|
360
|
+
name: name,
|
|
361
|
+
data: data || "",
|
|
362
|
+
)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
private
|
|
366
|
+
|
|
367
|
+
# Calculate padding needed to align to boundary
|
|
368
|
+
#
|
|
369
|
+
# @param size [Integer] Current size
|
|
370
|
+
# @param alignment [Integer] Alignment boundary
|
|
371
|
+
# @return [Integer] Padding bytes needed
|
|
372
|
+
def padding_to_align(size, alignment)
|
|
373
|
+
remainder = size % alignment
|
|
374
|
+
remainder.zero? ? 0 : alignment - remainder
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# Class method for padding calculation
|
|
378
|
+
def self.padding_to_align(size, alignment)
|
|
379
|
+
remainder = size % alignment
|
|
380
|
+
remainder.zero? ? 0 : alignment - remainder
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
end
|