omnizip 0.4.7-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +293 -0
- data/CHANGELOG.md +1647 -0
- data/CONTEXT.md +68 -0
- data/COPYING +502 -0
- data/Gemfile +19 -0
- data/LICENSE +12 -0
- data/README.adoc +1327 -0
- data/Rakefile +15 -0
- data/TODO.refactor/00-overview.md +67 -0
- data/TODO.refactor/01-registry-base-class.md +81 -0
- data/TODO.refactor/02-error-hierarchy.md +57 -0
- data/TODO.refactor/03-autoload-entry-point.md +69 -0
- data/TODO.refactor/04-filter-base-consolidation.md +49 -0
- data/TODO.refactor/05-send-private-methods.md +64 -0
- data/TODO.refactor/06-instance-variable-access.md +69 -0
- data/TODO.refactor/07-respond-to-replacement.md +237 -0
- data/TODO.refactor/08-spec-doubles.md +27 -0
- data/TODO.refactor/09-cli-shared-module.md +35 -0
- data/TODO.refactor/10-format-detector-ocp.md +34 -0
- data/TODO.refactor/11-convenience-decoupling.md +38 -0
- data/TODO.refactor/12-thread-safety.md +8 -0
- data/TODO.refactor/13-lutaml-model-migration.md +158 -0
- data/TODO.refactor/14-add-missing-specs.md +25 -0
- data/benchmark/README.md +260 -0
- data/benchmark/benchmark_suite.rb +125 -0
- data/benchmark/compression_bench.rb +181 -0
- data/benchmark/filter_bench.rb +180 -0
- data/benchmark/models/benchmark_result.rb +59 -0
- data/benchmark/models/comparison_result.rb +69 -0
- data/benchmark/profile_suite.rb +167 -0
- data/benchmark/reporter.rb +150 -0
- data/benchmark/run_benchmarks.rb +66 -0
- data/benchmark/test_data.rb +137 -0
- data/config/formats/rar3_spec.yml +92 -0
- data/config/formats/rar5_spec.yml +102 -0
- data/docs/.github/workflows/docs.yml +142 -0
- data/docs/.gitignore +21 -0
- data/docs/.lychee.toml +67 -0
- data/docs/Gemfile +13 -0
- data/docs/RAR_WRITE_SUPPORT.md +26 -0
- data/docs/README.md +101 -0
- data/docs/_config.yml +112 -0
- data/docs/assets/logo.svg +1 -0
- data/docs/assets/omnizip-logo.pdf +1540 -11
- data/docs/comparison/feature-matrix.adoc +694 -0
- data/docs/comparison/index.adoc +113 -0
- data/docs/comparison/vs-7zip.adoc +309 -0
- data/docs/comparison/vs-peazip.adoc +77 -0
- data/docs/comparison/vs-rubyzip.adoc +342 -0
- data/docs/comparison/vs-winrar.adoc +100 -0
- data/docs/compatibility.adoc +579 -0
- data/docs/concepts/index.adoc +129 -0
- data/docs/developer/architecture.adoc +256 -0
- data/docs/developer/contributing.adoc +158 -0
- data/docs/developer/index.adoc +25 -0
- data/docs/developer/testing.adoc +212 -0
- data/docs/getting-started/basic-usage.adoc +263 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +183 -0
- data/docs/getting-started/your-first-archive.adoc +219 -0
- data/docs/guides/advanced-features/encryption.adoc +277 -0
- data/docs/guides/advanced-features/index.adoc +59 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
- data/docs/guides/advanced-features/streaming.adoc +142 -0
- data/docs/guides/archive-formats/gzip-format.adoc +105 -0
- data/docs/guides/archive-formats/index.adoc +160 -0
- data/docs/guides/archive-formats/ole-format.adoc +151 -0
- data/docs/guides/archive-formats/rar-format.adoc +104 -0
- data/docs/guides/archive-formats/rar5.adoc +521 -0
- data/docs/guides/archive-formats/rpm-format.adoc +108 -0
- data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
- data/docs/guides/archive-formats/tar-format.adoc +106 -0
- data/docs/guides/archive-formats/xz-format.adoc +118 -0
- data/docs/guides/archive-formats/zip-format.adoc +35 -0
- data/docs/guides/compression-algorithms/bzip2.adoc +114 -0
- data/docs/guides/compression-algorithms/deflate.adoc +313 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +394 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
- data/docs/guides/creating-archives.adoc +348 -0
- data/docs/guides/extracting-archives.adoc +53 -0
- data/docs/guides/format-conversion.adoc +64 -0
- data/docs/guides/index.adoc +49 -0
- data/docs/guides/migration-rubyzip.adoc +217 -0
- data/docs/guides/parity-archives.adoc +605 -0
- data/docs/guides/performance-tuning.adoc +88 -0
- data/docs/index.adoc +228 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +187 -0
- data/docs/reference/cli/compress-command.adoc +114 -0
- data/docs/reference/cli/overview.adoc +140 -0
- data/docs/reference/index.adoc +26 -0
- data/docs/resources/faq.adoc +185 -0
- data/docs/resources/quick-reference.adoc +222 -0
- data/docs/rust-backend.md +0 -0
- data/docs/troubleshooting/index.adoc +207 -0
- data/docs/xar_format.md +216 -0
- data/examples/api_comparison.rb +205 -0
- data/examples/deflate64_example.rb +96 -0
- data/examples/par2_demo.rb +121 -0
- data/examples/quick_start_native.rb +150 -0
- data/examples/quick_start_rubyzip.rb +115 -0
- data/examples/rubyzip_compatibility_demo.rb +194 -0
- data/exe/omnizip +27 -0
- data/lib/omnizip/algorithm.rb +176 -0
- data/lib/omnizip/algorithm_registry.rb +65 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
- data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
- data/lib/omnizip/algorithms/bzip2.rb +108 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
- data/lib/omnizip/algorithms/deflate.rb +135 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
- data/lib/omnizip/algorithms/deflate64.rb +118 -0
- data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
- data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
- data/lib/omnizip/algorithms/lzma/decoder.rb +146 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
- data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
- data/lib/omnizip/algorithms/lzma/match.rb +32 -0
- data/lib/omnizip/algorithms/lzma/match_finder.rb +233 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
- data/lib/omnizip/algorithms/lzma.rb +266 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +133 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +146 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +122 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
- data/lib/omnizip/algorithms/registration.rb +28 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
- data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
- data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
- data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
- data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
- data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
- data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
- data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
- data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +210 -0
- data/lib/omnizip/algorithms.rb +35 -0
- data/lib/omnizip/archive/builder.rb +48 -0
- data/lib/omnizip/archive/reader_session.rb +67 -0
- data/lib/omnizip/archive.rb +86 -0
- data/lib/omnizip/archive_handler.rb +82 -0
- data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
- data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
- data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
- data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
- data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
- data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
- data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
- data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
- data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
- data/lib/omnizip/archive_handlers.rb +18 -0
- data/lib/omnizip/backends.rb +160 -0
- data/lib/omnizip/buffer/memory_archive.rb +246 -0
- data/lib/omnizip/buffer/memory_extractor.rb +234 -0
- data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
- data/lib/omnizip/buffer.rb +187 -0
- data/lib/omnizip/checksum_registry.rb +41 -0
- data/lib/omnizip/checksums/crc32.rb +101 -0
- data/lib/omnizip/checksums/crc64.rb +102 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/registration.rb +16 -0
- data/lib/omnizip/checksums/verifier.rb +130 -0
- data/lib/omnizip/checksums.rb +11 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +123 -0
- data/lib/omnizip/chunked.rb +123 -0
- data/lib/omnizip/cli/output_formatter.rb +112 -0
- data/lib/omnizip/cli.rb +604 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +245 -0
- data/lib/omnizip/commands/archive_extract_command.rb +231 -0
- data/lib/omnizip/commands/archive_list_command.rb +204 -0
- data/lib/omnizip/commands/archive_repair_command.rb +129 -0
- data/lib/omnizip/commands/archive_verify_command.rb +115 -0
- data/lib/omnizip/commands/compress_command.rb +115 -0
- data/lib/omnizip/commands/decompress_command.rb +149 -0
- data/lib/omnizip/commands/list_command.rb +51 -0
- data/lib/omnizip/commands/metadata_command.rb +215 -0
- data/lib/omnizip/commands/parity_create_command.rb +114 -0
- data/lib/omnizip/commands/parity_repair_command.rb +120 -0
- data/lib/omnizip/commands/parity_verify_command.rb +122 -0
- data/lib/omnizip/commands/profile_list_command.rb +54 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/commands.rb +21 -0
- data/lib/omnizip/convenience.rb +389 -0
- data/lib/omnizip/converter/conversion_registry.rb +50 -0
- data/lib/omnizip/converter/conversion_strategy.rb +108 -0
- data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
- data/lib/omnizip/converter.rb +124 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/crypto.rb +11 -0
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/error.rb +110 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +96 -0
- data/lib/omnizip/eta/rate_calculator.rb +104 -0
- data/lib/omnizip/eta/sample_history.rb +143 -0
- data/lib/omnizip/eta/time_estimator.rb +106 -0
- data/lib/omnizip/eta.rb +68 -0
- data/lib/omnizip/extraction/filter_chain.rb +179 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +66 -0
- data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
- data/lib/omnizip/extraction/regex_pattern.rb +50 -0
- data/lib/omnizip/extraction/selective_extractor.rb +247 -0
- data/lib/omnizip/extraction.rb +115 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +117 -0
- data/lib/omnizip/filter.rb +141 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +113 -0
- data/lib/omnizip/filters/bcj.rb +277 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
- data/lib/omnizip/filters/bcj2.rb +93 -0
- data/lib/omnizip/filters/bcj_arm.rb +174 -0
- data/lib/omnizip/filters/bcj_arm64.rb +242 -0
- data/lib/omnizip/filters/bcj_ia64.rb +194 -0
- data/lib/omnizip/filters/bcj_ppc.rb +188 -0
- data/lib/omnizip/filters/bcj_sparc.rb +174 -0
- data/lib/omnizip/filters/bcj_x86.rb +191 -0
- data/lib/omnizip/filters/delta.rb +195 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/filters.rb +20 -0
- data/lib/omnizip/format_detector.rb +166 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +159 -0
- data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +389 -0
- data/lib/omnizip/formats/cpio/reader.rb +194 -0
- data/lib/omnizip/formats/cpio/writer.rb +232 -0
- data/lib/omnizip/formats/cpio.rb +132 -0
- data/lib/omnizip/formats/format_spec_loader.rb +228 -0
- data/lib/omnizip/formats/gzip.rb +236 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
- data/lib/omnizip/formats/iso/directory_record.rb +162 -0
- data/lib/omnizip/formats/iso/joliet.rb +204 -0
- data/lib/omnizip/formats/iso/path_table.rb +125 -0
- data/lib/omnizip/formats/iso/reader.rb +194 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +543 -0
- data/lib/omnizip/formats/iso.rb +133 -0
- data/lib/omnizip/formats/lzip.rb +161 -0
- data/lib/omnizip/formats/lzma_alone.rb +149 -0
- data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
- data/lib/omnizip/formats/msi/constants.rb +157 -0
- data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
- data/lib/omnizip/formats/msi/entry.rb +134 -0
- data/lib/omnizip/formats/msi/reader.rb +301 -0
- data/lib/omnizip/formats/msi/string_pool.rb +246 -0
- data/lib/omnizip/formats/msi/table_parser.rb +244 -0
- data/lib/omnizip/formats/msi.rb +73 -0
- data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
- data/lib/omnizip/formats/ole/constants.rb +61 -0
- data/lib/omnizip/formats/ole/dirent.rb +439 -0
- data/lib/omnizip/formats/ole/header.rb +199 -0
- data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
- data/lib/omnizip/formats/ole/storage.rb +482 -0
- data/lib/omnizip/formats/ole/types/variant.rb +338 -0
- data/lib/omnizip/formats/ole.rb +143 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
- data/lib/omnizip/formats/rar/block_parser.rb +282 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman.rb +25 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
- data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
- data/lib/omnizip/formats/rar/compression.rb +17 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +88 -0
- data/lib/omnizip/formats/rar/decompressor.rb +316 -0
- data/lib/omnizip/formats/rar/external_writer.rb +311 -0
- data/lib/omnizip/formats/rar/header.rb +209 -0
- data/lib/omnizip/formats/rar/license_validator.rb +111 -0
- data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
- data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
- data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
- data/lib/omnizip/formats/rar/models.rb +14 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -0
- data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
- data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
- data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +96 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +208 -0
- data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +260 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +176 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
- data/lib/omnizip/formats/rar/reader.rb +377 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
- data/lib/omnizip/formats/rar/writer.rb +437 -0
- data/lib/omnizip/formats/rar.rb +193 -0
- data/lib/omnizip/formats/rar3/compressor.rb +71 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar3/reader.rb +107 -0
- data/lib/omnizip/formats/rar3/writer.rb +220 -0
- data/lib/omnizip/formats/rar3.rb +15 -0
- data/lib/omnizip/formats/rar5/compressor.rb +71 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar5/reader.rb +130 -0
- data/lib/omnizip/formats/rar5/writer.rb +65 -0
- data/lib/omnizip/formats/rar5.rb +15 -0
- data/lib/omnizip/formats/rpm/constants.rb +58 -0
- data/lib/omnizip/formats/rpm/entry.rb +106 -0
- data/lib/omnizip/formats/rpm/header.rb +106 -0
- data/lib/omnizip/formats/rpm/lead.rb +132 -0
- data/lib/omnizip/formats/rpm/tag.rb +228 -0
- data/lib/omnizip/formats/rpm/writer.rb +652 -0
- data/lib/omnizip/formats/rpm.rb +458 -0
- data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
- data/lib/omnizip/formats/seven_zip/header.rb +102 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/models.rb +20 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
- data/lib/omnizip/formats/seven_zip.rb +179 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +98 -0
- data/lib/omnizip/formats/tar/header.rb +206 -0
- data/lib/omnizip/formats/tar/reader.rb +119 -0
- data/lib/omnizip/formats/tar/writer.rb +212 -0
- data/lib/omnizip/formats/tar.rb +74 -0
- data/lib/omnizip/formats/xar/constants.rb +119 -0
- data/lib/omnizip/formats/xar/entry.rb +268 -0
- data/lib/omnizip/formats/xar/header.rb +223 -0
- data/lib/omnizip/formats/xar/reader.rb +400 -0
- data/lib/omnizip/formats/xar/toc.rb +570 -0
- data/lib/omnizip/formats/xar/writer.rb +461 -0
- data/lib/omnizip/formats/xar.rb +145 -0
- data/lib/omnizip/formats/xz/reader.rb +121 -0
- data/lib/omnizip/formats/xz/writer.rb +416 -0
- data/lib/omnizip/formats/xz.rb +210 -0
- data/lib/omnizip/formats/xz_const.rb +49 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl.rb +52 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
- data/lib/omnizip/formats/zip/reader.rb +376 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +489 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/formats.rb +29 -0
- data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
- data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
- data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
- data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
- data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
- data/lib/omnizip/implementations/base.rb +19 -0
- data/lib/omnizip/implementations/rust/archive.rb +93 -0
- data/lib/omnizip/implementations/rust/library.rb +221 -0
- data/lib/omnizip/implementations/rust.rb +26 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
- data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
- data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
- data/lib/omnizip/implementations/seven_zip.rb +11 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
- data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
- data/lib/omnizip/implementations/xz_utils.rb +10 -0
- data/lib/omnizip/implementations.rb +25 -0
- data/lib/omnizip/io/buffered_input.rb +147 -0
- data/lib/omnizip/io/buffered_output.rb +106 -0
- data/lib/omnizip/io/source.rb +143 -0
- data/lib/omnizip/io/stream_manager.rb +117 -0
- data/lib/omnizip/io.rb +15 -0
- data/lib/omnizip/link_handler/hard_link.rb +79 -0
- data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
- data/lib/omnizip/link_handler.rb +129 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +153 -0
- data/lib/omnizip/metadata/metadata_editor.rb +169 -0
- data/lib/omnizip/metadata/metadata_registry.rb +71 -0
- data/lib/omnizip/metadata/metadata_validator.rb +101 -0
- data/lib/omnizip/metadata.rb +58 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +41 -0
- data/lib/omnizip/models/attribute_apply.rb +40 -0
- data/lib/omnizip/models/compression_options.rb +53 -0
- data/lib/omnizip/models/conversion_options.rb +79 -0
- data/lib/omnizip/models/conversion_result.rb +141 -0
- data/lib/omnizip/models/eta_result.rb +45 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +142 -0
- data/lib/omnizip/models/filter_config.rb +148 -0
- data/lib/omnizip/models/match_result.rb +141 -0
- data/lib/omnizip/models/optimization_suggestion.rb +95 -0
- data/lib/omnizip/models/parallel_options.rb +116 -0
- data/lib/omnizip/models/performance_result.rb +85 -0
- data/lib/omnizip/models/profile_report.rb +116 -0
- data/lib/omnizip/models/progress_options.rb +39 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +45 -0
- data/lib/omnizip/parallel/engine.rb +52 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +225 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
- data/lib/omnizip/parallel/thread_pool.rb +60 -0
- data/lib/omnizip/parallel/worker_pool.rb +227 -0
- data/lib/omnizip/parallel.rb +156 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +71 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
- data/lib/omnizip/parity/models/main_packet.rb +126 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +102 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
- data/lib/omnizip/parity/models.rb +27 -0
- data/lib/omnizip/parity/par2_creator.rb +496 -0
- data/lib/omnizip/parity/par2_repairer.rb +409 -0
- data/lib/omnizip/parity/par2_verifier.rb +373 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
- data/lib/omnizip/parity.rb +207 -0
- data/lib/omnizip/password/encryption_registry.rb +26 -0
- data/lib/omnizip/password/encryption_strategy.rb +96 -0
- data/lib/omnizip/password/password_validator.rb +129 -0
- data/lib/omnizip/password/winzip_aes_strategy.rb +190 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
- data/lib/omnizip/password.rb +88 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
- data/lib/omnizip/pipe.rb +120 -0
- data/lib/omnizip/platform/ntfs_streams.rb +200 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +36 -0
- data/lib/omnizip/profile/balanced_profile.rb +31 -0
- data/lib/omnizip/profile/binary_profile.rb +33 -0
- data/lib/omnizip/profile/compression_profile.rb +157 -0
- data/lib/omnizip/profile/custom_profile.rb +155 -0
- data/lib/omnizip/profile/fast_profile.rb +31 -0
- data/lib/omnizip/profile/maximum_profile.rb +31 -0
- data/lib/omnizip/profile/profile_detector.rb +108 -0
- data/lib/omnizip/profile/profile_registry.rb +160 -0
- data/lib/omnizip/profile/text_profile.rb +33 -0
- data/lib/omnizip/profile.rb +261 -0
- data/lib/omnizip/profiler/memory_profiler.rb +66 -0
- data/lib/omnizip/profiler/method_profiler.rb +49 -0
- data/lib/omnizip/profiler/report_generator.rb +158 -0
- data/lib/omnizip/profiler.rb +192 -0
- data/lib/omnizip/progress/callback_reporter.rb +34 -0
- data/lib/omnizip/progress/console_reporter.rb +59 -0
- data/lib/omnizip/progress/log_reporter.rb +89 -0
- data/lib/omnizip/progress/operation_progress.rb +118 -0
- data/lib/omnizip/progress/progress_bar.rb +156 -0
- data/lib/omnizip/progress/progress_reporter.rb +40 -0
- data/lib/omnizip/progress/progress_tracker.rb +215 -0
- data/lib/omnizip/progress/silent_reporter.rb +22 -0
- data/lib/omnizip/progress.rb +131 -0
- data/lib/omnizip/registry.rb +111 -0
- data/lib/omnizip/rubyzip_compat.rb +61 -0
- data/lib/omnizip/temp/safe_extract.rb +124 -0
- data/lib/omnizip/temp/temp_file.rb +123 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +184 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +160 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +270 -0
- data/lib/omnizip/zip/output_stream.rb +320 -0
- data/lib/omnizip/zip.rb +23 -0
- data/lib/omnizip.rb +157 -0
- data/lib/tasks/msi_test_files.rake +66 -0
- data/lib/tasks/platform_gems.rake +147 -0
- data/lib/tasks/rust_backend.rake +48 -0
- data/readme-docs/advanced-features.adoc +514 -0
- data/readme-docs/api-usage.adoc +445 -0
- data/readme-docs/architecture.adoc +450 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +446 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +316 -0
- data/readme-docs/installation.adoc +228 -0
- data/readme-docs/par2-archives.adoc +608 -0
- data/readme-docs/performance-profiler.adoc +389 -0
- data/readme-docs/preprocessing-filters.adoc +280 -0
- data/vendor/libomnizip_ffi.so +0 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +768 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module Iso
|
|
6
|
+
# Rock Ridge Extensions for ISO 9660
|
|
7
|
+
#
|
|
8
|
+
# Implements System Use Sharing Protocol (SUSP) and Rock Ridge
|
|
9
|
+
# extensions to store Unix file attributes, permissions, symbolic links,
|
|
10
|
+
# and device nodes in ISO 9660 images.
|
|
11
|
+
#
|
|
12
|
+
# Rock Ridge allows ISO images to preserve full Unix filesystem semantics.
|
|
13
|
+
module RockRidge
|
|
14
|
+
# SUSP/Rock Ridge signature identifiers
|
|
15
|
+
module Signatures
|
|
16
|
+
SP = "SP" # System Use Sharing Protocol indicator
|
|
17
|
+
CE = "CE" # Continuation area
|
|
18
|
+
PX = "PX" # POSIX file attributes
|
|
19
|
+
PN = "PN" # POSIX device number
|
|
20
|
+
SL = "SL" # Symbolic link
|
|
21
|
+
NM = "NM" # Alternate name
|
|
22
|
+
CL = "CL" # Child link
|
|
23
|
+
PL = "PL" # Parent link
|
|
24
|
+
RE = "RE" # Relocated directory
|
|
25
|
+
TF = "TF" # Time stamps
|
|
26
|
+
SF = "SF" # Sparse file
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# System Use Entry
|
|
30
|
+
class SUEntry
|
|
31
|
+
attr_accessor :signature, :length, :version, :data
|
|
32
|
+
|
|
33
|
+
# Initialize entry
|
|
34
|
+
#
|
|
35
|
+
# @param signature [String] 2-byte signature
|
|
36
|
+
# @param version [Integer] Entry version
|
|
37
|
+
# @param data [String] Entry data
|
|
38
|
+
def initialize(signature, version: 1, data: "")
|
|
39
|
+
@signature = signature
|
|
40
|
+
@length = 4 + data.bytesize
|
|
41
|
+
@version = version
|
|
42
|
+
@data = data
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Convert to binary
|
|
46
|
+
#
|
|
47
|
+
# @return [String] Binary representation
|
|
48
|
+
def to_binary
|
|
49
|
+
result = +""
|
|
50
|
+
result << @signature # 2 bytes
|
|
51
|
+
result << [@length].pack("C") # 1 byte
|
|
52
|
+
result << [@version].pack("C") # 1 byte
|
|
53
|
+
result << @data
|
|
54
|
+
result
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Parse from binary
|
|
58
|
+
#
|
|
59
|
+
# @param data [String] Binary data
|
|
60
|
+
# @param offset [Integer] Starting offset
|
|
61
|
+
# @return [SUEntry] Parsed entry
|
|
62
|
+
def self.parse(data, offset = 0)
|
|
63
|
+
signature = data[offset, 2]
|
|
64
|
+
length = data.getbyte(offset + 2)
|
|
65
|
+
version = data.getbyte(offset + 3)
|
|
66
|
+
entry_data = data[offset + 4, length - 4]
|
|
67
|
+
|
|
68
|
+
new(signature, version: version, data: entry_data)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Add Rock Ridge extensions to directory record
|
|
73
|
+
#
|
|
74
|
+
# @param record_data [String] Directory record data
|
|
75
|
+
# @param file_stat [File::Stat] File statistics
|
|
76
|
+
# @param name [String] File name
|
|
77
|
+
# @param is_symlink [Boolean] Is this a symbolic link
|
|
78
|
+
# @return [String] Updated record with Rock Ridge fields
|
|
79
|
+
def self.add_extensions(record_data, file_stat, name, is_symlink: false)
|
|
80
|
+
system_use = +""
|
|
81
|
+
|
|
82
|
+
# Add SP entry (first entry in root directory only)
|
|
83
|
+
# This indicates Rock Ridge is being used
|
|
84
|
+
# For simplicity, we'll add to all entries
|
|
85
|
+
|
|
86
|
+
# Add PX (POSIX attributes)
|
|
87
|
+
system_use << build_px_entry(file_stat).to_binary
|
|
88
|
+
|
|
89
|
+
# Add TF (timestamps)
|
|
90
|
+
system_use << build_tf_entry(file_stat).to_binary
|
|
91
|
+
|
|
92
|
+
# Add NM (alternate name) if different from ISO name
|
|
93
|
+
unless name == File.basename(name).upcase
|
|
94
|
+
system_use << build_nm_entry(name).to_binary
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Add SL (symbolic link) if applicable
|
|
98
|
+
if is_symlink
|
|
99
|
+
link_target = File.readlink(file_stat)
|
|
100
|
+
system_use << build_sl_entry(link_target).to_binary
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Append system use to record
|
|
104
|
+
record_data + system_use
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Build PX (POSIX attributes) entry
|
|
108
|
+
#
|
|
109
|
+
# @param stat [File::Stat] File statistics
|
|
110
|
+
# @return [SUEntry] PX entry
|
|
111
|
+
def self.build_px_entry(stat)
|
|
112
|
+
data = +""
|
|
113
|
+
|
|
114
|
+
# File mode (both-endian)
|
|
115
|
+
data << [stat.mode].pack("V")
|
|
116
|
+
data << [stat.mode].pack("N")
|
|
117
|
+
|
|
118
|
+
# Number of links (both-endian)
|
|
119
|
+
data << [stat.nlink].pack("V")
|
|
120
|
+
data << [stat.nlink].pack("N")
|
|
121
|
+
|
|
122
|
+
# User ID (both-endian)
|
|
123
|
+
data << [stat.uid].pack("V")
|
|
124
|
+
data << [stat.uid].pack("N")
|
|
125
|
+
|
|
126
|
+
# Group ID (both-endian)
|
|
127
|
+
data << [stat.gid].pack("V")
|
|
128
|
+
data << [stat.gid].pack("N")
|
|
129
|
+
|
|
130
|
+
# Inode number (both-endian) - optional
|
|
131
|
+
data << [stat.ino].pack("V")
|
|
132
|
+
data << [stat.ino].pack("N")
|
|
133
|
+
|
|
134
|
+
SUEntry.new(Signatures::PX, data: data)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Build TF (timestamps) entry
|
|
138
|
+
#
|
|
139
|
+
# @param stat [File::Stat] File statistics
|
|
140
|
+
# @return [SUEntry] TF entry
|
|
141
|
+
def self.build_tf_entry(stat)
|
|
142
|
+
# Flags indicating which timestamps are present
|
|
143
|
+
# Bit 0: Creation time
|
|
144
|
+
# Bit 1: Modify time
|
|
145
|
+
# Bit 2: Access time
|
|
146
|
+
# Bit 3: Attributes time
|
|
147
|
+
# Bit 4: Backup time
|
|
148
|
+
# Bit 5: Expiration time
|
|
149
|
+
# Bit 6: Effective time
|
|
150
|
+
# Bit 7: Long format (17 bytes instead of 7)
|
|
151
|
+
|
|
152
|
+
flags = 0b00000110 # Modify and access times, short format
|
|
153
|
+
|
|
154
|
+
data = +""
|
|
155
|
+
data << [flags].pack("C")
|
|
156
|
+
|
|
157
|
+
# Modification time (7-byte format)
|
|
158
|
+
data << encode_time_7byte(stat.mtime)
|
|
159
|
+
|
|
160
|
+
# Access time (7-byte format)
|
|
161
|
+
data << encode_time_7byte(stat.atime)
|
|
162
|
+
|
|
163
|
+
SUEntry.new(Signatures::TF, data: data)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Build NM (alternate name) entry
|
|
167
|
+
#
|
|
168
|
+
# @param name [String] File name
|
|
169
|
+
# @return [SUEntry] NM entry
|
|
170
|
+
def self.build_nm_entry(name)
|
|
171
|
+
# Flags
|
|
172
|
+
# Bit 0: CONTINUE (name continues in next NM)
|
|
173
|
+
# Bit 1: CURRENT (name is ".")
|
|
174
|
+
# Bit 2: PARENT (name is "..")
|
|
175
|
+
flags = 0
|
|
176
|
+
|
|
177
|
+
data = +""
|
|
178
|
+
data << [flags].pack("C")
|
|
179
|
+
data << name
|
|
180
|
+
|
|
181
|
+
SUEntry.new(Signatures::NM, data: data)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Build SL (symbolic link) entry
|
|
185
|
+
#
|
|
186
|
+
# @param target [String] Link target
|
|
187
|
+
# @return [SUEntry] SL entry
|
|
188
|
+
def self.build_sl_entry(target)
|
|
189
|
+
# Flags
|
|
190
|
+
# Bit 0: CONTINUE (link continues in next SL)
|
|
191
|
+
flags = 0
|
|
192
|
+
|
|
193
|
+
data = +""
|
|
194
|
+
data << [flags].pack("C")
|
|
195
|
+
|
|
196
|
+
# Component flags
|
|
197
|
+
# Bit 0: CONTINUE (component continues)
|
|
198
|
+
# Bit 1: CURRENT (component is ".")
|
|
199
|
+
# Bit 2: PARENT (component is "..")
|
|
200
|
+
# Bit 3: ROOT (component is root)
|
|
201
|
+
comp_flags = 0
|
|
202
|
+
|
|
203
|
+
# Component length
|
|
204
|
+
data << [comp_flags].pack("C")
|
|
205
|
+
data << [target.bytesize].pack("C")
|
|
206
|
+
data << target
|
|
207
|
+
|
|
208
|
+
SUEntry.new(Signatures::SL, data: data)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Build PN (POSIX device number) entry
|
|
212
|
+
#
|
|
213
|
+
# @param stat [File::Stat] File statistics
|
|
214
|
+
# @return [SUEntry] PN entry
|
|
215
|
+
def self.build_pn_entry(stat)
|
|
216
|
+
data = +""
|
|
217
|
+
|
|
218
|
+
# Device number high (both-endian)
|
|
219
|
+
dev_high = (stat.rdev >> 32) & 0xFFFFFFFF
|
|
220
|
+
data << [dev_high].pack("V")
|
|
221
|
+
data << [dev_high].pack("N")
|
|
222
|
+
|
|
223
|
+
# Device number low (both-endian)
|
|
224
|
+
dev_low = stat.rdev & 0xFFFFFFFF
|
|
225
|
+
data << [dev_low].pack("V")
|
|
226
|
+
data << [dev_low].pack("N")
|
|
227
|
+
|
|
228
|
+
SUEntry.new(Signatures::PN, data: data)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Encode time in 7-byte format
|
|
232
|
+
#
|
|
233
|
+
# @param time [Time] Time to encode
|
|
234
|
+
# @return [String] 7-byte encoded time
|
|
235
|
+
def self.encode_time_7byte(time)
|
|
236
|
+
[
|
|
237
|
+
time.year - 1900,
|
|
238
|
+
time.month,
|
|
239
|
+
time.day,
|
|
240
|
+
time.hour,
|
|
241
|
+
time.min,
|
|
242
|
+
time.sec,
|
|
243
|
+
0, # GMT offset
|
|
244
|
+
].pack("C7")
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Parse Rock Ridge extensions from system use field
|
|
248
|
+
#
|
|
249
|
+
# @param system_use [String] System use field data
|
|
250
|
+
# @return [Hash] Parsed attributes
|
|
251
|
+
def self.parse_extensions(system_use)
|
|
252
|
+
attributes = {}
|
|
253
|
+
offset = 0
|
|
254
|
+
|
|
255
|
+
while offset < system_use.bytesize
|
|
256
|
+
entry = SUEntry.parse(system_use, offset)
|
|
257
|
+
|
|
258
|
+
case entry.signature
|
|
259
|
+
when Signatures::PX
|
|
260
|
+
attributes[:posix] = parse_px_entry(entry)
|
|
261
|
+
when Signatures::TF
|
|
262
|
+
attributes[:times] = parse_tf_entry(entry)
|
|
263
|
+
when Signatures::NM
|
|
264
|
+
attributes[:name] = parse_nm_entry(entry)
|
|
265
|
+
when Signatures::SL
|
|
266
|
+
attributes[:symlink] = parse_sl_entry(entry)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
offset += entry.length
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
attributes
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Parse PX entry
|
|
276
|
+
#
|
|
277
|
+
# @param entry [SUEntry] PX entry
|
|
278
|
+
# @return [Hash] Parsed POSIX attributes
|
|
279
|
+
def self.parse_px_entry(entry)
|
|
280
|
+
data = entry.data
|
|
281
|
+
{
|
|
282
|
+
mode: data[0, 4].unpack1("V"),
|
|
283
|
+
nlink: data[8, 4].unpack1("V"),
|
|
284
|
+
uid: data[16, 4].unpack1("V"),
|
|
285
|
+
gid: data[24, 4].unpack1("V"),
|
|
286
|
+
ino: data[32, 4].unpack1("V"),
|
|
287
|
+
}
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Parse TF entry
|
|
291
|
+
#
|
|
292
|
+
# @param entry [SUEntry] TF entry
|
|
293
|
+
# @return [Hash] Parsed timestamps
|
|
294
|
+
def self.parse_tf_entry(entry)
|
|
295
|
+
# Parse based on flags
|
|
296
|
+
flags = entry.data.getbyte(0)
|
|
297
|
+
times = {}
|
|
298
|
+
|
|
299
|
+
offset = 1
|
|
300
|
+
if flags & 0x02 # Modify time
|
|
301
|
+
times[:mtime] = parse_time_7byte(entry.data[offset, 7])
|
|
302
|
+
offset += 7
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
if flags & 0x04 # Access time
|
|
306
|
+
times[:atime] = parse_time_7byte(entry.data[offset, 7])
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
times
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# Parse NM entry
|
|
313
|
+
#
|
|
314
|
+
# @param entry [SUEntry] NM entry
|
|
315
|
+
# @return [String] Alternate name
|
|
316
|
+
def self.parse_nm_entry(entry)
|
|
317
|
+
entry.data[1..]
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Parse SL entry
|
|
321
|
+
#
|
|
322
|
+
# @param entry [SUEntry] SL entry
|
|
323
|
+
# @return [String] Symbolic link target
|
|
324
|
+
def self.parse_sl_entry(entry)
|
|
325
|
+
# Skip flags byte, component flags, read length and target
|
|
326
|
+
comp_len = entry.data.getbyte(2)
|
|
327
|
+
entry.data[3, comp_len]
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# Parse 7-byte time format
|
|
331
|
+
#
|
|
332
|
+
# @param data [String] 7-byte time data
|
|
333
|
+
# @return [Time] Parsed time
|
|
334
|
+
def self.parse_time_7byte(data)
|
|
335
|
+
year = 1900 + data.getbyte(0)
|
|
336
|
+
month = data.getbyte(1)
|
|
337
|
+
day = data.getbyte(2)
|
|
338
|
+
hour = data.getbyte(3)
|
|
339
|
+
minute = data.getbyte(4)
|
|
340
|
+
second = data.getbyte(5)
|
|
341
|
+
|
|
342
|
+
Time.new(year, month, day, hour, minute, second)
|
|
343
|
+
rescue ArgumentError
|
|
344
|
+
Time.now
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "time"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Formats
|
|
7
|
+
module Iso
|
|
8
|
+
# ISO 9660 Volume Descriptor Builder
|
|
9
|
+
#
|
|
10
|
+
# Builds primary and supplementary volume descriptors for ISO images.
|
|
11
|
+
# Handles proper encoding of volume metadata and root directory information.
|
|
12
|
+
class VolumeBuilder
|
|
13
|
+
# @return [String] Volume identifier
|
|
14
|
+
attr_reader :volume_id
|
|
15
|
+
|
|
16
|
+
# @return [String] System identifier
|
|
17
|
+
attr_reader :system_id
|
|
18
|
+
|
|
19
|
+
# @return [String] Publisher
|
|
20
|
+
attr_reader :publisher
|
|
21
|
+
|
|
22
|
+
# @return [String] Preparer
|
|
23
|
+
attr_reader :preparer
|
|
24
|
+
|
|
25
|
+
# @return [String] Application
|
|
26
|
+
attr_reader :application
|
|
27
|
+
|
|
28
|
+
# @return [Integer] ISO level
|
|
29
|
+
attr_reader :level
|
|
30
|
+
|
|
31
|
+
# @return [Boolean] Rock Ridge enabled
|
|
32
|
+
attr_reader :rock_ridge
|
|
33
|
+
|
|
34
|
+
# @return [Boolean] Joliet enabled
|
|
35
|
+
attr_reader :joliet
|
|
36
|
+
|
|
37
|
+
# Initialize volume builder
|
|
38
|
+
#
|
|
39
|
+
# @param options [Hash] Builder options
|
|
40
|
+
def initialize(options = {})
|
|
41
|
+
@volume_id = options.fetch(:volume_id, "OMNIZIP")
|
|
42
|
+
@system_id = options.fetch(:system_id, "LINUX")
|
|
43
|
+
@publisher = options.fetch(:publisher, "")
|
|
44
|
+
@preparer = options.fetch(:preparer, "")
|
|
45
|
+
@application = options.fetch(:application, "OMNIZIP")
|
|
46
|
+
@level = options.fetch(:level, 2)
|
|
47
|
+
@rock_ridge = options.fetch(:rock_ridge, false)
|
|
48
|
+
@joliet = options.fetch(:joliet, false)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Build primary volume descriptor
|
|
52
|
+
#
|
|
53
|
+
# @param root_dir [Hash] Root directory information
|
|
54
|
+
# @return [String] Primary VD sector (2048 bytes)
|
|
55
|
+
def build_primary(root_dir)
|
|
56
|
+
sector = +""
|
|
57
|
+
|
|
58
|
+
# Byte 0: Volume descriptor type (1 = Primary)
|
|
59
|
+
sector << [Iso::VD_PRIMARY].pack("C")
|
|
60
|
+
|
|
61
|
+
# Bytes 1-5: Standard identifier "CD001"
|
|
62
|
+
sector << VolumeDescriptor::ISO_IDENTIFIER
|
|
63
|
+
|
|
64
|
+
# Byte 6: Version (1)
|
|
65
|
+
sector << [1].pack("C")
|
|
66
|
+
|
|
67
|
+
# Byte 7: Unused (0)
|
|
68
|
+
sector << "\x00"
|
|
69
|
+
|
|
70
|
+
# Bytes 8-39: System identifier (a-characters, space-padded)
|
|
71
|
+
sector << pad_a_string(@system_id, 32)
|
|
72
|
+
|
|
73
|
+
# Bytes 40-71: Volume identifier (d-characters, space-padded)
|
|
74
|
+
sector << pad_d_string(@volume_id, 32)
|
|
75
|
+
|
|
76
|
+
# Bytes 72-79: Unused (zeros)
|
|
77
|
+
sector << ("\x00" * 8)
|
|
78
|
+
|
|
79
|
+
# Bytes 80-87: Volume space size (both-endian)
|
|
80
|
+
volume_sectors = root_dir[:total_sectors] || 100
|
|
81
|
+
sector << [volume_sectors].pack("V") # Little-endian
|
|
82
|
+
sector << [volume_sectors].pack("N") # Big-endian
|
|
83
|
+
|
|
84
|
+
# Bytes 88-119: Unused (zeros)
|
|
85
|
+
sector << ("\x00" * 32)
|
|
86
|
+
|
|
87
|
+
# Bytes 120-123: Volume set size (both-endian)
|
|
88
|
+
sector << [1].pack("v")
|
|
89
|
+
sector << [1].pack("n")
|
|
90
|
+
|
|
91
|
+
# Bytes 124-127: Volume sequence number (both-endian)
|
|
92
|
+
sector << [1].pack("v")
|
|
93
|
+
sector << [1].pack("n")
|
|
94
|
+
|
|
95
|
+
# Bytes 128-131: Logical block size (both-endian)
|
|
96
|
+
sector << [Iso::SECTOR_SIZE].pack("v")
|
|
97
|
+
sector << [Iso::SECTOR_SIZE].pack("n")
|
|
98
|
+
|
|
99
|
+
# Bytes 132-139: Path table size (both-endian)
|
|
100
|
+
path_table_size = root_dir[:path_table_size] || 10
|
|
101
|
+
sector << [path_table_size].pack("V")
|
|
102
|
+
sector << [path_table_size].pack("N")
|
|
103
|
+
|
|
104
|
+
# Bytes 140-143: Location of type L path table
|
|
105
|
+
sector << [root_dir[:path_table_location] || 19].pack("V")
|
|
106
|
+
|
|
107
|
+
# Bytes 144-147: Location of optional type L path table
|
|
108
|
+
sector << [0].pack("V")
|
|
109
|
+
|
|
110
|
+
# Bytes 148-151: Location of type M path table
|
|
111
|
+
sector << [root_dir[:path_table_location_be] || 20].pack("N")
|
|
112
|
+
|
|
113
|
+
# Bytes 152-155: Location of optional type M path table
|
|
114
|
+
sector << [0].pack("N")
|
|
115
|
+
|
|
116
|
+
# Bytes 156-189: Root directory record (34 bytes)
|
|
117
|
+
sector << build_root_directory_record(root_dir)
|
|
118
|
+
|
|
119
|
+
# Bytes 190-317: Volume set identifier
|
|
120
|
+
sector << pad_d_string("", 128)
|
|
121
|
+
|
|
122
|
+
# Bytes 318-445: Publisher identifier
|
|
123
|
+
sector << pad_a_string(@publisher, 128)
|
|
124
|
+
|
|
125
|
+
# Bytes 446-573: Data preparer identifier
|
|
126
|
+
sector << pad_a_string(@preparer, 128)
|
|
127
|
+
|
|
128
|
+
# Bytes 574-701: Application identifier
|
|
129
|
+
sector << pad_a_string(@application, 128)
|
|
130
|
+
|
|
131
|
+
# Bytes 702-738: Copyright file identifier
|
|
132
|
+
sector << pad_d_string("", 37)
|
|
133
|
+
|
|
134
|
+
# Bytes 739-775: Abstract file identifier
|
|
135
|
+
sector << pad_d_string("", 37)
|
|
136
|
+
|
|
137
|
+
# Bytes 776-812: Bibliographic file identifier
|
|
138
|
+
sector << pad_d_string("", 37)
|
|
139
|
+
|
|
140
|
+
# Bytes 813-829: Volume creation date/time
|
|
141
|
+
now = Time.now
|
|
142
|
+
sector << encode_volume_datetime(now)
|
|
143
|
+
|
|
144
|
+
# Bytes 830-846: Volume modification date/time
|
|
145
|
+
sector << encode_volume_datetime(now)
|
|
146
|
+
|
|
147
|
+
# Bytes 847-863: Volume expiration date/time (not set)
|
|
148
|
+
sector << encode_volume_datetime(nil)
|
|
149
|
+
|
|
150
|
+
# Bytes 864-880: Volume effective date/time (not set)
|
|
151
|
+
sector << encode_volume_datetime(nil)
|
|
152
|
+
|
|
153
|
+
# Byte 881: File structure version (1)
|
|
154
|
+
sector << [1].pack("C")
|
|
155
|
+
|
|
156
|
+
# Byte 882: Unused (0)
|
|
157
|
+
sector << "\x00"
|
|
158
|
+
|
|
159
|
+
# Bytes 883-1395: Application use
|
|
160
|
+
sector << ("\x00" * 513)
|
|
161
|
+
|
|
162
|
+
# Bytes 1396-2047: Reserved
|
|
163
|
+
sector << ("\x00" * 652)
|
|
164
|
+
|
|
165
|
+
sector
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Build Joliet supplementary volume descriptor
|
|
169
|
+
#
|
|
170
|
+
# @param root_dir [Hash] Root directory information
|
|
171
|
+
# @return [String] Joliet SVD sector (2048 bytes)
|
|
172
|
+
def build_joliet(root_dir)
|
|
173
|
+
# Joliet is similar to primary VD but with:
|
|
174
|
+
# - Type = 2 (supplementary)
|
|
175
|
+
# - UCS-2 encoding for strings
|
|
176
|
+
# - Escape sequences for character set
|
|
177
|
+
|
|
178
|
+
sector = build_primary(root_dir)
|
|
179
|
+
|
|
180
|
+
# Modify type to supplementary
|
|
181
|
+
sector.setbyte(0, Iso::VD_SUPPLEMENTARY)
|
|
182
|
+
|
|
183
|
+
# Add escape sequences for UCS-2
|
|
184
|
+
# Bytes 88-90: %/@ %/C %/E for levels 1, 2, 3
|
|
185
|
+
sector.setbyte(88, 0x25) # '%'
|
|
186
|
+
sector.setbyte(89, 0x2F) # '/'
|
|
187
|
+
sector.setbyte(90, 0x45) # 'E'
|
|
188
|
+
|
|
189
|
+
# Convert volume ID to UCS-2
|
|
190
|
+
volume_id_ucs2 = @volume_id.encode("UTF-16BE")
|
|
191
|
+
padded_volume_id = pad_string(volume_id_ucs2,
|
|
192
|
+
32).force_encoding("ASCII-8BIT")
|
|
193
|
+
|
|
194
|
+
# Replace bytes 40-71 with UCS-2 volume ID
|
|
195
|
+
32.times do |i|
|
|
196
|
+
sector.setbyte(40 + i, padded_volume_id.getbyte(i))
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
sector
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
private
|
|
203
|
+
|
|
204
|
+
# Build root directory record
|
|
205
|
+
#
|
|
206
|
+
# @param root_dir [Hash] Root directory info
|
|
207
|
+
# @return [String] 34-byte directory record
|
|
208
|
+
def build_root_directory_record(root_dir)
|
|
209
|
+
record = +""
|
|
210
|
+
|
|
211
|
+
# Length of record (34 bytes for root)
|
|
212
|
+
record << [34].pack("C")
|
|
213
|
+
|
|
214
|
+
# Extended attribute length (0)
|
|
215
|
+
record << [0].pack("C")
|
|
216
|
+
|
|
217
|
+
# Location of extent (both-endian)
|
|
218
|
+
location = root_dir[:location] || 21
|
|
219
|
+
record << [location].pack("V")
|
|
220
|
+
record << [location].pack("N")
|
|
221
|
+
|
|
222
|
+
# Data length (both-endian)
|
|
223
|
+
data_length = root_dir[:size] || Iso::SECTOR_SIZE
|
|
224
|
+
record << [data_length].pack("V")
|
|
225
|
+
record << [data_length].pack("N")
|
|
226
|
+
|
|
227
|
+
# Recording date
|
|
228
|
+
record << encode_record_datetime(Time.now)
|
|
229
|
+
|
|
230
|
+
# Flags (directory)
|
|
231
|
+
record << [Iso::FLAG_DIRECTORY].pack("C")
|
|
232
|
+
|
|
233
|
+
# File unit size, interleave gap
|
|
234
|
+
record << [0, 0].pack("C2")
|
|
235
|
+
|
|
236
|
+
# Volume sequence number (both-endian)
|
|
237
|
+
record << [1].pack("v")
|
|
238
|
+
record << [1].pack("n")
|
|
239
|
+
|
|
240
|
+
# File identifier length (1 for root)
|
|
241
|
+
record << [1].pack("C")
|
|
242
|
+
|
|
243
|
+
# File identifier (0x00 for root)
|
|
244
|
+
record << "\x00"
|
|
245
|
+
|
|
246
|
+
record
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Encode volume date/time (17-byte format)
|
|
250
|
+
#
|
|
251
|
+
# @param time [Time, nil] Time to encode
|
|
252
|
+
# @return [String] 17-byte encoded time
|
|
253
|
+
def encode_volume_datetime(time)
|
|
254
|
+
if time.nil?
|
|
255
|
+
# All zeros for unset time
|
|
256
|
+
return "#{'0' * 16}\u0000"
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
format(
|
|
260
|
+
"%04d%02d%02d%02d%02d%02d%02d",
|
|
261
|
+
time.year,
|
|
262
|
+
time.month,
|
|
263
|
+
time.day,
|
|
264
|
+
time.hour,
|
|
265
|
+
time.min,
|
|
266
|
+
time.sec,
|
|
267
|
+
0, # Centiseconds
|
|
268
|
+
) + [0].pack("c") # GMT offset
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# Encode recording date/time (7-byte format)
|
|
272
|
+
#
|
|
273
|
+
# @param time [Time] Time to encode
|
|
274
|
+
# @return [String] 7-byte encoded time
|
|
275
|
+
def encode_record_datetime(time)
|
|
276
|
+
[
|
|
277
|
+
time.year - 1900,
|
|
278
|
+
time.month,
|
|
279
|
+
time.day,
|
|
280
|
+
time.hour,
|
|
281
|
+
time.min,
|
|
282
|
+
time.sec,
|
|
283
|
+
0, # GMT offset
|
|
284
|
+
].pack("C7")
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Pad string with spaces (a-characters)
|
|
288
|
+
#
|
|
289
|
+
# @param str [String] String to pad
|
|
290
|
+
# @param length [Integer] Target length
|
|
291
|
+
# @return [String] Padded string
|
|
292
|
+
def pad_a_string(str, length)
|
|
293
|
+
str = str[0, length] if str.bytesize > length
|
|
294
|
+
str + (" " * (length - str.bytesize))
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Pad string with spaces (d-characters)
|
|
298
|
+
#
|
|
299
|
+
# @param str [String] String to pad
|
|
300
|
+
# @param length [Integer] Target length
|
|
301
|
+
# @return [String] Padded string
|
|
302
|
+
def pad_d_string(str, length)
|
|
303
|
+
pad_a_string(str, length)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Pad generic string
|
|
307
|
+
#
|
|
308
|
+
# @param str [String] String to pad
|
|
309
|
+
# @param length [Integer] Target length
|
|
310
|
+
# @return [String] Padded string
|
|
311
|
+
def pad_string(str, length)
|
|
312
|
+
str = str[0, length] if str.bytesize > length
|
|
313
|
+
padding = "\x00".encode(str.encoding) * (length - str.bytesize)
|
|
314
|
+
str + padding
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|