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,320 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "time"
|
|
4
|
+
require_relative "../iso"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Formats
|
|
8
|
+
module Iso
|
|
9
|
+
# ISO 9660 Volume Descriptor Builder
|
|
10
|
+
#
|
|
11
|
+
# Builds primary and supplementary volume descriptors for ISO images.
|
|
12
|
+
# Handles proper encoding of volume metadata and root directory information.
|
|
13
|
+
class VolumeBuilder
|
|
14
|
+
# @return [String] Volume identifier
|
|
15
|
+
attr_reader :volume_id
|
|
16
|
+
|
|
17
|
+
# @return [String] System identifier
|
|
18
|
+
attr_reader :system_id
|
|
19
|
+
|
|
20
|
+
# @return [String] Publisher
|
|
21
|
+
attr_reader :publisher
|
|
22
|
+
|
|
23
|
+
# @return [String] Preparer
|
|
24
|
+
attr_reader :preparer
|
|
25
|
+
|
|
26
|
+
# @return [String] Application
|
|
27
|
+
attr_reader :application
|
|
28
|
+
|
|
29
|
+
# @return [Integer] ISO level
|
|
30
|
+
attr_reader :level
|
|
31
|
+
|
|
32
|
+
# @return [Boolean] Rock Ridge enabled
|
|
33
|
+
attr_reader :rock_ridge
|
|
34
|
+
|
|
35
|
+
# @return [Boolean] Joliet enabled
|
|
36
|
+
attr_reader :joliet
|
|
37
|
+
|
|
38
|
+
# Initialize volume builder
|
|
39
|
+
#
|
|
40
|
+
# @param options [Hash] Builder options
|
|
41
|
+
def initialize(options = {})
|
|
42
|
+
@volume_id = options.fetch(:volume_id, "OMNIZIP")
|
|
43
|
+
@system_id = options.fetch(:system_id, "LINUX")
|
|
44
|
+
@publisher = options.fetch(:publisher, "")
|
|
45
|
+
@preparer = options.fetch(:preparer, "")
|
|
46
|
+
@application = options.fetch(:application, "OMNIZIP")
|
|
47
|
+
@level = options.fetch(:level, 2)
|
|
48
|
+
@rock_ridge = options.fetch(:rock_ridge, false)
|
|
49
|
+
@joliet = options.fetch(:joliet, false)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Build primary volume descriptor
|
|
53
|
+
#
|
|
54
|
+
# @param root_dir [Hash] Root directory information
|
|
55
|
+
# @return [String] Primary VD sector (2048 bytes)
|
|
56
|
+
def build_primary(root_dir)
|
|
57
|
+
sector = +""
|
|
58
|
+
|
|
59
|
+
# Byte 0: Volume descriptor type (1 = Primary)
|
|
60
|
+
sector << [Iso::VD_PRIMARY].pack("C")
|
|
61
|
+
|
|
62
|
+
# Bytes 1-5: Standard identifier "CD001"
|
|
63
|
+
sector << VolumeDescriptor::ISO_IDENTIFIER
|
|
64
|
+
|
|
65
|
+
# Byte 6: Version (1)
|
|
66
|
+
sector << [1].pack("C")
|
|
67
|
+
|
|
68
|
+
# Byte 7: Unused (0)
|
|
69
|
+
sector << "\x00"
|
|
70
|
+
|
|
71
|
+
# Bytes 8-39: System identifier (a-characters, space-padded)
|
|
72
|
+
sector << pad_a_string(@system_id, 32)
|
|
73
|
+
|
|
74
|
+
# Bytes 40-71: Volume identifier (d-characters, space-padded)
|
|
75
|
+
sector << pad_d_string(@volume_id, 32)
|
|
76
|
+
|
|
77
|
+
# Bytes 72-79: Unused (zeros)
|
|
78
|
+
sector << ("\x00" * 8)
|
|
79
|
+
|
|
80
|
+
# Bytes 80-87: Volume space size (both-endian)
|
|
81
|
+
volume_sectors = root_dir[:total_sectors] || 100
|
|
82
|
+
sector << [volume_sectors].pack("V") # Little-endian
|
|
83
|
+
sector << [volume_sectors].pack("N") # Big-endian
|
|
84
|
+
|
|
85
|
+
# Bytes 88-119: Unused (zeros)
|
|
86
|
+
sector << ("\x00" * 32)
|
|
87
|
+
|
|
88
|
+
# Bytes 120-123: Volume set size (both-endian)
|
|
89
|
+
sector << [1].pack("v")
|
|
90
|
+
sector << [1].pack("n")
|
|
91
|
+
|
|
92
|
+
# Bytes 124-127: Volume sequence number (both-endian)
|
|
93
|
+
sector << [1].pack("v")
|
|
94
|
+
sector << [1].pack("n")
|
|
95
|
+
|
|
96
|
+
# Bytes 128-131: Logical block size (both-endian)
|
|
97
|
+
sector << [Iso::SECTOR_SIZE].pack("v")
|
|
98
|
+
sector << [Iso::SECTOR_SIZE].pack("n")
|
|
99
|
+
|
|
100
|
+
# Bytes 132-139: Path table size (both-endian)
|
|
101
|
+
path_table_size = root_dir[:path_table_size] || 10
|
|
102
|
+
sector << [path_table_size].pack("V")
|
|
103
|
+
sector << [path_table_size].pack("N")
|
|
104
|
+
|
|
105
|
+
# Bytes 140-143: Location of type L path table
|
|
106
|
+
sector << [root_dir[:path_table_location] || 19].pack("V")
|
|
107
|
+
|
|
108
|
+
# Bytes 144-147: Location of optional type L path table
|
|
109
|
+
sector << [0].pack("V")
|
|
110
|
+
|
|
111
|
+
# Bytes 148-151: Location of type M path table
|
|
112
|
+
sector << [root_dir[:path_table_location_be] || 20].pack("N")
|
|
113
|
+
|
|
114
|
+
# Bytes 152-155: Location of optional type M path table
|
|
115
|
+
sector << [0].pack("N")
|
|
116
|
+
|
|
117
|
+
# Bytes 156-189: Root directory record (34 bytes)
|
|
118
|
+
sector << build_root_directory_record(root_dir)
|
|
119
|
+
|
|
120
|
+
# Bytes 190-317: Volume set identifier
|
|
121
|
+
sector << pad_d_string("", 128)
|
|
122
|
+
|
|
123
|
+
# Bytes 318-445: Publisher identifier
|
|
124
|
+
sector << pad_a_string(@publisher, 128)
|
|
125
|
+
|
|
126
|
+
# Bytes 446-573: Data preparer identifier
|
|
127
|
+
sector << pad_a_string(@preparer, 128)
|
|
128
|
+
|
|
129
|
+
# Bytes 574-701: Application identifier
|
|
130
|
+
sector << pad_a_string(@application, 128)
|
|
131
|
+
|
|
132
|
+
# Bytes 702-738: Copyright file identifier
|
|
133
|
+
sector << pad_d_string("", 37)
|
|
134
|
+
|
|
135
|
+
# Bytes 739-775: Abstract file identifier
|
|
136
|
+
sector << pad_d_string("", 37)
|
|
137
|
+
|
|
138
|
+
# Bytes 776-812: Bibliographic file identifier
|
|
139
|
+
sector << pad_d_string("", 37)
|
|
140
|
+
|
|
141
|
+
# Bytes 813-829: Volume creation date/time
|
|
142
|
+
now = Time.now
|
|
143
|
+
sector << encode_volume_datetime(now)
|
|
144
|
+
|
|
145
|
+
# Bytes 830-846: Volume modification date/time
|
|
146
|
+
sector << encode_volume_datetime(now)
|
|
147
|
+
|
|
148
|
+
# Bytes 847-863: Volume expiration date/time (not set)
|
|
149
|
+
sector << encode_volume_datetime(nil)
|
|
150
|
+
|
|
151
|
+
# Bytes 864-880: Volume effective date/time (not set)
|
|
152
|
+
sector << encode_volume_datetime(nil)
|
|
153
|
+
|
|
154
|
+
# Byte 881: File structure version (1)
|
|
155
|
+
sector << [1].pack("C")
|
|
156
|
+
|
|
157
|
+
# Byte 882: Unused (0)
|
|
158
|
+
sector << "\x00"
|
|
159
|
+
|
|
160
|
+
# Bytes 883-1395: Application use
|
|
161
|
+
sector << ("\x00" * 513)
|
|
162
|
+
|
|
163
|
+
# Bytes 1396-2047: Reserved
|
|
164
|
+
sector << ("\x00" * 652)
|
|
165
|
+
|
|
166
|
+
sector
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Build Joliet supplementary volume descriptor
|
|
170
|
+
#
|
|
171
|
+
# @param root_dir [Hash] Root directory information
|
|
172
|
+
# @return [String] Joliet SVD sector (2048 bytes)
|
|
173
|
+
def build_joliet(root_dir)
|
|
174
|
+
# Joliet is similar to primary VD but with:
|
|
175
|
+
# - Type = 2 (supplementary)
|
|
176
|
+
# - UCS-2 encoding for strings
|
|
177
|
+
# - Escape sequences for character set
|
|
178
|
+
|
|
179
|
+
sector = build_primary(root_dir)
|
|
180
|
+
|
|
181
|
+
# Modify type to supplementary
|
|
182
|
+
sector.setbyte(0, Iso::VD_SUPPLEMENTARY)
|
|
183
|
+
|
|
184
|
+
# Add escape sequences for UCS-2
|
|
185
|
+
# Bytes 88-90: %/@ %/C %/E for levels 1, 2, 3
|
|
186
|
+
sector.setbyte(88, 0x25) # '%'
|
|
187
|
+
sector.setbyte(89, 0x2F) # '/'
|
|
188
|
+
sector.setbyte(90, 0x45) # 'E'
|
|
189
|
+
|
|
190
|
+
# Convert volume ID to UCS-2
|
|
191
|
+
volume_id_ucs2 = @volume_id.encode("UTF-16BE")
|
|
192
|
+
padded_volume_id = pad_string(volume_id_ucs2,
|
|
193
|
+
32).force_encoding("ASCII-8BIT")
|
|
194
|
+
|
|
195
|
+
# Replace bytes 40-71 with UCS-2 volume ID
|
|
196
|
+
32.times do |i|
|
|
197
|
+
sector.setbyte(40 + i, padded_volume_id.getbyte(i))
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
sector
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
private
|
|
204
|
+
|
|
205
|
+
# Build root directory record
|
|
206
|
+
#
|
|
207
|
+
# @param root_dir [Hash] Root directory info
|
|
208
|
+
# @return [String] 34-byte directory record
|
|
209
|
+
def build_root_directory_record(root_dir)
|
|
210
|
+
record = +""
|
|
211
|
+
|
|
212
|
+
# Length of record (34 bytes for root)
|
|
213
|
+
record << [34].pack("C")
|
|
214
|
+
|
|
215
|
+
# Extended attribute length (0)
|
|
216
|
+
record << [0].pack("C")
|
|
217
|
+
|
|
218
|
+
# Location of extent (both-endian)
|
|
219
|
+
location = root_dir[:location] || 21
|
|
220
|
+
record << [location].pack("V")
|
|
221
|
+
record << [location].pack("N")
|
|
222
|
+
|
|
223
|
+
# Data length (both-endian)
|
|
224
|
+
data_length = root_dir[:size] || Iso::SECTOR_SIZE
|
|
225
|
+
record << [data_length].pack("V")
|
|
226
|
+
record << [data_length].pack("N")
|
|
227
|
+
|
|
228
|
+
# Recording date
|
|
229
|
+
record << encode_record_datetime(Time.now)
|
|
230
|
+
|
|
231
|
+
# Flags (directory)
|
|
232
|
+
record << [Iso::FLAG_DIRECTORY].pack("C")
|
|
233
|
+
|
|
234
|
+
# File unit size, interleave gap
|
|
235
|
+
record << [0, 0].pack("C2")
|
|
236
|
+
|
|
237
|
+
# Volume sequence number (both-endian)
|
|
238
|
+
record << [1].pack("v")
|
|
239
|
+
record << [1].pack("n")
|
|
240
|
+
|
|
241
|
+
# File identifier length (1 for root)
|
|
242
|
+
record << [1].pack("C")
|
|
243
|
+
|
|
244
|
+
# File identifier (0x00 for root)
|
|
245
|
+
record << "\x00"
|
|
246
|
+
|
|
247
|
+
record
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Encode volume date/time (17-byte format)
|
|
251
|
+
#
|
|
252
|
+
# @param time [Time, nil] Time to encode
|
|
253
|
+
# @return [String] 17-byte encoded time
|
|
254
|
+
def encode_volume_datetime(time)
|
|
255
|
+
if time.nil?
|
|
256
|
+
# All zeros for unset time
|
|
257
|
+
return "#{'0' * 16}\u0000"
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
format(
|
|
261
|
+
"%04d%02d%02d%02d%02d%02d%02d",
|
|
262
|
+
time.year,
|
|
263
|
+
time.month,
|
|
264
|
+
time.day,
|
|
265
|
+
time.hour,
|
|
266
|
+
time.min,
|
|
267
|
+
time.sec,
|
|
268
|
+
0, # Centiseconds
|
|
269
|
+
) + [0].pack("c") # GMT offset
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Encode recording date/time (7-byte format)
|
|
273
|
+
#
|
|
274
|
+
# @param time [Time] Time to encode
|
|
275
|
+
# @return [String] 7-byte encoded time
|
|
276
|
+
def encode_record_datetime(time)
|
|
277
|
+
[
|
|
278
|
+
time.year - 1900,
|
|
279
|
+
time.month,
|
|
280
|
+
time.day,
|
|
281
|
+
time.hour,
|
|
282
|
+
time.min,
|
|
283
|
+
time.sec,
|
|
284
|
+
0, # GMT offset
|
|
285
|
+
].pack("C7")
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Pad string with spaces (a-characters)
|
|
289
|
+
#
|
|
290
|
+
# @param str [String] String to pad
|
|
291
|
+
# @param length [Integer] Target length
|
|
292
|
+
# @return [String] Padded string
|
|
293
|
+
def pad_a_string(str, length)
|
|
294
|
+
str = str[0, length] if str.bytesize > length
|
|
295
|
+
str + (" " * (length - str.bytesize))
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Pad string with spaces (d-characters)
|
|
299
|
+
#
|
|
300
|
+
# @param str [String] String to pad
|
|
301
|
+
# @param length [Integer] Target length
|
|
302
|
+
# @return [String] Padded string
|
|
303
|
+
def pad_d_string(str, length)
|
|
304
|
+
pad_a_string(str, length)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Pad generic string
|
|
308
|
+
#
|
|
309
|
+
# @param str [String] String to pad
|
|
310
|
+
# @param length [Integer] Target length
|
|
311
|
+
# @return [String] Padded string
|
|
312
|
+
def pad_string(str, length)
|
|
313
|
+
str = str[0, length] if str.bytesize > length
|
|
314
|
+
padding = "\x00".encode(str.encoding) * (length - str.bytesize)
|
|
315
|
+
str + padding
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module Iso
|
|
6
|
+
# ISO 9660 Volume Descriptor
|
|
7
|
+
# Represents the primary volume descriptor containing metadata
|
|
8
|
+
class VolumeDescriptor
|
|
9
|
+
attr_reader :type, :identifier, :version, :volume_identifier,
|
|
10
|
+
:volume_space_size, :volume_set_size, :volume_sequence_number,
|
|
11
|
+
:logical_block_size, :path_table_size, :path_table_location,
|
|
12
|
+
:root_directory_record, :volume_set_identifier,
|
|
13
|
+
:publisher_identifier, :preparer_identifier,
|
|
14
|
+
:application_identifier, :creation_date, :modification_date,
|
|
15
|
+
:system_identifier
|
|
16
|
+
|
|
17
|
+
# Standard identifier for ISO 9660
|
|
18
|
+
ISO_IDENTIFIER = "CD001"
|
|
19
|
+
|
|
20
|
+
# Parse volume descriptor from binary data
|
|
21
|
+
#
|
|
22
|
+
# @param data [String] Binary sector data (2048 bytes)
|
|
23
|
+
# @return [VolumeDescriptor] Parsed descriptor
|
|
24
|
+
def self.parse(data)
|
|
25
|
+
new.tap { |vd| vd.parse(data) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Parse descriptor data
|
|
29
|
+
#
|
|
30
|
+
# @param data [String] Binary data
|
|
31
|
+
def parse(data)
|
|
32
|
+
raise "Invalid volume descriptor size" unless data.bytesize >= 2048
|
|
33
|
+
|
|
34
|
+
# Byte 0: Volume descriptor type
|
|
35
|
+
@type = data.getbyte(0)
|
|
36
|
+
|
|
37
|
+
# Bytes 1-5: Standard identifier "CD001"
|
|
38
|
+
@identifier = data[1, 5]
|
|
39
|
+
unless @identifier == ISO_IDENTIFIER
|
|
40
|
+
raise "Invalid ISO identifier: expected #{ISO_IDENTIFIER}, got #{@identifier}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Byte 6: Version (should be 1)
|
|
44
|
+
@version = data.getbyte(6)
|
|
45
|
+
|
|
46
|
+
# Parse based on type
|
|
47
|
+
case @type
|
|
48
|
+
when Iso::VD_PRIMARY
|
|
49
|
+
parse_primary_volume_descriptor(data)
|
|
50
|
+
when Iso::VD_TERMINATOR
|
|
51
|
+
# Terminator has no additional data
|
|
52
|
+
else
|
|
53
|
+
# Skip other types for now
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Check if this is a primary volume descriptor
|
|
58
|
+
#
|
|
59
|
+
# @return [Boolean] true if primary VD
|
|
60
|
+
def primary?
|
|
61
|
+
@type == Iso::VD_PRIMARY
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Check if this is a terminator
|
|
65
|
+
#
|
|
66
|
+
# @return [Boolean] true if terminator
|
|
67
|
+
def terminator?
|
|
68
|
+
@type == Iso::VD_TERMINATOR
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
# Parse primary volume descriptor fields
|
|
74
|
+
#
|
|
75
|
+
# @param data [String] Binary data
|
|
76
|
+
def parse_primary_volume_descriptor(data)
|
|
77
|
+
# Byte 7: Unused (0)
|
|
78
|
+
# Bytes 8-39: System identifier
|
|
79
|
+
@system_identifier = data[8, 32].strip
|
|
80
|
+
|
|
81
|
+
# Bytes 40-71: Volume identifier
|
|
82
|
+
@volume_identifier = data[40, 32].strip
|
|
83
|
+
|
|
84
|
+
# Bytes 72-79: Unused (zeros)
|
|
85
|
+
|
|
86
|
+
# Bytes 80-87: Volume space size (both-endian)
|
|
87
|
+
@volume_space_size = data[80, 4].unpack1("V")
|
|
88
|
+
|
|
89
|
+
# Bytes 88-119: Unused (zeros)
|
|
90
|
+
|
|
91
|
+
# Bytes 120-123: Volume set size (both-endian)
|
|
92
|
+
@volume_set_size = data[120, 2].unpack1("v")
|
|
93
|
+
|
|
94
|
+
# Bytes 124-127: Volume sequence number (both-endian)
|
|
95
|
+
@volume_sequence_number = data[124, 2].unpack1("v")
|
|
96
|
+
|
|
97
|
+
# Bytes 128-131: Logical block size (both-endian)
|
|
98
|
+
@logical_block_size = data[128, 2].unpack1("v")
|
|
99
|
+
|
|
100
|
+
# Bytes 132-139: Path table size (both-endian)
|
|
101
|
+
@path_table_size = data[132, 4].unpack1("V")
|
|
102
|
+
|
|
103
|
+
# Bytes 140-143: Path table location (little-endian)
|
|
104
|
+
@path_table_location = data[140, 4].unpack1("V")
|
|
105
|
+
|
|
106
|
+
# Bytes 144-147: Optional path table location
|
|
107
|
+
# Bytes 148-151: Path table location (big-endian)
|
|
108
|
+
# Bytes 152-155: Optional path table location
|
|
109
|
+
|
|
110
|
+
# Bytes 156-189: Root directory record (34 bytes)
|
|
111
|
+
@root_directory_record = DirectoryRecord.parse(data[156, 34])
|
|
112
|
+
|
|
113
|
+
# Bytes 190-317: Volume set identifier
|
|
114
|
+
@volume_set_identifier = data[190, 128].strip
|
|
115
|
+
|
|
116
|
+
# Bytes 318-445: Publisher identifier
|
|
117
|
+
@publisher_identifier = data[318, 128].strip
|
|
118
|
+
|
|
119
|
+
# Bytes 446-573: Data preparer identifier
|
|
120
|
+
@preparer_identifier = data[446, 128].strip
|
|
121
|
+
|
|
122
|
+
# Bytes 574-701: Application identifier
|
|
123
|
+
@application_identifier = data[574, 128].strip
|
|
124
|
+
|
|
125
|
+
# Bytes 702-738: Copyright file identifier
|
|
126
|
+
# Bytes 739-775: Abstract file identifier
|
|
127
|
+
# Bytes 776-812: Bibliographic file identifier
|
|
128
|
+
|
|
129
|
+
# Bytes 813-829: Volume creation date/time
|
|
130
|
+
@creation_date = parse_datetime(data[813, 17])
|
|
131
|
+
|
|
132
|
+
# Bytes 830-846: Volume modification date/time
|
|
133
|
+
@modification_date = parse_datetime(data[830, 17])
|
|
134
|
+
|
|
135
|
+
# Bytes 847-863: Volume expiration date/time
|
|
136
|
+
# Bytes 864-880: Volume effective date/time
|
|
137
|
+
|
|
138
|
+
# Byte 881: File structure version
|
|
139
|
+
# Bytes 882-1395: Application use
|
|
140
|
+
# Bytes 1396-2047: Reserved
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Parse ISO 9660 datetime format
|
|
144
|
+
#
|
|
145
|
+
# @param data [String] 17-byte datetime string
|
|
146
|
+
# @return [Time, nil] Parsed time or nil if invalid
|
|
147
|
+
def parse_datetime(data)
|
|
148
|
+
return nil if data.nil? || data.bytesize < 17
|
|
149
|
+
|
|
150
|
+
year = data[0, 4].to_i
|
|
151
|
+
month = data[4, 2].to_i
|
|
152
|
+
day = data[6, 2].to_i
|
|
153
|
+
hour = data[8, 2].to_i
|
|
154
|
+
minute = data[10, 2].to_i
|
|
155
|
+
second = data[12, 2].to_i
|
|
156
|
+
# Centiseconds at 14-15 (ignored)
|
|
157
|
+
# Timezone offset at 16 (ignored for now)
|
|
158
|
+
|
|
159
|
+
return nil if year.zero?
|
|
160
|
+
|
|
161
|
+
Time.new(year, month, day, hour, minute, second)
|
|
162
|
+
rescue ArgumentError
|
|
163
|
+
nil
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|