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,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Omnizip
|
|
20
|
+
module IO
|
|
21
|
+
# Buffered input stream for efficient reading.
|
|
22
|
+
#
|
|
23
|
+
# This class provides buffered reading capabilities with methods
|
|
24
|
+
# for reading bytes, integers, and other data types efficiently.
|
|
25
|
+
class BufferedInput
|
|
26
|
+
DEFAULT_BUFFER_SIZE = 65_536
|
|
27
|
+
|
|
28
|
+
attr_reader :source, :buffer_size, :position
|
|
29
|
+
|
|
30
|
+
# Initialize buffered input.
|
|
31
|
+
#
|
|
32
|
+
# @param source [IO, #read] Input source
|
|
33
|
+
# @param buffer_size [Integer] Size of internal buffer
|
|
34
|
+
def initialize(source, buffer_size: DEFAULT_BUFFER_SIZE)
|
|
35
|
+
@source = source
|
|
36
|
+
@buffer_size = buffer_size
|
|
37
|
+
@buffer = String.new(capacity: buffer_size)
|
|
38
|
+
@buffer_pos = 0
|
|
39
|
+
@buffer_end = 0
|
|
40
|
+
@position = 0
|
|
41
|
+
@eof = false
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Read bytes from the stream.
|
|
45
|
+
#
|
|
46
|
+
# @param num_bytes [Integer] Number of bytes to read
|
|
47
|
+
# @return [String, nil] Read bytes or nil if EOF
|
|
48
|
+
def read(num_bytes)
|
|
49
|
+
return nil if @eof && @buffer_pos >= @buffer_end
|
|
50
|
+
|
|
51
|
+
result = String.new(capacity: num_bytes)
|
|
52
|
+
read_into_result(result, num_bytes)
|
|
53
|
+
result.empty? ? nil : result
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Read a single byte.
|
|
57
|
+
#
|
|
58
|
+
# @return [Integer, nil] Byte value (0-255) or nil if EOF
|
|
59
|
+
def read_byte
|
|
60
|
+
return nil if @eof && @buffer_pos >= @buffer_end
|
|
61
|
+
|
|
62
|
+
ensure_buffer_filled
|
|
63
|
+
return nil if @buffer_pos >= @buffer_end
|
|
64
|
+
|
|
65
|
+
consume_byte
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Check if at end of stream.
|
|
69
|
+
#
|
|
70
|
+
# @return [Boolean] True if at EOF
|
|
71
|
+
def eof?
|
|
72
|
+
@eof && @buffer_pos >= @buffer_end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Close the underlying source.
|
|
76
|
+
#
|
|
77
|
+
# @return [void]
|
|
78
|
+
def close
|
|
79
|
+
@source.close if @source.respond_to?(:close)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def read_into_result(result, num_bytes)
|
|
85
|
+
while result.bytesize < num_bytes && !eof?
|
|
86
|
+
copy_from_buffer(result, num_bytes)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def copy_from_buffer(result, num_bytes)
|
|
91
|
+
available = @buffer_end - @buffer_pos
|
|
92
|
+
if available.positive?
|
|
93
|
+
copy_available_bytes(result, num_bytes, available)
|
|
94
|
+
else
|
|
95
|
+
fill_buffer
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def copy_available_bytes(result, num_bytes, available)
|
|
100
|
+
to_copy = [num_bytes - result.bytesize, available].min
|
|
101
|
+
result << @buffer[@buffer_pos, to_copy]
|
|
102
|
+
@buffer_pos += to_copy
|
|
103
|
+
@position += to_copy
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def ensure_buffer_filled
|
|
107
|
+
fill_buffer if @buffer_pos >= @buffer_end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def consume_byte
|
|
111
|
+
byte = @buffer.getbyte(@buffer_pos)
|
|
112
|
+
@buffer_pos += 1
|
|
113
|
+
@position += 1
|
|
114
|
+
byte
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def fill_buffer
|
|
118
|
+
return if @eof
|
|
119
|
+
|
|
120
|
+
data = @source.read(@buffer_size)
|
|
121
|
+
update_buffer(data)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def update_buffer(data)
|
|
125
|
+
if data.nil? || data.empty?
|
|
126
|
+
mark_eof
|
|
127
|
+
else
|
|
128
|
+
update_buffer_data(data)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def mark_eof
|
|
133
|
+
@eof = true
|
|
134
|
+
@buffer = +""
|
|
135
|
+
@buffer_pos = 0
|
|
136
|
+
@buffer_end = 0
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def update_buffer_data(data)
|
|
140
|
+
@buffer = data
|
|
141
|
+
@buffer_pos = 0
|
|
142
|
+
@buffer_end = data.bytesize
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Omnizip
|
|
20
|
+
module IO
|
|
21
|
+
# Buffered output stream for efficient writing.
|
|
22
|
+
#
|
|
23
|
+
# This class provides buffered writing capabilities to minimize
|
|
24
|
+
# I/O operations and improve performance.
|
|
25
|
+
class BufferedOutput
|
|
26
|
+
DEFAULT_BUFFER_SIZE = 65_536
|
|
27
|
+
|
|
28
|
+
attr_reader :destination, :buffer_size, :position
|
|
29
|
+
|
|
30
|
+
# Initialize buffered output.
|
|
31
|
+
#
|
|
32
|
+
# @param destination [IO, #write] Output destination
|
|
33
|
+
# @param buffer_size [Integer] Size of internal buffer
|
|
34
|
+
def initialize(destination, buffer_size: DEFAULT_BUFFER_SIZE)
|
|
35
|
+
@destination = destination
|
|
36
|
+
@buffer_size = buffer_size
|
|
37
|
+
@buffer = String.new(capacity: buffer_size)
|
|
38
|
+
@position = 0
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Write data to the stream.
|
|
42
|
+
#
|
|
43
|
+
# @param data [String] Data to write
|
|
44
|
+
# @return [Integer] Number of bytes written
|
|
45
|
+
def write(data)
|
|
46
|
+
return 0 if data.nil? || data.empty?
|
|
47
|
+
|
|
48
|
+
bytes_written = 0
|
|
49
|
+
offset = 0
|
|
50
|
+
|
|
51
|
+
while offset < data.bytesize
|
|
52
|
+
offset = write_chunk(data, offset)
|
|
53
|
+
bytes_written = offset
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
bytes_written
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Write a single byte.
|
|
60
|
+
#
|
|
61
|
+
# @param byte [Integer] Byte value (0-255)
|
|
62
|
+
# @return [Integer] Number of bytes written (1)
|
|
63
|
+
def write_byte(byte)
|
|
64
|
+
@buffer << byte.chr
|
|
65
|
+
@position += 1
|
|
66
|
+
|
|
67
|
+
flush if @buffer.bytesize >= @buffer_size
|
|
68
|
+
|
|
69
|
+
1
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Flush buffered data to destination.
|
|
73
|
+
#
|
|
74
|
+
# @return [void]
|
|
75
|
+
def flush
|
|
76
|
+
return if @buffer.empty?
|
|
77
|
+
|
|
78
|
+
@destination.write(@buffer)
|
|
79
|
+
@buffer.clear
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Close the stream and flush remaining data.
|
|
83
|
+
#
|
|
84
|
+
# @return [void]
|
|
85
|
+
def close
|
|
86
|
+
flush
|
|
87
|
+
@destination.close if @destination.respond_to?(:close)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def write_chunk(data, offset)
|
|
93
|
+
available = @buffer_size - @buffer.bytesize
|
|
94
|
+
to_write = [data.bytesize - offset, available].min
|
|
95
|
+
|
|
96
|
+
@buffer << data[offset, to_write]
|
|
97
|
+
@position += to_write
|
|
98
|
+
|
|
99
|
+
flush if @buffer.bytesize >= @buffer_size
|
|
100
|
+
|
|
101
|
+
offset + to_write
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require "stringio"
|
|
20
|
+
|
|
21
|
+
module Omnizip
|
|
22
|
+
module IO
|
|
23
|
+
# Manages I/O operations and wraps various source types.
|
|
24
|
+
#
|
|
25
|
+
# This class provides a unified interface for different I/O sources
|
|
26
|
+
# including files, IO objects, and strings.
|
|
27
|
+
class StreamManager
|
|
28
|
+
attr_reader :source
|
|
29
|
+
|
|
30
|
+
# Initialize stream manager.
|
|
31
|
+
#
|
|
32
|
+
# @param source [String, IO, File, StringIO] Input source
|
|
33
|
+
# @param mode [String] File mode (for file paths)
|
|
34
|
+
def initialize(source, mode: "rb")
|
|
35
|
+
@source = normalize_source(source, mode)
|
|
36
|
+
@owned = source.is_a?(String) && File.exist?(source)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Create a buffered input from the source.
|
|
40
|
+
#
|
|
41
|
+
# @param buffer_size [Integer] Buffer size
|
|
42
|
+
# @return [BufferedInput] Buffered input stream
|
|
43
|
+
def buffered_input(buffer_size: BufferedInput::DEFAULT_BUFFER_SIZE)
|
|
44
|
+
BufferedInput.new(@source, buffer_size: buffer_size)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Create a buffered output to the source.
|
|
48
|
+
#
|
|
49
|
+
# @param buffer_size [Integer] Buffer size
|
|
50
|
+
# @return [BufferedOutput] Buffered output stream
|
|
51
|
+
def buffered_output(buffer_size: BufferedOutput::DEFAULT_BUFFER_SIZE)
|
|
52
|
+
BufferedOutput.new(@source, buffer_size: buffer_size)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Read all data from source.
|
|
56
|
+
#
|
|
57
|
+
# @return [String] All data from source
|
|
58
|
+
def read_all
|
|
59
|
+
@source.read
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Write data to source.
|
|
63
|
+
#
|
|
64
|
+
# @param data [String] Data to write
|
|
65
|
+
# @return [Integer] Number of bytes written
|
|
66
|
+
def write(data)
|
|
67
|
+
@source.write(data)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Close the underlying source if owned.
|
|
71
|
+
#
|
|
72
|
+
# @return [void]
|
|
73
|
+
def close
|
|
74
|
+
@source.close if @owned && @source.respond_to?(:close)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Check if source is at end.
|
|
78
|
+
#
|
|
79
|
+
# @return [Boolean] True if at EOF
|
|
80
|
+
def eof?
|
|
81
|
+
@source.eof? if @source.respond_to?(:eof?)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def normalize_source(source, mode)
|
|
87
|
+
case source
|
|
88
|
+
when String
|
|
89
|
+
normalize_string_source(source, mode)
|
|
90
|
+
when IO, File, StringIO
|
|
91
|
+
source
|
|
92
|
+
else
|
|
93
|
+
validate_io_interface(source)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def normalize_string_source(source, mode)
|
|
98
|
+
if File.exist?(source)
|
|
99
|
+
File.open(source, mode)
|
|
100
|
+
else
|
|
101
|
+
StringIO.new(source)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def validate_io_interface(source)
|
|
106
|
+
if source.respond_to?(:read) || source.respond_to?(:write)
|
|
107
|
+
source
|
|
108
|
+
else
|
|
109
|
+
raise ArgumentError,
|
|
110
|
+
"Invalid source type: #{source.class}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module LinkHandler
|
|
5
|
+
# Model for hard links
|
|
6
|
+
class HardLink
|
|
7
|
+
attr_reader :target, :path, :inode
|
|
8
|
+
|
|
9
|
+
def initialize(target:, path: nil, inode: nil)
|
|
10
|
+
@target = target
|
|
11
|
+
@path = path
|
|
12
|
+
@inode = inode
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Create the hard link on the filesystem
|
|
16
|
+
def create(link_path)
|
|
17
|
+
LinkHandler.create_hardlink(@target, link_path)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Serialize for archive storage
|
|
21
|
+
def serialize
|
|
22
|
+
{
|
|
23
|
+
target: @target,
|
|
24
|
+
inode: @inode,
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Deserialize from archive storage
|
|
29
|
+
def self.deserialize(data, path: nil)
|
|
30
|
+
if data.is_a?(Hash)
|
|
31
|
+
new(
|
|
32
|
+
target: data[:target] || data["target"],
|
|
33
|
+
path: path,
|
|
34
|
+
inode: data[:inode] || data["inode"],
|
|
35
|
+
)
|
|
36
|
+
else
|
|
37
|
+
# Legacy format: just the target path
|
|
38
|
+
new(target: data, path: path)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Check if this is a symbolic link
|
|
43
|
+
def symlink?
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Check if this is a hard link
|
|
48
|
+
def hardlink?
|
|
49
|
+
true
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Get the link type as string
|
|
53
|
+
def link_type
|
|
54
|
+
"hardlink"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Convert to hash representation
|
|
58
|
+
def to_h
|
|
59
|
+
{
|
|
60
|
+
type: :hardlink,
|
|
61
|
+
target: @target,
|
|
62
|
+
path: @path,
|
|
63
|
+
inode: @inode,
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# String representation
|
|
68
|
+
def to_s
|
|
69
|
+
"#{@path} -> #{@target} (hard link)"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Inspect representation
|
|
73
|
+
def inspect
|
|
74
|
+
"#<Omnizip::LinkHandler::HardLink target=#{@target.inspect} " \
|
|
75
|
+
"path=#{@path.inspect} inode=#{@inode}>"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module LinkHandler
|
|
5
|
+
# Model for symbolic links
|
|
6
|
+
class SymbolicLink
|
|
7
|
+
attr_reader :target, :path
|
|
8
|
+
|
|
9
|
+
# Unix permissions for symbolic links (0120777)
|
|
10
|
+
SYMLINK_PERMISSIONS = 0o120777
|
|
11
|
+
|
|
12
|
+
def initialize(target:, path: nil)
|
|
13
|
+
@target = target
|
|
14
|
+
@path = path
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Create the symbolic link on the filesystem
|
|
18
|
+
def create(link_path)
|
|
19
|
+
LinkHandler.create_symlink(@target, link_path)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Get Unix permissions for symbolic links
|
|
23
|
+
def permissions
|
|
24
|
+
SYMLINK_PERMISSIONS
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Serialize for archive storage (returns the target path)
|
|
28
|
+
def serialize
|
|
29
|
+
@target
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Deserialize from archive storage
|
|
33
|
+
def self.deserialize(target_data, path: nil)
|
|
34
|
+
new(target: target_data, path: path)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Check if this is a symbolic link
|
|
38
|
+
def symlink?
|
|
39
|
+
true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Check if this is a hard link
|
|
43
|
+
def hardlink?
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get the link type as string
|
|
48
|
+
def link_type
|
|
49
|
+
"symlink"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Convert to hash representation
|
|
53
|
+
def to_h
|
|
54
|
+
{
|
|
55
|
+
type: :symlink,
|
|
56
|
+
target: @target,
|
|
57
|
+
path: @path,
|
|
58
|
+
permissions: permissions,
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# String representation
|
|
63
|
+
def to_s
|
|
64
|
+
"#{@path} -> #{@target} (symlink)"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Inspect representation
|
|
68
|
+
def inspect
|
|
69
|
+
"#<Omnizip::LinkHandler::SymbolicLink target=#{@target.inspect} " \
|
|
70
|
+
"path=#{@path.inspect}>"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "link_handler/symbolic_link"
|
|
4
|
+
require_relative "link_handler/hard_link"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
# Handles symbolic and hard link operations with platform detection
|
|
8
|
+
module LinkHandler
|
|
9
|
+
class << self
|
|
10
|
+
# Check if the platform supports symbolic links
|
|
11
|
+
def supported?
|
|
12
|
+
!windows_platform?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Check if symbolic links are supported
|
|
16
|
+
def symlink_supported?
|
|
17
|
+
File.respond_to?(:symlink) && supported?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Check if hard links are supported
|
|
21
|
+
def hardlink_supported?
|
|
22
|
+
File.respond_to?(:link) && supported?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Detect if a path is a symbolic link
|
|
26
|
+
def symlink?(path)
|
|
27
|
+
return false unless symlink_supported?
|
|
28
|
+
|
|
29
|
+
File.symlink?(path)
|
|
30
|
+
rescue StandardError
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Detect if a path is a hard link
|
|
35
|
+
def hardlink?(path)
|
|
36
|
+
return false unless hardlink_supported?
|
|
37
|
+
return false unless File.exist?(path)
|
|
38
|
+
return false if File.directory?(path)
|
|
39
|
+
|
|
40
|
+
stat = File.stat(path)
|
|
41
|
+
stat.nlink > 1
|
|
42
|
+
rescue StandardError
|
|
43
|
+
false
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Detect the type of link (or nil if not a link)
|
|
47
|
+
def detect_link(path)
|
|
48
|
+
return nil unless supported?
|
|
49
|
+
return :symlink if symlink?(path)
|
|
50
|
+
return :hardlink if hardlink?(path)
|
|
51
|
+
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Create a symbolic link
|
|
56
|
+
def create_symlink(target, link_path)
|
|
57
|
+
unless symlink_supported?
|
|
58
|
+
raise Omnizip::Error,
|
|
59
|
+
"Symbolic links are not supported on #{RUBY_PLATFORM}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
FileUtils.mkdir_p(File.dirname(link_path))
|
|
63
|
+
File.symlink(target, link_path)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Create a hard link
|
|
67
|
+
def create_hardlink(target, link_path)
|
|
68
|
+
unless hardlink_supported?
|
|
69
|
+
raise Omnizip::Error,
|
|
70
|
+
"Hard links are not supported on #{RUBY_PLATFORM}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
FileUtils.mkdir_p(File.dirname(link_path))
|
|
74
|
+
File.link(target, link_path)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Read the target of a symbolic link
|
|
78
|
+
def read_link_target(link_path)
|
|
79
|
+
unless symlink_supported?
|
|
80
|
+
raise Omnizip::Error,
|
|
81
|
+
"Symbolic links are not supported on #{RUBY_PLATFORM}"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
File.readlink(link_path)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Get inode number for hard link tracking
|
|
88
|
+
def inode_number(path)
|
|
89
|
+
return nil unless hardlink_supported?
|
|
90
|
+
return nil unless File.exist?(path)
|
|
91
|
+
|
|
92
|
+
File.stat(path).ino
|
|
93
|
+
rescue StandardError
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Create a SymbolicLink instance from a filesystem path
|
|
98
|
+
def symbolic_link_from_path(path)
|
|
99
|
+
return nil unless symlink?(path)
|
|
100
|
+
|
|
101
|
+
target = read_link_target(path)
|
|
102
|
+
SymbolicLink.new(target: target, path: path)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Create a HardLink instance from a filesystem path
|
|
106
|
+
def hard_link_from_path(path, original_path)
|
|
107
|
+
return nil unless hardlink?(path)
|
|
108
|
+
|
|
109
|
+
HardLink.new(
|
|
110
|
+
target: original_path,
|
|
111
|
+
path: path,
|
|
112
|
+
inode: inode_number(path),
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
# Check if running on Windows platform
|
|
119
|
+
def windows_platform?
|
|
120
|
+
RUBY_PLATFORM.match?(/mswin|mingw|cygwin/)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|