omnizip 0.4.7-arm-linux
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 +293 -0
- data/CHANGELOG.md +1647 -0
- data/CONTEXT.md +68 -0
- data/COPYING +502 -0
- data/Gemfile +19 -0
- data/LICENSE +12 -0
- data/README.adoc +1327 -0
- data/Rakefile +15 -0
- data/TODO.refactor/00-overview.md +67 -0
- data/TODO.refactor/01-registry-base-class.md +81 -0
- data/TODO.refactor/02-error-hierarchy.md +57 -0
- data/TODO.refactor/03-autoload-entry-point.md +69 -0
- data/TODO.refactor/04-filter-base-consolidation.md +49 -0
- data/TODO.refactor/05-send-private-methods.md +64 -0
- data/TODO.refactor/06-instance-variable-access.md +69 -0
- data/TODO.refactor/07-respond-to-replacement.md +237 -0
- data/TODO.refactor/08-spec-doubles.md +27 -0
- data/TODO.refactor/09-cli-shared-module.md +35 -0
- data/TODO.refactor/10-format-detector-ocp.md +34 -0
- data/TODO.refactor/11-convenience-decoupling.md +38 -0
- data/TODO.refactor/12-thread-safety.md +8 -0
- data/TODO.refactor/13-lutaml-model-migration.md +158 -0
- data/TODO.refactor/14-add-missing-specs.md +25 -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 +92 -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 +263 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +183 -0
- data/docs/getting-started/your-first-archive.adoc +219 -0
- data/docs/guides/advanced-features/encryption.adoc +277 -0
- data/docs/guides/advanced-features/index.adoc +59 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
- data/docs/guides/advanced-features/streaming.adoc +142 -0
- data/docs/guides/archive-formats/gzip-format.adoc +105 -0
- data/docs/guides/archive-formats/index.adoc +160 -0
- data/docs/guides/archive-formats/ole-format.adoc +151 -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/rpm-format.adoc +108 -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 +114 -0
- data/docs/guides/compression-algorithms/deflate.adoc +313 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +394 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
- data/docs/guides/creating-archives.adoc +348 -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 +228 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +187 -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/rust-backend.md +0 -0
- data/docs/troubleshooting/index.adoc +207 -0
- data/docs/xar_format.md +216 -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 +176 -0
- data/lib/omnizip/algorithm_registry.rb +65 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
- data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
- data/lib/omnizip/algorithms/bzip2.rb +108 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
- data/lib/omnizip/algorithms/deflate.rb +135 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
- data/lib/omnizip/algorithms/deflate64.rb +118 -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 +146 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
- data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -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 +233 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
- data/lib/omnizip/algorithms/lzma.rb +266 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +133 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +146 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +122 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
- data/lib/omnizip/algorithms/registration.rb +28 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
- data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
- data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
- data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
- data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
- data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
- data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
- data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
- data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +210 -0
- data/lib/omnizip/algorithms.rb +35 -0
- data/lib/omnizip/archive/builder.rb +48 -0
- data/lib/omnizip/archive/reader_session.rb +67 -0
- data/lib/omnizip/archive.rb +86 -0
- data/lib/omnizip/archive_handler.rb +82 -0
- data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
- data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
- data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
- data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
- data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
- data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
- data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
- data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
- data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
- data/lib/omnizip/archive_handlers.rb +18 -0
- data/lib/omnizip/backends.rb +160 -0
- data/lib/omnizip/buffer/memory_archive.rb +246 -0
- data/lib/omnizip/buffer/memory_extractor.rb +234 -0
- data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
- data/lib/omnizip/buffer.rb +187 -0
- data/lib/omnizip/checksum_registry.rb +41 -0
- data/lib/omnizip/checksums/crc32.rb +101 -0
- data/lib/omnizip/checksums/crc64.rb +102 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/registration.rb +16 -0
- data/lib/omnizip/checksums/verifier.rb +130 -0
- data/lib/omnizip/checksums.rb +11 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +123 -0
- data/lib/omnizip/chunked.rb +123 -0
- data/lib/omnizip/cli/output_formatter.rb +112 -0
- data/lib/omnizip/cli.rb +604 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +245 -0
- data/lib/omnizip/commands/archive_extract_command.rb +231 -0
- data/lib/omnizip/commands/archive_list_command.rb +204 -0
- data/lib/omnizip/commands/archive_repair_command.rb +129 -0
- data/lib/omnizip/commands/archive_verify_command.rb +115 -0
- data/lib/omnizip/commands/compress_command.rb +115 -0
- data/lib/omnizip/commands/decompress_command.rb +149 -0
- data/lib/omnizip/commands/list_command.rb +51 -0
- data/lib/omnizip/commands/metadata_command.rb +215 -0
- data/lib/omnizip/commands/parity_create_command.rb +114 -0
- data/lib/omnizip/commands/parity_repair_command.rb +120 -0
- data/lib/omnizip/commands/parity_verify_command.rb +122 -0
- data/lib/omnizip/commands/profile_list_command.rb +54 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/commands.rb +21 -0
- data/lib/omnizip/convenience.rb +389 -0
- data/lib/omnizip/converter/conversion_registry.rb +50 -0
- data/lib/omnizip/converter/conversion_strategy.rb +108 -0
- data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
- data/lib/omnizip/converter.rb +124 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/crypto.rb +11 -0
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/error.rb +110 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +96 -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 +68 -0
- data/lib/omnizip/extraction/filter_chain.rb +179 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +66 -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 +247 -0
- data/lib/omnizip/extraction.rb +115 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +117 -0
- data/lib/omnizip/filter.rb +141 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +113 -0
- data/lib/omnizip/filters/bcj.rb +277 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
- data/lib/omnizip/filters/bcj2.rb +93 -0
- data/lib/omnizip/filters/bcj_arm.rb +174 -0
- data/lib/omnizip/filters/bcj_arm64.rb +242 -0
- data/lib/omnizip/filters/bcj_ia64.rb +194 -0
- data/lib/omnizip/filters/bcj_ppc.rb +188 -0
- data/lib/omnizip/filters/bcj_sparc.rb +174 -0
- data/lib/omnizip/filters/bcj_x86.rb +191 -0
- data/lib/omnizip/filters/delta.rb +195 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/filters.rb +20 -0
- data/lib/omnizip/format_detector.rb +166 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +159 -0
- data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +389 -0
- data/lib/omnizip/formats/cpio/reader.rb +194 -0
- data/lib/omnizip/formats/cpio/writer.rb +232 -0
- data/lib/omnizip/formats/cpio.rb +132 -0
- data/lib/omnizip/formats/format_spec_loader.rb +228 -0
- data/lib/omnizip/formats/gzip.rb +236 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
- data/lib/omnizip/formats/iso/directory_record.rb +162 -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 +194 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +543 -0
- data/lib/omnizip/formats/iso.rb +133 -0
- data/lib/omnizip/formats/lzip.rb +161 -0
- data/lib/omnizip/formats/lzma_alone.rb +149 -0
- data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
- data/lib/omnizip/formats/msi/constants.rb +157 -0
- data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
- data/lib/omnizip/formats/msi/entry.rb +134 -0
- data/lib/omnizip/formats/msi/reader.rb +301 -0
- data/lib/omnizip/formats/msi/string_pool.rb +246 -0
- data/lib/omnizip/formats/msi/table_parser.rb +244 -0
- data/lib/omnizip/formats/msi.rb +73 -0
- data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
- data/lib/omnizip/formats/ole/constants.rb +61 -0
- data/lib/omnizip/formats/ole/dirent.rb +439 -0
- data/lib/omnizip/formats/ole/header.rb +199 -0
- data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
- data/lib/omnizip/formats/ole/storage.rb +482 -0
- data/lib/omnizip/formats/ole/types/variant.rb +338 -0
- data/lib/omnizip/formats/ole.rb +143 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
- data/lib/omnizip/formats/rar/block_parser.rb +282 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -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/lz77_huffman.rb +25 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
- data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
- data/lib/omnizip/formats/rar/compression.rb +17 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +88 -0
- data/lib/omnizip/formats/rar/decompressor.rb +316 -0
- data/lib/omnizip/formats/rar/external_writer.rb +311 -0
- data/lib/omnizip/formats/rar/header.rb +209 -0
- data/lib/omnizip/formats/rar/license_validator.rb +111 -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/models.rb +14 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -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 +96 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +208 -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 +260 -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 +176 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
- data/lib/omnizip/formats/rar/reader.rb +377 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
- data/lib/omnizip/formats/rar/writer.rb +437 -0
- data/lib/omnizip/formats/rar.rb +193 -0
- data/lib/omnizip/formats/rar3/compressor.rb +71 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar3/reader.rb +107 -0
- data/lib/omnizip/formats/rar3/writer.rb +220 -0
- data/lib/omnizip/formats/rar3.rb +15 -0
- data/lib/omnizip/formats/rar5/compressor.rb +71 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar5/reader.rb +130 -0
- data/lib/omnizip/formats/rar5/writer.rb +65 -0
- data/lib/omnizip/formats/rar5.rb +15 -0
- data/lib/omnizip/formats/rpm/constants.rb +58 -0
- data/lib/omnizip/formats/rpm/entry.rb +106 -0
- data/lib/omnizip/formats/rpm/header.rb +106 -0
- data/lib/omnizip/formats/rpm/lead.rb +132 -0
- data/lib/omnizip/formats/rpm/tag.rb +228 -0
- data/lib/omnizip/formats/rpm/writer.rb +652 -0
- data/lib/omnizip/formats/rpm.rb +458 -0
- data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
- data/lib/omnizip/formats/seven_zip/header.rb +102 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/models.rb +20 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
- data/lib/omnizip/formats/seven_zip.rb +179 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +98 -0
- data/lib/omnizip/formats/tar/header.rb +206 -0
- data/lib/omnizip/formats/tar/reader.rb +119 -0
- data/lib/omnizip/formats/tar/writer.rb +212 -0
- data/lib/omnizip/formats/tar.rb +74 -0
- data/lib/omnizip/formats/xar/constants.rb +119 -0
- data/lib/omnizip/formats/xar/entry.rb +268 -0
- data/lib/omnizip/formats/xar/header.rb +223 -0
- data/lib/omnizip/formats/xar/reader.rb +400 -0
- data/lib/omnizip/formats/xar/toc.rb +570 -0
- data/lib/omnizip/formats/xar/writer.rb +461 -0
- data/lib/omnizip/formats/xar.rb +145 -0
- data/lib/omnizip/formats/xz/reader.rb +121 -0
- data/lib/omnizip/formats/xz/writer.rb +416 -0
- data/lib/omnizip/formats/xz.rb +210 -0
- data/lib/omnizip/formats/xz_const.rb +49 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl.rb +52 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
- data/lib/omnizip/formats/zip/reader.rb +376 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +489 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/formats.rb +29 -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/base.rb +19 -0
- data/lib/omnizip/implementations/rust/archive.rb +93 -0
- data/lib/omnizip/implementations/rust/library.rb +221 -0
- data/lib/omnizip/implementations/rust.rb +26 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
- data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
- data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
- data/lib/omnizip/implementations/seven_zip.rb +11 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
- data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
- data/lib/omnizip/implementations/xz_utils.rb +10 -0
- data/lib/omnizip/implementations.rb +25 -0
- data/lib/omnizip/io/buffered_input.rb +147 -0
- data/lib/omnizip/io/buffered_output.rb +106 -0
- data/lib/omnizip/io/source.rb +143 -0
- data/lib/omnizip/io/stream_manager.rb +117 -0
- data/lib/omnizip/io.rb +15 -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 +129 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +153 -0
- data/lib/omnizip/metadata/metadata_editor.rb +169 -0
- data/lib/omnizip/metadata/metadata_registry.rb +71 -0
- data/lib/omnizip/metadata/metadata_validator.rb +101 -0
- data/lib/omnizip/metadata.rb +58 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +41 -0
- data/lib/omnizip/models/attribute_apply.rb +40 -0
- data/lib/omnizip/models/compression_options.rb +53 -0
- data/lib/omnizip/models/conversion_options.rb +79 -0
- data/lib/omnizip/models/conversion_result.rb +141 -0
- data/lib/omnizip/models/eta_result.rb +45 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +142 -0
- data/lib/omnizip/models/filter_config.rb +148 -0
- data/lib/omnizip/models/match_result.rb +141 -0
- data/lib/omnizip/models/optimization_suggestion.rb +95 -0
- data/lib/omnizip/models/parallel_options.rb +116 -0
- data/lib/omnizip/models/performance_result.rb +85 -0
- data/lib/omnizip/models/profile_report.rb +116 -0
- data/lib/omnizip/models/progress_options.rb +39 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +45 -0
- data/lib/omnizip/parallel/engine.rb +52 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +225 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
- data/lib/omnizip/parallel/thread_pool.rb +60 -0
- data/lib/omnizip/parallel/worker_pool.rb +227 -0
- data/lib/omnizip/parallel.rb +156 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +71 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
- data/lib/omnizip/parity/models/main_packet.rb +126 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +102 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
- data/lib/omnizip/parity/models.rb +27 -0
- data/lib/omnizip/parity/par2_creator.rb +496 -0
- data/lib/omnizip/parity/par2_repairer.rb +409 -0
- data/lib/omnizip/parity/par2_verifier.rb +373 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
- data/lib/omnizip/parity.rb +207 -0
- data/lib/omnizip/password/encryption_registry.rb +26 -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 +190 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
- data/lib/omnizip/password.rb +88 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
- data/lib/omnizip/pipe.rb +120 -0
- data/lib/omnizip/platform/ntfs_streams.rb +200 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +36 -0
- data/lib/omnizip/profile/balanced_profile.rb +31 -0
- data/lib/omnizip/profile/binary_profile.rb +33 -0
- data/lib/omnizip/profile/compression_profile.rb +157 -0
- data/lib/omnizip/profile/custom_profile.rb +155 -0
- data/lib/omnizip/profile/fast_profile.rb +31 -0
- data/lib/omnizip/profile/maximum_profile.rb +31 -0
- data/lib/omnizip/profile/profile_detector.rb +108 -0
- data/lib/omnizip/profile/profile_registry.rb +160 -0
- data/lib/omnizip/profile/text_profile.rb +33 -0
- data/lib/omnizip/profile.rb +261 -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 +158 -0
- data/lib/omnizip/profiler.rb +192 -0
- data/lib/omnizip/progress/callback_reporter.rb +34 -0
- data/lib/omnizip/progress/console_reporter.rb +59 -0
- data/lib/omnizip/progress/log_reporter.rb +89 -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 +215 -0
- data/lib/omnizip/progress/silent_reporter.rb +22 -0
- data/lib/omnizip/progress.rb +131 -0
- data/lib/omnizip/registry.rb +111 -0
- data/lib/omnizip/rubyzip_compat.rb +61 -0
- data/lib/omnizip/temp/safe_extract.rb +124 -0
- data/lib/omnizip/temp/temp_file.rb +123 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +184 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +160 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +270 -0
- data/lib/omnizip/zip/output_stream.rb +320 -0
- data/lib/omnizip/zip.rb +23 -0
- data/lib/omnizip.rb +157 -0
- data/lib/tasks/msi_test_files.rake +66 -0
- data/lib/tasks/platform_gems.rake +147 -0
- data/lib/tasks/rust_backend.rake +48 -0
- data/readme-docs/advanced-features.adoc +514 -0
- data/readme-docs/api-usage.adoc +445 -0
- data/readme-docs/architecture.adoc +450 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +446 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +316 -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/vendor/libomnizip_ffi.so +0 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +768 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module Xar
|
|
6
|
+
# XAR archive header parser and builder
|
|
7
|
+
#
|
|
8
|
+
# The XAR header is 28 bytes (or 64 bytes for extended format):
|
|
9
|
+
# - Bytes 0-3: Magic number (0x78617221 = "xar!")
|
|
10
|
+
# - Bytes 4-5: Header size (little-endian)
|
|
11
|
+
# - Bytes 6-7: Format version (little-endian)
|
|
12
|
+
# - Bytes 8-15: TOC compressed size (big-endian uint64)
|
|
13
|
+
# - Bytes 16-23: TOC uncompressed size (big-endian uint64)
|
|
14
|
+
# - Bytes 24-27: Checksum algorithm (big-endian uint32)
|
|
15
|
+
# - Bytes 28-63: (Optional) Checksum name for CKSUM_OTHER
|
|
16
|
+
class Header
|
|
17
|
+
include Omnizip::Formats::Xar::Constants
|
|
18
|
+
|
|
19
|
+
attr_reader :magic, :header_size, :version, :toc_compressed_size,
|
|
20
|
+
:toc_uncompressed_size, :checksum_algorithm,
|
|
21
|
+
:checksum_name
|
|
22
|
+
|
|
23
|
+
# Parse header from binary data
|
|
24
|
+
#
|
|
25
|
+
# @param data [String] Binary header data (28+ bytes)
|
|
26
|
+
# @return [Header] Parsed header object
|
|
27
|
+
# @raise [ArgumentError] If data is invalid
|
|
28
|
+
def self.parse(data)
|
|
29
|
+
if data.bytesize < HEADER_SIZE
|
|
30
|
+
raise ArgumentError,
|
|
31
|
+
"Header data too short (#{data.bytesize} bytes)"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
magic = data[0, 4].unpack1("N")
|
|
35
|
+
# XAR spec: header_size and version are little-endian, rest are big-endian
|
|
36
|
+
# However, some tools (like macOS xar) store these in big-endian format.
|
|
37
|
+
# We detect this by checking if the parsed values make sense.
|
|
38
|
+
header_size_le = data[4, 2].unpack1("v") # little-endian
|
|
39
|
+
header_size_be = data[4, 2].unpack1("n") # big-endian
|
|
40
|
+
version_le = data[6, 2].unpack1("v") # little-endian
|
|
41
|
+
version_be = data[6, 2].unpack1("n") # big-endian
|
|
42
|
+
|
|
43
|
+
# Detect endianness: standard header is 28 bytes, version is 1
|
|
44
|
+
# If little-endian gives valid values, use it; otherwise use big-endian
|
|
45
|
+
if header_size_le == HEADER_SIZE && version_le == XAR_VERSION
|
|
46
|
+
header_size = header_size_le
|
|
47
|
+
version = version_le
|
|
48
|
+
elsif header_size_be == HEADER_SIZE && version_be == XAR_VERSION
|
|
49
|
+
header_size = header_size_be
|
|
50
|
+
version = version_be
|
|
51
|
+
else
|
|
52
|
+
# Default to little-endian (spec-compliant)
|
|
53
|
+
header_size = header_size_le
|
|
54
|
+
version = version_le
|
|
55
|
+
# Normalize version 256 to 1 (big-endian encoding of version 1)
|
|
56
|
+
version = 1 if version == 256
|
|
57
|
+
end
|
|
58
|
+
toc_compressed_size = data[8, 8].unpack1("Q>") # big-endian uint64
|
|
59
|
+
toc_uncompressed_size = data[16, 8].unpack1("Q>") # big-endian uint64
|
|
60
|
+
checksum_algorithm = data[24, 4].unpack1("N")
|
|
61
|
+
|
|
62
|
+
# Parse checksum name for custom algorithms
|
|
63
|
+
checksum_name = nil
|
|
64
|
+
if checksum_algorithm == CKSUM_OTHER && data.bytesize >= HEADER_SIZE_EX
|
|
65
|
+
checksum_name = data[28, 36].strip
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
new(
|
|
69
|
+
magic: magic,
|
|
70
|
+
header_size: header_size,
|
|
71
|
+
version: version,
|
|
72
|
+
toc_compressed_size: toc_compressed_size,
|
|
73
|
+
toc_uncompressed_size: toc_uncompressed_size,
|
|
74
|
+
checksum_algorithm: checksum_algorithm,
|
|
75
|
+
checksum_name: checksum_name,
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Read header from file
|
|
80
|
+
#
|
|
81
|
+
# @param file [IO] File handle positioned at start
|
|
82
|
+
# @return [Header] Parsed header
|
|
83
|
+
def self.read(file)
|
|
84
|
+
data = file.read(HEADER_SIZE_EX) # Read max possible size
|
|
85
|
+
raise ArgumentError, "Failed to read header" unless data
|
|
86
|
+
|
|
87
|
+
# Parse to get actual header size
|
|
88
|
+
header = parse(data)
|
|
89
|
+
|
|
90
|
+
# Seek back if we read too much
|
|
91
|
+
if data.bytesize > header.header_size
|
|
92
|
+
file.seek(header.header_size, ::IO::SEEK_SET)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
header
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Initialize header
|
|
99
|
+
#
|
|
100
|
+
# @param magic [Integer] Magic number
|
|
101
|
+
# @param header_size [Integer] Header size in bytes
|
|
102
|
+
# @param version [Integer] Format version
|
|
103
|
+
# @param toc_compressed_size [Integer] Compressed TOC size
|
|
104
|
+
# @param toc_uncompressed_size [Integer] Uncompressed TOC size
|
|
105
|
+
# @param checksum_algorithm [Integer] Checksum algorithm constant
|
|
106
|
+
# @param checksum_name [String, nil] Checksum name for CKSUM_OTHER
|
|
107
|
+
def initialize(magic: MAGIC,
|
|
108
|
+
header_size: HEADER_SIZE,
|
|
109
|
+
version: XAR_VERSION,
|
|
110
|
+
toc_compressed_size: 0,
|
|
111
|
+
toc_uncompressed_size: 0,
|
|
112
|
+
checksum_algorithm: CKSUM_SHA1,
|
|
113
|
+
checksum_name: nil)
|
|
114
|
+
@magic = magic
|
|
115
|
+
@header_size = checksum_algorithm == CKSUM_OTHER && checksum_name ? HEADER_SIZE_EX : header_size
|
|
116
|
+
@version = version
|
|
117
|
+
@toc_compressed_size = toc_compressed_size
|
|
118
|
+
@toc_uncompressed_size = toc_uncompressed_size
|
|
119
|
+
@checksum_algorithm = checksum_algorithm
|
|
120
|
+
@checksum_name = checksum_name
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Validate header
|
|
124
|
+
#
|
|
125
|
+
# @return [Boolean] true if valid
|
|
126
|
+
# @raise [ArgumentError] If header is invalid
|
|
127
|
+
def validate!
|
|
128
|
+
unless @magic == MAGIC
|
|
129
|
+
raise ArgumentError,
|
|
130
|
+
format("Invalid magic: 0x%08x (expected 0x%08x)", @magic,
|
|
131
|
+
MAGIC)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
unless @header_size >= HEADER_SIZE
|
|
135
|
+
raise ArgumentError, "Header size too small: #{@header_size}"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
unless @version == XAR_VERSION
|
|
139
|
+
raise ArgumentError, "Unsupported version: #{@version}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
unless [CKSUM_NONE, CKSUM_SHA1, CKSUM_MD5,
|
|
143
|
+
CKSUM_OTHER].include?(@checksum_algorithm)
|
|
144
|
+
raise ArgumentError,
|
|
145
|
+
"Unknown checksum algorithm: #{@checksum_algorithm}"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
if @checksum_algorithm == CKSUM_OTHER && @checksum_name.to_s.strip.empty?
|
|
149
|
+
raise ArgumentError, "Custom checksum requires checksum_name"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
true
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Check if header is valid
|
|
156
|
+
#
|
|
157
|
+
# @return [Boolean] true if valid
|
|
158
|
+
def valid?
|
|
159
|
+
validate!
|
|
160
|
+
rescue ArgumentError
|
|
161
|
+
false
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Get checksum algorithm name
|
|
165
|
+
#
|
|
166
|
+
# @return [String] Checksum algorithm name
|
|
167
|
+
def checksum_algorithm_name
|
|
168
|
+
if @checksum_algorithm == CKSUM_OTHER
|
|
169
|
+
@checksum_name || "unknown"
|
|
170
|
+
else
|
|
171
|
+
CHECKSUM_NAMES[@checksum_algorithm] || "unknown"
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Get checksum size in bytes
|
|
176
|
+
#
|
|
177
|
+
# @return [Integer] Checksum size
|
|
178
|
+
def checksum_size
|
|
179
|
+
CHECKSUM_SIZES[checksum_algorithm_name] || 0
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Check if checksum is used
|
|
183
|
+
#
|
|
184
|
+
# @return [Boolean] true if checksum is used
|
|
185
|
+
def checksum?
|
|
186
|
+
@checksum_algorithm != CKSUM_NONE
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Serialize header to binary
|
|
190
|
+
#
|
|
191
|
+
# @return [String] Binary header data
|
|
192
|
+
def to_bytes
|
|
193
|
+
data = +""
|
|
194
|
+
data << [@magic].pack("N") # 4 bytes, big-endian
|
|
195
|
+
data << [@header_size].pack("v") # 2 bytes, little-endian
|
|
196
|
+
data << [@version].pack("v") # 2 bytes, little-endian
|
|
197
|
+
data << [@toc_compressed_size].pack("Q>") # 8 bytes, big-endian
|
|
198
|
+
data << [@toc_uncompressed_size].pack("Q>") # 8 bytes, big-endian
|
|
199
|
+
data << [@checksum_algorithm].pack("N") # 4 bytes, big-endian
|
|
200
|
+
|
|
201
|
+
# Add checksum name for custom algorithms
|
|
202
|
+
if @checksum_algorithm == CKSUM_OTHER && @checksum_name
|
|
203
|
+
name_bytes = @checksum_name.to_s.encode("ASCII").ljust(36, "\x00")
|
|
204
|
+
data << name_bytes[0, 36]
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
data
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Update TOC sizes
|
|
211
|
+
#
|
|
212
|
+
# @param compressed [Integer] Compressed TOC size
|
|
213
|
+
# @param uncompressed [Integer] Uncompressed TOC size
|
|
214
|
+
# @return [Header] self for chaining
|
|
215
|
+
def update_toc_sizes(compressed, uncompressed)
|
|
216
|
+
@toc_compressed_size = compressed
|
|
217
|
+
@toc_uncompressed_size = uncompressed
|
|
218
|
+
self
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zlib"
|
|
4
|
+
require "digest"
|
|
5
|
+
require "fileutils"
|
|
6
|
+
require "stringio"
|
|
7
|
+
|
|
8
|
+
module Omnizip
|
|
9
|
+
module Formats
|
|
10
|
+
module Xar
|
|
11
|
+
# XAR archive reader
|
|
12
|
+
#
|
|
13
|
+
# Provides read access to XAR archives with support for:
|
|
14
|
+
# - Multiple compression algorithms (gzip, bzip2, lzma, xz, none)
|
|
15
|
+
# - Checksum verification
|
|
16
|
+
# - Extended attributes
|
|
17
|
+
# - Hardlinks and symlinks
|
|
18
|
+
class Reader
|
|
19
|
+
include Omnizip::Formats::Xar::Constants
|
|
20
|
+
|
|
21
|
+
attr_reader :file_path, :header, :toc, :entries
|
|
22
|
+
|
|
23
|
+
# Open a XAR archive for reading
|
|
24
|
+
#
|
|
25
|
+
# @param file_path [String] Path to XAR file
|
|
26
|
+
# @return [Reader] Reader instance
|
|
27
|
+
def self.open(file_path)
|
|
28
|
+
reader = new(file_path)
|
|
29
|
+
reader.open
|
|
30
|
+
|
|
31
|
+
if block_given?
|
|
32
|
+
begin
|
|
33
|
+
yield reader
|
|
34
|
+
ensure
|
|
35
|
+
reader.close
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
reader
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Read and list entries from XAR archive
|
|
43
|
+
#
|
|
44
|
+
# @param file_path [String] Path to XAR file
|
|
45
|
+
# @return [Array<Entry>] List of entries
|
|
46
|
+
def self.list(file_path)
|
|
47
|
+
open(file_path, &:entries) # rubocop:disable Security/Open
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Extract XAR archive to directory
|
|
51
|
+
#
|
|
52
|
+
# @param file_path [String] Path to XAR file
|
|
53
|
+
# @param output_dir [String] Output directory
|
|
54
|
+
def self.extract(file_path, output_dir)
|
|
55
|
+
open(file_path) do |reader| # rubocop:disable Security/Open
|
|
56
|
+
reader.extract_all(output_dir)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Initialize reader
|
|
61
|
+
#
|
|
62
|
+
# @param file_path [String] Path to XAR file
|
|
63
|
+
def initialize(file_path)
|
|
64
|
+
@file_path = file_path
|
|
65
|
+
@file = nil
|
|
66
|
+
@header = nil
|
|
67
|
+
@toc = nil
|
|
68
|
+
@entries = []
|
|
69
|
+
@heap_offset = 0
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Open and parse the archive
|
|
73
|
+
#
|
|
74
|
+
# @return [Reader] self
|
|
75
|
+
def open
|
|
76
|
+
@file = File.open(@file_path, "rb")
|
|
77
|
+
read_header
|
|
78
|
+
read_toc
|
|
79
|
+
self
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Close the archive
|
|
83
|
+
def close
|
|
84
|
+
@file&.close
|
|
85
|
+
@file = nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Check if archive is open
|
|
89
|
+
#
|
|
90
|
+
# @return [Boolean] true if open
|
|
91
|
+
def open?
|
|
92
|
+
!@file.nil?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Get all entries
|
|
96
|
+
#
|
|
97
|
+
# @return [Array<Entry>] List of entries
|
|
98
|
+
def list
|
|
99
|
+
@entries
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Get entry by name
|
|
103
|
+
#
|
|
104
|
+
# @param name [String] Entry name
|
|
105
|
+
# @return [Entry, nil] Entry or nil if not found
|
|
106
|
+
def get_entry(name)
|
|
107
|
+
@entries.find { |e| e.name == name }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Read entry data
|
|
111
|
+
#
|
|
112
|
+
# @param entry [Entry] Entry to read
|
|
113
|
+
# @return [String, nil] Entry data or nil if no data
|
|
114
|
+
def read_data(entry)
|
|
115
|
+
return nil unless entry.data_length&.positive?
|
|
116
|
+
return nil unless @file
|
|
117
|
+
|
|
118
|
+
@file.seek(@heap_offset + entry.data_offset)
|
|
119
|
+
# In XAR format:
|
|
120
|
+
# - data_length is the compressed (archived) size (what to read from heap)
|
|
121
|
+
# - data_size is the uncompressed (extracted) size (decompressed size)
|
|
122
|
+
compressed_data = @file.read(entry.data_length)
|
|
123
|
+
|
|
124
|
+
decompress_data(compressed_data, entry.data_encoding, entry.data_size)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Extract all entries to directory
|
|
128
|
+
#
|
|
129
|
+
# @param output_dir [String] Output directory
|
|
130
|
+
def extract_all(output_dir)
|
|
131
|
+
FileUtils.mkdir_p(output_dir)
|
|
132
|
+
|
|
133
|
+
# Sort entries to ensure directories are created first
|
|
134
|
+
sorted_entries = @entries.sort_by do |e|
|
|
135
|
+
[e.directory? ? 0 : 1, e.name]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
sorted_entries.each do |entry|
|
|
139
|
+
extract_entry(entry, output_dir)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Extract single entry to directory
|
|
144
|
+
#
|
|
145
|
+
# @param entry [Entry] Entry to extract
|
|
146
|
+
# @param output_dir [String] Output directory
|
|
147
|
+
def extract_entry(entry, output_dir)
|
|
148
|
+
full_path = File.join(output_dir, entry.name)
|
|
149
|
+
|
|
150
|
+
case entry.type
|
|
151
|
+
when TYPE_DIRECTORY
|
|
152
|
+
FileUtils.mkdir_p(full_path)
|
|
153
|
+
when TYPE_SYMLINK
|
|
154
|
+
extract_symlink(entry, full_path)
|
|
155
|
+
when TYPE_HARDLINK
|
|
156
|
+
extract_hardlink(entry, full_path, output_dir)
|
|
157
|
+
when TYPE_FILE
|
|
158
|
+
extract_file(entry, full_path)
|
|
159
|
+
when TYPE_BLOCK, TYPE_CHAR
|
|
160
|
+
extract_device(entry, full_path)
|
|
161
|
+
when TYPE_FIFO
|
|
162
|
+
extract_fifo(entry, full_path)
|
|
163
|
+
else
|
|
164
|
+
# Unknown type, try to extract as file
|
|
165
|
+
extract_file(entry, full_path) if entry.data_size&.positive?
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Set file metadata
|
|
169
|
+
set_entry_metadata(entry, full_path)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Get archive information
|
|
173
|
+
#
|
|
174
|
+
# @return [Hash] Archive info
|
|
175
|
+
def info
|
|
176
|
+
{
|
|
177
|
+
file_path: @file_path,
|
|
178
|
+
header: {
|
|
179
|
+
version: @header&.version,
|
|
180
|
+
checksum_algorithm: @header&.checksum_algorithm_name,
|
|
181
|
+
toc_compressed_size: @header&.toc_compressed_size,
|
|
182
|
+
toc_uncompressed_size: @header&.toc_uncompressed_size,
|
|
183
|
+
},
|
|
184
|
+
entry_count: @entries.size,
|
|
185
|
+
file_count: @entries.count(&:file?),
|
|
186
|
+
directory_count: @entries.count(&:directory?),
|
|
187
|
+
symlink_count: @entries.count(&:symlink?),
|
|
188
|
+
total_size: @entries.sum { |e| e.size || 0 },
|
|
189
|
+
}
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
private
|
|
193
|
+
|
|
194
|
+
# Read and parse header
|
|
195
|
+
def read_header
|
|
196
|
+
@header = Header.read(@file)
|
|
197
|
+
@header.validate!
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Read and parse TOC
|
|
201
|
+
def read_toc
|
|
202
|
+
# Read compressed TOC
|
|
203
|
+
@file.seek(@header.header_size)
|
|
204
|
+
compressed_toc = @file.read(@header.toc_compressed_size)
|
|
205
|
+
|
|
206
|
+
raise Omnizip::InvalidArchiveError, "Failed to read TOC" unless compressed_toc
|
|
207
|
+
|
|
208
|
+
# Parse TOC
|
|
209
|
+
@toc = Toc.parse(compressed_toc, @header.toc_uncompressed_size)
|
|
210
|
+
@entries = @toc.entries
|
|
211
|
+
|
|
212
|
+
# Calculate heap offset:
|
|
213
|
+
# The heap starts immediately after the compressed TOC.
|
|
214
|
+
# The TOC checksum is stored INSIDE the heap (at offset 0), not after it.
|
|
215
|
+
# File data offsets in the TOC are relative to the heap start.
|
|
216
|
+
@heap_offset = @header.header_size + @header.toc_compressed_size
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Decompress data based on encoding
|
|
220
|
+
#
|
|
221
|
+
# @param data [String] Compressed data
|
|
222
|
+
# @param encoding [String] Compression encoding
|
|
223
|
+
# @param expected_size [Integer] Expected decompressed size
|
|
224
|
+
# @return [String] Decompressed data
|
|
225
|
+
def decompress_data(data, encoding, _expected_size = nil)
|
|
226
|
+
case encoding
|
|
227
|
+
when COMPRESSION_GZIP, "application/x-gzip"
|
|
228
|
+
decompress_gzip(data)
|
|
229
|
+
when COMPRESSION_BZIP2, "application/x-bzip2"
|
|
230
|
+
decompress_bzip2(data)
|
|
231
|
+
when COMPRESSION_LZMA, "application/x-lzma"
|
|
232
|
+
decompress_lzma(data)
|
|
233
|
+
when COMPRESSION_XZ, "application/x-xz"
|
|
234
|
+
decompress_xz(data)
|
|
235
|
+
else
|
|
236
|
+
# No compression or unknown
|
|
237
|
+
data || +""
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Decompress gzip data
|
|
242
|
+
#
|
|
243
|
+
# @param data [String] Zlib compressed data (XAR uses zlib, not actual gzip)
|
|
244
|
+
# @return [String] Decompressed data
|
|
245
|
+
def decompress_gzip(data)
|
|
246
|
+
# XAR "gzip" compression is actually zlib format (with 0x78xx header)
|
|
247
|
+
# Try different decompression methods for robustness
|
|
248
|
+
|
|
249
|
+
# Method 1: Standard zlib format (with header)
|
|
250
|
+
begin
|
|
251
|
+
result = Zlib::Inflate.inflate(data)
|
|
252
|
+
return result
|
|
253
|
+
rescue Zlib::Error
|
|
254
|
+
# Continue to next method
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Method 2: Raw deflate (some implementations may use this)
|
|
258
|
+
begin
|
|
259
|
+
inf = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
|
260
|
+
result = inf.inflate(data)
|
|
261
|
+
inf.finish
|
|
262
|
+
inf.close
|
|
263
|
+
return result
|
|
264
|
+
rescue Zlib::Error
|
|
265
|
+
# Continue to next method
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Method 3: Raw deflate without finish (for truncated data)
|
|
269
|
+
begin
|
|
270
|
+
inf = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
|
271
|
+
result = inf.inflate(data)
|
|
272
|
+
inf.close
|
|
273
|
+
result
|
|
274
|
+
rescue Zlib::Error => e
|
|
275
|
+
raise Omnizip::DecompressionError, "Failed to decompress data: #{e.message}"
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Decompress bzip2 data
|
|
280
|
+
#
|
|
281
|
+
# @param data [String] Bzip2 compressed data
|
|
282
|
+
# @return [String] Decompressed data
|
|
283
|
+
def decompress_bzip2(data)
|
|
284
|
+
decompressor = Omnizip::Algorithms::Bzip2::Decompressor.new
|
|
285
|
+
decompressor.decompress(data)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Decompress LZMA data
|
|
289
|
+
#
|
|
290
|
+
# @param data [String] LZMA compressed data
|
|
291
|
+
# @return [String] Decompressed data
|
|
292
|
+
def decompress_lzma(data)
|
|
293
|
+
decoder = Omnizip::Algorithms::Lzma::Decoder.new
|
|
294
|
+
decoder.decode(data)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Decompress XZ data
|
|
298
|
+
#
|
|
299
|
+
# @param data [String] XZ compressed data
|
|
300
|
+
# @return [String] Decompressed data
|
|
301
|
+
def decompress_xz(data)
|
|
302
|
+
reader = Omnizip::Formats::Xz::StreamReader.new(StringIO.new(data))
|
|
303
|
+
reader.read
|
|
304
|
+
ensure
|
|
305
|
+
reader&.close
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Extract file
|
|
309
|
+
#
|
|
310
|
+
# @param entry [Entry] File entry
|
|
311
|
+
# @param path [String] Output path
|
|
312
|
+
def extract_file(entry, path)
|
|
313
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
314
|
+
|
|
315
|
+
data = read_data(entry)
|
|
316
|
+
return unless data
|
|
317
|
+
|
|
318
|
+
File.binwrite(path, data)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Extract symlink
|
|
322
|
+
#
|
|
323
|
+
# @param entry [Entry] Symlink entry
|
|
324
|
+
# @param path [String] Output path
|
|
325
|
+
def extract_symlink(entry, path)
|
|
326
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
327
|
+
|
|
328
|
+
target = entry.link_target
|
|
329
|
+
return unless target
|
|
330
|
+
|
|
331
|
+
File.unlink(path) if File.symlink?(path)
|
|
332
|
+
File.symlink(target, path)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Extract hardlink
|
|
336
|
+
#
|
|
337
|
+
# @param entry [Entry] Hardlink entry
|
|
338
|
+
# @param path [String] Output path
|
|
339
|
+
# @param output_dir [String] Output directory
|
|
340
|
+
def extract_hardlink(entry, path, output_dir)
|
|
341
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
342
|
+
|
|
343
|
+
target = entry.link_target
|
|
344
|
+
return unless target
|
|
345
|
+
|
|
346
|
+
target_path = File.join(output_dir, target)
|
|
347
|
+
|
|
348
|
+
# If target exists, create hardlink
|
|
349
|
+
if File.exist?(target_path)
|
|
350
|
+
FileUtils.rm_f(path)
|
|
351
|
+
File.link(target_path, path)
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Extract device node
|
|
356
|
+
#
|
|
357
|
+
# @param entry [Entry] Device entry
|
|
358
|
+
# @param path [String] Output path
|
|
359
|
+
def extract_device(entry, path)
|
|
360
|
+
# Creating device nodes requires root privileges
|
|
361
|
+
# This is a no-op on most systems
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Extract FIFO
|
|
365
|
+
#
|
|
366
|
+
# @param entry [Entry] FIFO entry
|
|
367
|
+
# @param path [String] Output path
|
|
368
|
+
def extract_fifo(entry, path)
|
|
369
|
+
# Creating FIFOs may require privileges
|
|
370
|
+
# This is a no-op on most systems
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# Set entry metadata on extracted file
|
|
374
|
+
#
|
|
375
|
+
# @param entry [Entry] Entry
|
|
376
|
+
# @param path [String] File path
|
|
377
|
+
def set_entry_metadata(entry, path)
|
|
378
|
+
return unless File.exist?(path)
|
|
379
|
+
|
|
380
|
+
# Set mode
|
|
381
|
+
File.chmod(entry.mode, path) if entry.mode&.positive?
|
|
382
|
+
|
|
383
|
+
# Set timestamps
|
|
384
|
+
if entry.mtime
|
|
385
|
+
File.utime(entry.atime || entry.mtime, entry.mtime, path)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# Set ownership (requires privileges)
|
|
389
|
+
if entry.uid && entry.gid
|
|
390
|
+
begin
|
|
391
|
+
File.chown(entry.uid, entry.gid, path)
|
|
392
|
+
rescue Errno::EPERM
|
|
393
|
+
# Ignore permission errors
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
end
|