omnizip 0.4.7-x86_64-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.
Files changed (632) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +293 -0
  5. data/CHANGELOG.md +1647 -0
  6. data/CONTEXT.md +68 -0
  7. data/COPYING +502 -0
  8. data/Gemfile +19 -0
  9. data/LICENSE +12 -0
  10. data/README.adoc +1327 -0
  11. data/Rakefile +15 -0
  12. data/TODO.refactor/00-overview.md +67 -0
  13. data/TODO.refactor/01-registry-base-class.md +81 -0
  14. data/TODO.refactor/02-error-hierarchy.md +57 -0
  15. data/TODO.refactor/03-autoload-entry-point.md +69 -0
  16. data/TODO.refactor/04-filter-base-consolidation.md +49 -0
  17. data/TODO.refactor/05-send-private-methods.md +64 -0
  18. data/TODO.refactor/06-instance-variable-access.md +69 -0
  19. data/TODO.refactor/07-respond-to-replacement.md +237 -0
  20. data/TODO.refactor/08-spec-doubles.md +27 -0
  21. data/TODO.refactor/09-cli-shared-module.md +35 -0
  22. data/TODO.refactor/10-format-detector-ocp.md +34 -0
  23. data/TODO.refactor/11-convenience-decoupling.md +38 -0
  24. data/TODO.refactor/12-thread-safety.md +8 -0
  25. data/TODO.refactor/13-lutaml-model-migration.md +158 -0
  26. data/TODO.refactor/14-add-missing-specs.md +25 -0
  27. data/benchmark/README.md +260 -0
  28. data/benchmark/benchmark_suite.rb +125 -0
  29. data/benchmark/compression_bench.rb +181 -0
  30. data/benchmark/filter_bench.rb +180 -0
  31. data/benchmark/models/benchmark_result.rb +59 -0
  32. data/benchmark/models/comparison_result.rb +69 -0
  33. data/benchmark/profile_suite.rb +167 -0
  34. data/benchmark/reporter.rb +150 -0
  35. data/benchmark/run_benchmarks.rb +66 -0
  36. data/benchmark/test_data.rb +137 -0
  37. data/config/formats/rar3_spec.yml +92 -0
  38. data/config/formats/rar5_spec.yml +102 -0
  39. data/docs/.github/workflows/docs.yml +142 -0
  40. data/docs/.gitignore +21 -0
  41. data/docs/.lychee.toml +67 -0
  42. data/docs/Gemfile +13 -0
  43. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  44. data/docs/README.md +101 -0
  45. data/docs/_config.yml +112 -0
  46. data/docs/assets/logo.svg +1 -0
  47. data/docs/assets/omnizip-logo.pdf +1540 -11
  48. data/docs/comparison/feature-matrix.adoc +694 -0
  49. data/docs/comparison/index.adoc +113 -0
  50. data/docs/comparison/vs-7zip.adoc +309 -0
  51. data/docs/comparison/vs-peazip.adoc +77 -0
  52. data/docs/comparison/vs-rubyzip.adoc +342 -0
  53. data/docs/comparison/vs-winrar.adoc +100 -0
  54. data/docs/compatibility.adoc +579 -0
  55. data/docs/concepts/index.adoc +129 -0
  56. data/docs/developer/architecture.adoc +256 -0
  57. data/docs/developer/contributing.adoc +158 -0
  58. data/docs/developer/index.adoc +25 -0
  59. data/docs/developer/testing.adoc +212 -0
  60. data/docs/getting-started/basic-usage.adoc +263 -0
  61. data/docs/getting-started/index.adoc +42 -0
  62. data/docs/getting-started/installation.adoc +138 -0
  63. data/docs/getting-started/quick-start.adoc +183 -0
  64. data/docs/getting-started/your-first-archive.adoc +219 -0
  65. data/docs/guides/advanced-features/encryption.adoc +277 -0
  66. data/docs/guides/advanced-features/index.adoc +59 -0
  67. data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
  68. data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
  69. data/docs/guides/advanced-features/streaming.adoc +142 -0
  70. data/docs/guides/archive-formats/gzip-format.adoc +105 -0
  71. data/docs/guides/archive-formats/index.adoc +160 -0
  72. data/docs/guides/archive-formats/ole-format.adoc +151 -0
  73. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  74. data/docs/guides/archive-formats/rar5.adoc +521 -0
  75. data/docs/guides/archive-formats/rpm-format.adoc +108 -0
  76. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  77. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  78. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  79. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  80. data/docs/guides/compression-algorithms/bzip2.adoc +114 -0
  81. data/docs/guides/compression-algorithms/deflate.adoc +313 -0
  82. data/docs/guides/compression-algorithms/index.adoc +190 -0
  83. data/docs/guides/compression-algorithms/lzma.adoc +394 -0
  84. data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
  85. data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
  86. data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
  87. data/docs/guides/creating-archives.adoc +348 -0
  88. data/docs/guides/extracting-archives.adoc +53 -0
  89. data/docs/guides/format-conversion.adoc +64 -0
  90. data/docs/guides/index.adoc +49 -0
  91. data/docs/guides/migration-rubyzip.adoc +217 -0
  92. data/docs/guides/parity-archives.adoc +605 -0
  93. data/docs/guides/performance-tuning.adoc +88 -0
  94. data/docs/index.adoc +228 -0
  95. data/docs/lychee.toml +67 -0
  96. data/docs/reference/api/overview.adoc +187 -0
  97. data/docs/reference/cli/compress-command.adoc +114 -0
  98. data/docs/reference/cli/overview.adoc +140 -0
  99. data/docs/reference/index.adoc +26 -0
  100. data/docs/resources/faq.adoc +185 -0
  101. data/docs/resources/quick-reference.adoc +222 -0
  102. data/docs/rust-backend.md +0 -0
  103. data/docs/troubleshooting/index.adoc +207 -0
  104. data/docs/xar_format.md +216 -0
  105. data/examples/api_comparison.rb +205 -0
  106. data/examples/deflate64_example.rb +96 -0
  107. data/examples/par2_demo.rb +121 -0
  108. data/examples/quick_start_native.rb +150 -0
  109. data/examples/quick_start_rubyzip.rb +115 -0
  110. data/examples/rubyzip_compatibility_demo.rb +194 -0
  111. data/exe/omnizip +27 -0
  112. data/lib/omnizip/algorithm.rb +176 -0
  113. data/lib/omnizip/algorithm_registry.rb +65 -0
  114. data/lib/omnizip/algorithms/.keep +0 -0
  115. data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
  116. data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
  117. data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
  118. data/lib/omnizip/algorithms/bzip2.rb +108 -0
  119. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  120. data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
  121. data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
  122. data/lib/omnizip/algorithms/deflate.rb +135 -0
  123. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  124. data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
  125. data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
  126. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
  127. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
  128. data/lib/omnizip/algorithms/deflate64.rb +118 -0
  129. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  130. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  131. data/lib/omnizip/algorithms/lzma/decoder.rb +146 -0
  132. data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
  133. data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
  134. data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
  135. data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
  136. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
  137. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
  138. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
  139. data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
  140. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -0
  141. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  142. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  143. data/lib/omnizip/algorithms/lzma/match_finder.rb +233 -0
  144. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  145. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
  146. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
  147. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  148. data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
  149. data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
  150. data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
  151. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  152. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
  153. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
  154. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
  155. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
  156. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
  157. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
  158. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  159. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
  160. data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
  161. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
  162. data/lib/omnizip/algorithms/lzma.rb +266 -0
  163. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
  164. data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
  165. data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
  166. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
  167. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  168. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
  169. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  170. data/lib/omnizip/algorithms/lzma2.rb +133 -0
  171. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  172. data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
  173. data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
  174. data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
  175. data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
  176. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  177. data/lib/omnizip/algorithms/ppmd7.rb +146 -0
  178. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  179. data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
  180. data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
  181. data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
  182. data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
  183. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  184. data/lib/omnizip/algorithms/ppmd8.rb +122 -0
  185. data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
  186. data/lib/omnizip/algorithms/registration.rb +28 -0
  187. data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
  188. data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
  189. data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
  190. data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
  191. data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
  192. data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
  193. data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
  194. data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
  195. data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
  196. data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
  197. data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
  198. data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
  199. data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
  200. data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
  201. data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
  202. data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
  203. data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
  204. data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
  205. data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
  206. data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
  207. data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
  208. data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
  209. data/lib/omnizip/algorithms/zstandard.rb +210 -0
  210. data/lib/omnizip/algorithms.rb +35 -0
  211. data/lib/omnizip/archive/builder.rb +48 -0
  212. data/lib/omnizip/archive/reader_session.rb +67 -0
  213. data/lib/omnizip/archive.rb +86 -0
  214. data/lib/omnizip/archive_handler.rb +82 -0
  215. data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
  216. data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
  217. data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
  218. data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
  219. data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
  220. data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
  221. data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
  222. data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
  223. data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
  224. data/lib/omnizip/archive_handlers.rb +18 -0
  225. data/lib/omnizip/backends.rb +160 -0
  226. data/lib/omnizip/buffer/memory_archive.rb +246 -0
  227. data/lib/omnizip/buffer/memory_extractor.rb +234 -0
  228. data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
  229. data/lib/omnizip/buffer.rb +187 -0
  230. data/lib/omnizip/checksum_registry.rb +41 -0
  231. data/lib/omnizip/checksums/crc32.rb +101 -0
  232. data/lib/omnizip/checksums/crc64.rb +102 -0
  233. data/lib/omnizip/checksums/crc_base.rb +158 -0
  234. data/lib/omnizip/checksums/registration.rb +16 -0
  235. data/lib/omnizip/checksums/verifier.rb +130 -0
  236. data/lib/omnizip/checksums.rb +11 -0
  237. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  238. data/lib/omnizip/chunked/reader.rb +78 -0
  239. data/lib/omnizip/chunked/writer.rb +123 -0
  240. data/lib/omnizip/chunked.rb +123 -0
  241. data/lib/omnizip/cli/output_formatter.rb +112 -0
  242. data/lib/omnizip/cli.rb +604 -0
  243. data/lib/omnizip/commands/.keep +0 -0
  244. data/lib/omnizip/commands/archive_create_command.rb +245 -0
  245. data/lib/omnizip/commands/archive_extract_command.rb +231 -0
  246. data/lib/omnizip/commands/archive_list_command.rb +204 -0
  247. data/lib/omnizip/commands/archive_repair_command.rb +129 -0
  248. data/lib/omnizip/commands/archive_verify_command.rb +115 -0
  249. data/lib/omnizip/commands/compress_command.rb +115 -0
  250. data/lib/omnizip/commands/decompress_command.rb +149 -0
  251. data/lib/omnizip/commands/list_command.rb +51 -0
  252. data/lib/omnizip/commands/metadata_command.rb +215 -0
  253. data/lib/omnizip/commands/parity_create_command.rb +114 -0
  254. data/lib/omnizip/commands/parity_repair_command.rb +120 -0
  255. data/lib/omnizip/commands/parity_verify_command.rb +122 -0
  256. data/lib/omnizip/commands/profile_list_command.rb +54 -0
  257. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  258. data/lib/omnizip/commands.rb +21 -0
  259. data/lib/omnizip/convenience.rb +389 -0
  260. data/lib/omnizip/converter/conversion_registry.rb +50 -0
  261. data/lib/omnizip/converter/conversion_strategy.rb +108 -0
  262. data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
  263. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
  264. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
  265. data/lib/omnizip/converter.rb +124 -0
  266. data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
  267. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  268. data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
  269. data/lib/omnizip/crypto/aes256.rb +102 -0
  270. data/lib/omnizip/crypto.rb +11 -0
  271. data/lib/omnizip/entry.rb +44 -0
  272. data/lib/omnizip/error.rb +110 -0
  273. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
  274. data/lib/omnizip/eta/moving_average_estimator.rb +96 -0
  275. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  276. data/lib/omnizip/eta/sample_history.rb +143 -0
  277. data/lib/omnizip/eta/time_estimator.rb +106 -0
  278. data/lib/omnizip/eta.rb +68 -0
  279. data/lib/omnizip/extraction/filter_chain.rb +179 -0
  280. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  281. data/lib/omnizip/extraction/pattern_matcher.rb +66 -0
  282. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  283. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  284. data/lib/omnizip/extraction/selective_extractor.rb +247 -0
  285. data/lib/omnizip/extraction.rb +115 -0
  286. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  287. data/lib/omnizip/file_type.rb +117 -0
  288. data/lib/omnizip/filter.rb +141 -0
  289. data/lib/omnizip/filter_pipeline.rb +108 -0
  290. data/lib/omnizip/filter_registry.rb +113 -0
  291. data/lib/omnizip/filters/bcj.rb +277 -0
  292. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  293. data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
  294. data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
  295. data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
  296. data/lib/omnizip/filters/bcj2.rb +93 -0
  297. data/lib/omnizip/filters/bcj_arm.rb +174 -0
  298. data/lib/omnizip/filters/bcj_arm64.rb +242 -0
  299. data/lib/omnizip/filters/bcj_ia64.rb +194 -0
  300. data/lib/omnizip/filters/bcj_ppc.rb +188 -0
  301. data/lib/omnizip/filters/bcj_sparc.rb +174 -0
  302. data/lib/omnizip/filters/bcj_x86.rb +191 -0
  303. data/lib/omnizip/filters/delta.rb +195 -0
  304. data/lib/omnizip/filters/xz_delta.rb +258 -0
  305. data/lib/omnizip/filters.rb +20 -0
  306. data/lib/omnizip/format_detector.rb +166 -0
  307. data/lib/omnizip/formats/.keep +0 -0
  308. data/lib/omnizip/formats/bzip2_file.rb +159 -0
  309. data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
  310. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  311. data/lib/omnizip/formats/cpio/entry.rb +389 -0
  312. data/lib/omnizip/formats/cpio/reader.rb +194 -0
  313. data/lib/omnizip/formats/cpio/writer.rb +232 -0
  314. data/lib/omnizip/formats/cpio.rb +132 -0
  315. data/lib/omnizip/formats/format_spec_loader.rb +228 -0
  316. data/lib/omnizip/formats/gzip.rb +236 -0
  317. data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
  318. data/lib/omnizip/formats/iso/directory_record.rb +162 -0
  319. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  320. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  321. data/lib/omnizip/formats/iso/reader.rb +194 -0
  322. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  323. data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
  324. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  325. data/lib/omnizip/formats/iso/writer.rb +543 -0
  326. data/lib/omnizip/formats/iso.rb +133 -0
  327. data/lib/omnizip/formats/lzip.rb +161 -0
  328. data/lib/omnizip/formats/lzma_alone.rb +149 -0
  329. data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
  330. data/lib/omnizip/formats/msi/constants.rb +157 -0
  331. data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
  332. data/lib/omnizip/formats/msi/entry.rb +134 -0
  333. data/lib/omnizip/formats/msi/reader.rb +301 -0
  334. data/lib/omnizip/formats/msi/string_pool.rb +246 -0
  335. data/lib/omnizip/formats/msi/table_parser.rb +244 -0
  336. data/lib/omnizip/formats/msi.rb +73 -0
  337. data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
  338. data/lib/omnizip/formats/ole/constants.rb +61 -0
  339. data/lib/omnizip/formats/ole/dirent.rb +439 -0
  340. data/lib/omnizip/formats/ole/header.rb +199 -0
  341. data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
  342. data/lib/omnizip/formats/ole/storage.rb +482 -0
  343. data/lib/omnizip/formats/ole/types/variant.rb +338 -0
  344. data/lib/omnizip/formats/ole.rb +143 -0
  345. data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
  346. data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
  347. data/lib/omnizip/formats/rar/block_parser.rb +282 -0
  348. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  349. data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
  350. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
  351. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -0
  352. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  353. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  354. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  355. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  356. data/lib/omnizip/formats/rar/compression/lz77_huffman.rb +25 -0
  357. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
  358. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
  359. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
  360. data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
  361. data/lib/omnizip/formats/rar/compression.rb +17 -0
  362. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  363. data/lib/omnizip/formats/rar/constants.rb +88 -0
  364. data/lib/omnizip/formats/rar/decompressor.rb +316 -0
  365. data/lib/omnizip/formats/rar/external_writer.rb +311 -0
  366. data/lib/omnizip/formats/rar/header.rb +209 -0
  367. data/lib/omnizip/formats/rar/license_validator.rb +111 -0
  368. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  369. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  370. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  371. data/lib/omnizip/formats/rar/models.rb +14 -0
  372. data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
  373. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
  374. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -0
  375. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  376. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  377. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +96 -0
  378. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  379. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
  380. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  381. data/lib/omnizip/formats/rar/rar5/header.rb +208 -0
  382. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  383. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  384. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  385. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  386. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  387. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +260 -0
  388. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  389. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +176 -0
  390. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
  391. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
  392. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  393. data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
  394. data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
  395. data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
  396. data/lib/omnizip/formats/rar/reader.rb +377 -0
  397. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  398. data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
  399. data/lib/omnizip/formats/rar/writer.rb +437 -0
  400. data/lib/omnizip/formats/rar.rb +193 -0
  401. data/lib/omnizip/formats/rar3/compressor.rb +71 -0
  402. data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
  403. data/lib/omnizip/formats/rar3/reader.rb +107 -0
  404. data/lib/omnizip/formats/rar3/writer.rb +220 -0
  405. data/lib/omnizip/formats/rar3.rb +15 -0
  406. data/lib/omnizip/formats/rar5/compressor.rb +71 -0
  407. data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
  408. data/lib/omnizip/formats/rar5/reader.rb +130 -0
  409. data/lib/omnizip/formats/rar5/writer.rb +65 -0
  410. data/lib/omnizip/formats/rar5.rb +15 -0
  411. data/lib/omnizip/formats/rpm/constants.rb +58 -0
  412. data/lib/omnizip/formats/rpm/entry.rb +106 -0
  413. data/lib/omnizip/formats/rpm/header.rb +106 -0
  414. data/lib/omnizip/formats/rpm/lead.rb +132 -0
  415. data/lib/omnizip/formats/rpm/tag.rb +228 -0
  416. data/lib/omnizip/formats/rpm/writer.rb +652 -0
  417. data/lib/omnizip/formats/rpm.rb +458 -0
  418. data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
  419. data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
  420. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  421. data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
  422. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
  423. data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
  424. data/lib/omnizip/formats/seven_zip/header.rb +102 -0
  425. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
  426. data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
  427. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  428. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
  429. data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
  430. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  431. data/lib/omnizip/formats/seven_zip/models.rb +20 -0
  432. data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
  433. data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
  434. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
  435. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
  436. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  437. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
  438. data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
  439. data/lib/omnizip/formats/seven_zip.rb +179 -0
  440. data/lib/omnizip/formats/tar/constants.rb +73 -0
  441. data/lib/omnizip/formats/tar/entry.rb +98 -0
  442. data/lib/omnizip/formats/tar/header.rb +206 -0
  443. data/lib/omnizip/formats/tar/reader.rb +119 -0
  444. data/lib/omnizip/formats/tar/writer.rb +212 -0
  445. data/lib/omnizip/formats/tar.rb +74 -0
  446. data/lib/omnizip/formats/xar/constants.rb +119 -0
  447. data/lib/omnizip/formats/xar/entry.rb +268 -0
  448. data/lib/omnizip/formats/xar/header.rb +223 -0
  449. data/lib/omnizip/formats/xar/reader.rb +400 -0
  450. data/lib/omnizip/formats/xar/toc.rb +570 -0
  451. data/lib/omnizip/formats/xar/writer.rb +461 -0
  452. data/lib/omnizip/formats/xar.rb +145 -0
  453. data/lib/omnizip/formats/xz/reader.rb +121 -0
  454. data/lib/omnizip/formats/xz/writer.rb +416 -0
  455. data/lib/omnizip/formats/xz.rb +210 -0
  456. data/lib/omnizip/formats/xz_const.rb +49 -0
  457. data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
  458. data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
  459. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  460. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
  461. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  462. data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
  463. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
  464. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
  465. data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
  466. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
  467. data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
  468. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
  469. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  470. data/lib/omnizip/formats/xz_impl.rb +52 -0
  471. data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
  472. data/lib/omnizip/formats/zip/constants.rb +69 -0
  473. data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
  474. data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
  475. data/lib/omnizip/formats/zip/reader.rb +376 -0
  476. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  477. data/lib/omnizip/formats/zip/writer.rb +489 -0
  478. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
  479. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
  480. data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
  481. data/lib/omnizip/formats/zip.rb +50 -0
  482. data/lib/omnizip/formats.rb +29 -0
  483. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  484. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  485. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  486. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  487. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  488. data/lib/omnizip/implementations/base.rb +19 -0
  489. data/lib/omnizip/implementations/rust/archive.rb +93 -0
  490. data/lib/omnizip/implementations/rust/library.rb +221 -0
  491. data/lib/omnizip/implementations/rust.rb +26 -0
  492. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
  493. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
  494. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
  495. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
  496. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
  497. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
  498. data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
  499. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
  500. data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
  501. data/lib/omnizip/implementations/seven_zip.rb +11 -0
  502. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
  503. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
  504. data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
  505. data/lib/omnizip/implementations/xz_utils.rb +10 -0
  506. data/lib/omnizip/implementations.rb +25 -0
  507. data/lib/omnizip/io/buffered_input.rb +147 -0
  508. data/lib/omnizip/io/buffered_output.rb +106 -0
  509. data/lib/omnizip/io/source.rb +143 -0
  510. data/lib/omnizip/io/stream_manager.rb +117 -0
  511. data/lib/omnizip/io.rb +15 -0
  512. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  513. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  514. data/lib/omnizip/link_handler.rb +129 -0
  515. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  516. data/lib/omnizip/metadata/entry_metadata.rb +153 -0
  517. data/lib/omnizip/metadata/metadata_editor.rb +169 -0
  518. data/lib/omnizip/metadata/metadata_registry.rb +71 -0
  519. data/lib/omnizip/metadata/metadata_validator.rb +101 -0
  520. data/lib/omnizip/metadata.rb +58 -0
  521. data/lib/omnizip/models/.keep +0 -0
  522. data/lib/omnizip/models/algorithm_metadata.rb +41 -0
  523. data/lib/omnizip/models/attribute_apply.rb +40 -0
  524. data/lib/omnizip/models/compression_options.rb +53 -0
  525. data/lib/omnizip/models/conversion_options.rb +79 -0
  526. data/lib/omnizip/models/conversion_result.rb +141 -0
  527. data/lib/omnizip/models/eta_result.rb +45 -0
  528. data/lib/omnizip/models/extraction_rule.rb +115 -0
  529. data/lib/omnizip/models/filter_chain.rb +142 -0
  530. data/lib/omnizip/models/filter_config.rb +148 -0
  531. data/lib/omnizip/models/match_result.rb +141 -0
  532. data/lib/omnizip/models/optimization_suggestion.rb +95 -0
  533. data/lib/omnizip/models/parallel_options.rb +116 -0
  534. data/lib/omnizip/models/performance_result.rb +85 -0
  535. data/lib/omnizip/models/profile_report.rb +116 -0
  536. data/lib/omnizip/models/progress_options.rb +39 -0
  537. data/lib/omnizip/models/split_options.rb +116 -0
  538. data/lib/omnizip/optimization_registry.rb +45 -0
  539. data/lib/omnizip/parallel/engine.rb +52 -0
  540. data/lib/omnizip/parallel/job_queue.rb +209 -0
  541. data/lib/omnizip/parallel/job_scheduler.rb +225 -0
  542. data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
  543. data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
  544. data/lib/omnizip/parallel/thread_pool.rb +60 -0
  545. data/lib/omnizip/parallel/worker_pool.rb +227 -0
  546. data/lib/omnizip/parallel.rb +156 -0
  547. data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
  548. data/lib/omnizip/parity/galois16.rb +145 -0
  549. data/lib/omnizip/parity/models/creator_packet.rb +71 -0
  550. data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
  551. data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
  552. data/lib/omnizip/parity/models/main_packet.rb +126 -0
  553. data/lib/omnizip/parity/models/packet.rb +156 -0
  554. data/lib/omnizip/parity/models/packet_registry.rb +102 -0
  555. data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
  556. data/lib/omnizip/parity/models.rb +27 -0
  557. data/lib/omnizip/parity/par2_creator.rb +496 -0
  558. data/lib/omnizip/parity/par2_repairer.rb +409 -0
  559. data/lib/omnizip/parity/par2_verifier.rb +373 -0
  560. data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
  561. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  562. data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
  563. data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
  564. data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
  565. data/lib/omnizip/parity.rb +207 -0
  566. data/lib/omnizip/password/encryption_registry.rb +26 -0
  567. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  568. data/lib/omnizip/password/password_validator.rb +129 -0
  569. data/lib/omnizip/password/winzip_aes_strategy.rb +190 -0
  570. data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
  571. data/lib/omnizip/password.rb +88 -0
  572. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  573. data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
  574. data/lib/omnizip/pipe.rb +120 -0
  575. data/lib/omnizip/platform/ntfs_streams.rb +200 -0
  576. data/lib/omnizip/platform.rb +189 -0
  577. data/lib/omnizip/profile/archive_profile.rb +36 -0
  578. data/lib/omnizip/profile/balanced_profile.rb +31 -0
  579. data/lib/omnizip/profile/binary_profile.rb +33 -0
  580. data/lib/omnizip/profile/compression_profile.rb +157 -0
  581. data/lib/omnizip/profile/custom_profile.rb +155 -0
  582. data/lib/omnizip/profile/fast_profile.rb +31 -0
  583. data/lib/omnizip/profile/maximum_profile.rb +31 -0
  584. data/lib/omnizip/profile/profile_detector.rb +108 -0
  585. data/lib/omnizip/profile/profile_registry.rb +160 -0
  586. data/lib/omnizip/profile/text_profile.rb +33 -0
  587. data/lib/omnizip/profile.rb +261 -0
  588. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  589. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  590. data/lib/omnizip/profiler/report_generator.rb +158 -0
  591. data/lib/omnizip/profiler.rb +192 -0
  592. data/lib/omnizip/progress/callback_reporter.rb +34 -0
  593. data/lib/omnizip/progress/console_reporter.rb +59 -0
  594. data/lib/omnizip/progress/log_reporter.rb +89 -0
  595. data/lib/omnizip/progress/operation_progress.rb +118 -0
  596. data/lib/omnizip/progress/progress_bar.rb +156 -0
  597. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  598. data/lib/omnizip/progress/progress_tracker.rb +215 -0
  599. data/lib/omnizip/progress/silent_reporter.rb +22 -0
  600. data/lib/omnizip/progress.rb +131 -0
  601. data/lib/omnizip/registry.rb +111 -0
  602. data/lib/omnizip/rubyzip_compat.rb +61 -0
  603. data/lib/omnizip/temp/safe_extract.rb +124 -0
  604. data/lib/omnizip/temp/temp_file.rb +123 -0
  605. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  606. data/lib/omnizip/temp.rb +184 -0
  607. data/lib/omnizip/version.rb +5 -0
  608. data/lib/omnizip/zip/entry.rb +160 -0
  609. data/lib/omnizip/zip/file.rb +485 -0
  610. data/lib/omnizip/zip/input_stream.rb +270 -0
  611. data/lib/omnizip/zip/output_stream.rb +320 -0
  612. data/lib/omnizip/zip.rb +23 -0
  613. data/lib/omnizip.rb +157 -0
  614. data/lib/tasks/msi_test_files.rake +66 -0
  615. data/lib/tasks/platform_gems.rake +147 -0
  616. data/lib/tasks/rust_backend.rake +48 -0
  617. data/readme-docs/advanced-features.adoc +514 -0
  618. data/readme-docs/api-usage.adoc +445 -0
  619. data/readme-docs/architecture.adoc +450 -0
  620. data/readme-docs/archive-formats.adoc +479 -0
  621. data/readme-docs/cli-usage.adoc +222 -0
  622. data/readme-docs/compression-algorithms.adoc +446 -0
  623. data/readme-docs/compression-profiles.adoc +247 -0
  624. data/readme-docs/encryption-checksums.adoc +328 -0
  625. data/readme-docs/format-converter.adoc +316 -0
  626. data/readme-docs/installation.adoc +228 -0
  627. data/readme-docs/par2-archives.adoc +608 -0
  628. data/readme-docs/performance-profiler.adoc +389 -0
  629. data/readme-docs/preprocessing-filters.adoc +280 -0
  630. data/vendor/libomnizip_ffi.so +0 -0
  631. data/xz-file-format-1.2.1.txt +1174 -0
  632. metadata +768 -0
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ # .7z archive format support
6
+ # Provides read and write access to 7-Zip archives
7
+ #
8
+ # This module implements the .7z archive format specification,
9
+ # supporting:
10
+ # - Format signature and header validation
11
+ # - Archive structure parsing
12
+ # - File extraction
13
+ # - Archive creation
14
+ # - Split archives (multi-volume)
15
+ module SevenZip
16
+ # Nested classes - autoloaded
17
+ autoload :Constants, "omnizip/formats/seven_zip/constants"
18
+ autoload :Header, "omnizip/formats/seven_zip/header"
19
+ autoload :Parser, "omnizip/formats/seven_zip/parser"
20
+ autoload :Reader, "omnizip/formats/seven_zip/reader"
21
+ autoload :Writer, "omnizip/formats/seven_zip/writer"
22
+ autoload :CoderChain, "omnizip/formats/seven_zip/coder_chain"
23
+ autoload :StreamDecompressor,
24
+ "omnizip/formats/seven_zip/stream_decompressor"
25
+ autoload :StreamCompressor, "omnizip/formats/seven_zip/stream_compressor"
26
+ autoload :FileCollector, "omnizip/formats/seven_zip/file_collector"
27
+ autoload :HeaderWriter, "omnizip/formats/seven_zip/header_writer"
28
+ autoload :SplitArchiveReader,
29
+ "omnizip/formats/seven_zip/split_archive_reader"
30
+ autoload :SplitArchiveWriter,
31
+ "omnizip/formats/seven_zip/split_archive_writer"
32
+ autoload :HeaderEncryptor, "omnizip/formats/seven_zip/header_encryptor"
33
+ autoload :EncryptedHeader, "omnizip/formats/seven_zip/encrypted_header"
34
+ autoload :EncodedHeader, "omnizip/formats/seven_zip/encoded_header"
35
+ autoload :Bcj2StreamDecompressor,
36
+ "omnizip/formats/seven_zip/bcj2_stream_decompressor"
37
+ module Models
38
+ autoload :StreamInfo, "omnizip/formats/seven_zip/models/stream_info"
39
+ autoload :FileEntry, "omnizip/formats/seven_zip/models/file_entry"
40
+ autoload :Folder, "omnizip/formats/seven_zip/models/folder"
41
+ autoload :CoderInfo, "omnizip/formats/seven_zip/models/coder_info"
42
+ end
43
+ # Add autoload for Models namespace itself
44
+ autoload :Models, "omnizip/formats/seven_zip/models"
45
+
46
+ # Cross-namespace dependencies - autoloaded
47
+ autoload :Crc32, "omnizip/checksums/crc32"
48
+ autoload :LZMA2, "omnizip/algorithms/lzma2"
49
+ autoload :AlgorithmRegistry, "omnizip/algorithm_registry"
50
+ autoload :FilterRegistry, "omnizip/filter_registry"
51
+ autoload :FilterPipeline, "omnizip/filter_pipeline"
52
+ autoload :Bcj2Decoder, "omnizip/filters/bcj2/decoder"
53
+ autoload :Bcj2StreamData, "omnizip/filters/bcj2/stream_data"
54
+
55
+ # Create a new .7z archive
56
+ #
57
+ # @param path [String] Output path
58
+ # @param options [Hash] Compression options
59
+ # @option options [Integer] :volume_size Volume size for split archives
60
+ # @option options [String] :password Password for header encryption
61
+ # @option options [Boolean] :encrypt_headers Encrypt archive headers
62
+ # @yield [writer] Block for adding files
63
+ # @yieldparam writer [Writer] Archive writer
64
+ def self.create(path, options = {})
65
+ writer = Writer.new(path, options)
66
+ yield writer if block_given?
67
+ writer.write
68
+ writer
69
+ end
70
+
71
+ # Create a split .7z archive
72
+ #
73
+ # @param path [String] Base path (e.g., "backup.7z.001")
74
+ # @param split_options [Models::SplitOptions] Split configuration
75
+ # @param options [Hash] Compression options
76
+ # @yield [writer] Block for adding files
77
+ # @yieldparam writer [SplitArchiveWriter] Archive writer
78
+ def self.create_split(path, split_options, options = {})
79
+ writer = SplitArchiveWriter.new(path, options, split_options)
80
+ yield writer if block_given?
81
+ writer.write
82
+ writer
83
+ end
84
+
85
+ # Open existing .7z archive
86
+ #
87
+ # @param path [String] Archive path
88
+ # @param options [Hash] Reader options
89
+ # @option options [String] :password Password for encrypted headers
90
+ # @yield [reader] Block for reading archive
91
+ # @yieldparam reader [Reader] Archive reader
92
+ # @return [Reader] Archive reader
93
+ def self.open(path, options = {})
94
+ reader = Reader.new(path, options)
95
+ reader.open
96
+
97
+ if block_given?
98
+ begin
99
+ yield reader
100
+ ensure
101
+ reader.split_reader&.close
102
+ end
103
+ end
104
+
105
+ reader
106
+ end
107
+
108
+ # Search for embedded .7z archive in self-extracting executable
109
+ #
110
+ # Scans the file for 7z signatures and validates each candidate by
111
+ # checking the Start Header (version bytes, CRC, and header field
112
+ # sanity). Returns the offset of the first valid embedded archive.
113
+ #
114
+ # @param path [String] Path to potential self-extracting archive
115
+ # @return [Integer, nil] Offset of embedded 7z signature, or nil if not found
116
+ def self.search_embedded(path)
117
+ data = File.binread(path)
118
+ file_size = data.bytesize
119
+ signature = Constants::SIGNATURE
120
+ pos = 0
121
+
122
+ while (offset = data.index(signature, pos))
123
+ if valid_7z_start_header?(data, offset, file_size)
124
+ return offset
125
+ end
126
+
127
+ pos = offset + 1
128
+ end
129
+
130
+ nil
131
+ end
132
+
133
+ # Validate a candidate 7z Start Header at the given offset.
134
+ #
135
+ # Checks:
136
+ # 1. Enough bytes remain for a full 32-byte Start Header
137
+ # 2. Major version is 0 and minor version is 4 (only supported version)
138
+ # 3. Next Header offset + size points within (or at the end of) the file
139
+ # 4. Start Header CRC matches the header content
140
+ #
141
+ # @param data [String] File data
142
+ # @param offset [Integer] Offset of the 7z signature
143
+ # @param file_size [Integer] Total file size
144
+ # @return [Boolean] true if the header looks valid
145
+ def self.valid_7z_start_header?(data, offset, file_size)
146
+ header_size = Constants::START_HEADER_SIZE # 32
147
+ return false if offset + header_size > file_size
148
+
149
+ header_data = data.byteslice(offset, header_size)
150
+
151
+ # Check version byte (offset 6) - only major version is validated per 7-Zip SDK
152
+ # See: https://github.com/ip7z/7zip/blob/main/CPP/7zip/Archive/7z/7zIn.cpp#L1591-L1598
153
+ major_version = header_data.getbyte(6)
154
+ return false unless major_version == Constants::MAJOR_VERSION
155
+
156
+ # Parse Start Header fields (bytes 12-31)
157
+ next_header_data = header_data.byteslice(12, 20)
158
+ next_header_offset = next_header_data.unpack1("Q<")
159
+ next_header_size = next_header_data.byteslice(8, 8).unpack1("Q<")
160
+
161
+ # next_header_offset is relative to end of Start Header
162
+ header_end = offset + header_size + next_header_offset + next_header_size
163
+ return false if header_end > file_size
164
+ return false if next_header_size.zero? || next_header_size > file_size
165
+
166
+ # Validate Start Header CRC (bytes 8-11) over next_header_data (bytes 12-31)
167
+ stored_crc = header_data.byteslice(8, 4).unpack1("V")
168
+ computed_crc = Omnizip::Checksums::Crc32.new.tap do |c|
169
+ c.update(next_header_data)
170
+ end.finalize
171
+ return false unless stored_crc == computed_crc
172
+
173
+ true
174
+ rescue StandardError
175
+ false
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module Tar
6
+ # TAR format constants
7
+ module Constants
8
+ # TAR header size (POSIX ustar format)
9
+ HEADER_SIZE = 512
10
+
11
+ # Block size for TAR archives
12
+ BLOCK_SIZE = 512
13
+
14
+ # Type flags for TAR entries
15
+ TYPE_REGULAR = "0" # Regular file
16
+ TYPE_HARD_LINK = "1" # Hard link
17
+ TYPE_SYMLINK = "2" # Symbolic link
18
+ TYPE_CHAR_DEVICE = "3" # Character device
19
+ TYPE_BLOCK_DEVICE = "4" # Block device
20
+ TYPE_DIRECTORY = "5" # Directory
21
+ TYPE_FIFO = "6" # FIFO
22
+ TYPE_CONTIGUOUS = "7" # Contiguous file
23
+ TYPE_EXTENDED = "x" # Extended header
24
+ TYPE_GLOBAL_EXTENDED = "g" # Global extended header
25
+ TYPE_GNU_LONGNAME = "L" # GNU long name
26
+ TYPE_GNU_LONGLINK = "K" # GNU long link
27
+
28
+ # POSIX ustar magic value
29
+ USTAR_MAGIC = "ustar"
30
+
31
+ # POSIX ustar version
32
+ USTAR_VERSION = "00"
33
+
34
+ # Maximum file size (8GB - 1 for base-8 12-byte field)
35
+ MAX_FILE_SIZE = (8**12) - 1
36
+
37
+ # Field positions in TAR header
38
+ NAME_OFFSET = 0
39
+ NAME_SIZE = 100
40
+ MODE_OFFSET = 100
41
+ MODE_SIZE = 8
42
+ UID_OFFSET = 108
43
+ UID_SIZE = 8
44
+ GID_OFFSET = 116
45
+ GID_SIZE = 8
46
+ SIZE_OFFSET = 124
47
+ SIZE_SIZE = 12
48
+ MTIME_OFFSET = 136
49
+ MTIME_SIZE = 12
50
+ CHECKSUM_OFFSET = 148
51
+ CHECKSUM_SIZE = 8
52
+ TYPEFLAG_OFFSET = 156
53
+ TYPEFLAG_SIZE = 1
54
+ LINKNAME_OFFSET = 157
55
+ LINKNAME_SIZE = 100
56
+ MAGIC_OFFSET = 257
57
+ MAGIC_SIZE = 6
58
+ VERSION_OFFSET = 263
59
+ VERSION_SIZE = 2
60
+ UNAME_OFFSET = 265
61
+ UNAME_SIZE = 32
62
+ GNAME_OFFSET = 297
63
+ GNAME_SIZE = 32
64
+ DEVMAJOR_OFFSET = 329
65
+ DEVMAJOR_SIZE = 8
66
+ DEVMINOR_OFFSET = 337
67
+ DEVMINOR_SIZE = 8
68
+ PREFIX_OFFSET = 345
69
+ PREFIX_SIZE = 155
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module Tar
6
+ # TAR entry model
7
+ #
8
+ # Represents a single entry (file, directory, link) in a TAR archive
9
+ class Entry
10
+ include Omnizip::Entry
11
+ include Omnizip::Formats::Tar::Constants
12
+
13
+ attr_accessor :name, :mode, :uid, :gid, :size, :mtime, :typeflag,
14
+ :linkname, :uname, :gname, :devmajor, :devminor, :prefix
15
+ attr_reader :data
16
+
17
+ def entry_name = name
18
+ def entry_directory? = directory?
19
+ def entry_size = size
20
+ def entry_mtime = mtime
21
+
22
+ # Initialize a new TAR entry
23
+ #
24
+ # @param name [String] Entry name/path
25
+ # @param options [Hash] Entry options
26
+ def initialize(name, options = {})
27
+ @name = name
28
+ @mode = options[:mode] || 0o644
29
+ @uid = options[:uid] || 0
30
+ @gid = options[:gid] || 0
31
+ @size = options[:size] || 0
32
+ @mtime = options[:mtime] || Time.now
33
+ @typeflag = options[:typeflag] || TYPE_REGULAR
34
+ @linkname = options[:linkname] || ""
35
+ @uname = options[:uname] || ""
36
+ @gname = options[:gname] || ""
37
+ @devmajor = options[:devmajor] || 0
38
+ @devminor = options[:devminor] || 0
39
+ @prefix = options[:prefix] || ""
40
+ @data = nil
41
+ end
42
+
43
+ # Set entry data
44
+ #
45
+ # @param data [String] Entry data
46
+ def data=(data)
47
+ @data = data
48
+ @size = data.bytesize if data
49
+ end
50
+
51
+ # Check if entry is a directory
52
+ #
53
+ # @return [Boolean] true if directory
54
+ def directory?
55
+ @typeflag == TYPE_DIRECTORY
56
+ end
57
+
58
+ # Check if entry is a file
59
+ #
60
+ # @return [Boolean] true if regular file
61
+ def file?
62
+ @typeflag == TYPE_REGULAR || @typeflag.nil? || @typeflag.empty?
63
+ end
64
+
65
+ # Check if entry is a symbolic link
66
+ #
67
+ # @return [Boolean] true if symbolic link
68
+ def symlink?
69
+ @typeflag == TYPE_SYMLINK
70
+ end
71
+
72
+ # Get full entry name (prefix + name)
73
+ #
74
+ # @return [String] Full entry name
75
+ def full_name
76
+ if @prefix && !@prefix.empty?
77
+ File.join(@prefix, @name)
78
+ else
79
+ @name
80
+ end
81
+ end
82
+
83
+ # Calculate checksum for TAR header
84
+ #
85
+ # @param header [String] TAR header bytes
86
+ # @return [Integer] Checksum value
87
+ def self.calculate_checksum(header)
88
+ # Replace checksum field with spaces for calculation
89
+ checksum_header = header.dup
90
+ checksum_header[CHECKSUM_OFFSET, CHECKSUM_SIZE] = " " * CHECKSUM_SIZE
91
+
92
+ # Sum all bytes
93
+ checksum_header.bytes.sum
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module Tar
6
+ # TAR header parser (POSIX ustar format)
7
+ #
8
+ # Handles reading and writing 512-byte TAR headers
9
+ class Header
10
+ include Omnizip::Formats::Tar::Constants
11
+
12
+ # Parse a TAR header from binary data
13
+ #
14
+ # @param header_data [String] 512 bytes of header data
15
+ # @return [Entry, nil] Parsed entry or nil if end of archive
16
+ def self.parse(header_data)
17
+ return nil if header_data.nil? || header_data.bytesize < HEADER_SIZE
18
+ return nil if all_zeros?(header_data)
19
+
20
+ entry = Entry.new("")
21
+
22
+ # Extract fields from header
23
+ entry.name = extract_string(header_data, NAME_OFFSET, NAME_SIZE)
24
+ entry.mode = extract_octal(header_data, MODE_OFFSET, MODE_SIZE)
25
+ entry.uid = extract_octal(header_data, UID_OFFSET, UID_SIZE)
26
+ entry.gid = extract_octal(header_data, GID_OFFSET, GID_SIZE)
27
+ entry.size = extract_octal(header_data, SIZE_OFFSET, SIZE_SIZE)
28
+ entry.mtime = Time.at(
29
+ extract_octal(header_data, MTIME_OFFSET, MTIME_SIZE),
30
+ )
31
+ entry.typeflag = header_data[TYPEFLAG_OFFSET]
32
+ entry.linkname = extract_string(
33
+ header_data, LINKNAME_OFFSET, LINKNAME_SIZE
34
+ )
35
+
36
+ # Check for ustar format
37
+ magic = extract_string(header_data, MAGIC_OFFSET, MAGIC_SIZE)
38
+ if magic == USTAR_MAGIC
39
+ entry.uname = extract_string(header_data, UNAME_OFFSET, UNAME_SIZE)
40
+ entry.gname = extract_string(header_data, GNAME_OFFSET, GNAME_SIZE)
41
+ entry.devmajor = extract_octal(
42
+ header_data, DEVMAJOR_OFFSET, DEVMAJOR_SIZE
43
+ )
44
+ entry.devminor = extract_octal(
45
+ header_data, DEVMINOR_OFFSET, DEVMINOR_SIZE
46
+ )
47
+ entry.prefix = extract_string(
48
+ header_data, PREFIX_OFFSET, PREFIX_SIZE
49
+ )
50
+ # ustar stores long paths split across prefix + name;
51
+ # consumers see the joined path
52
+ unless entry.prefix.empty?
53
+ entry.name = "#{entry.prefix}/#{entry.name}"
54
+ end
55
+ end
56
+
57
+ # Verify checksum
58
+ checksum = extract_octal(
59
+ header_data, CHECKSUM_OFFSET, CHECKSUM_SIZE
60
+ )
61
+ calculated = Entry.calculate_checksum(header_data)
62
+ unless checksum == calculated
63
+ raise Error, "TAR header checksum mismatch"
64
+ end
65
+
66
+ entry
67
+ end
68
+
69
+ # Build a TAR header from an entry
70
+ #
71
+ # @param entry [Entry] Entry to build header for
72
+ # @return [String] 512 bytes of header data
73
+ def self.build(entry)
74
+ header = "\0" * HEADER_SIZE
75
+
76
+ # Write fields to header
77
+ name, prefix = split_long_name(entry.name, entry.prefix)
78
+ write_string(header, name, NAME_OFFSET, NAME_SIZE)
79
+ write_octal(header, entry.mode, MODE_OFFSET, MODE_SIZE)
80
+ write_octal(header, entry.uid, UID_OFFSET, UID_SIZE)
81
+ write_octal(header, entry.gid, GID_OFFSET, GID_SIZE)
82
+ write_octal(header, entry.size, SIZE_OFFSET, SIZE_SIZE)
83
+ write_octal(
84
+ header, entry.mtime.to_i, MTIME_OFFSET, MTIME_SIZE
85
+ )
86
+ header[TYPEFLAG_OFFSET] = entry.typeflag || TYPE_REGULAR
87
+ write_string(header, entry.linkname, LINKNAME_OFFSET, LINKNAME_SIZE)
88
+
89
+ # Write ustar magic and version
90
+ write_string(header, USTAR_MAGIC, MAGIC_OFFSET, MAGIC_SIZE)
91
+ write_string(header, USTAR_VERSION, VERSION_OFFSET, VERSION_SIZE)
92
+ write_string(header, entry.uname, UNAME_OFFSET, UNAME_SIZE)
93
+ write_string(header, entry.gname, GNAME_OFFSET, GNAME_SIZE)
94
+ write_octal(header, entry.devmajor, DEVMAJOR_OFFSET, DEVMAJOR_SIZE)
95
+ write_octal(header, entry.devminor, DEVMINOR_OFFSET, DEVMINOR_SIZE)
96
+ write_string(header, prefix, PREFIX_OFFSET, PREFIX_SIZE)
97
+
98
+ # Calculate and write checksum
99
+ checksum = Entry.calculate_checksum(header)
100
+ write_octal(header, checksum, CHECKSUM_OFFSET, CHECKSUM_SIZE)
101
+
102
+ header
103
+ end
104
+
105
+ # Check if header data is all zeros (end of archive marker)
106
+ #
107
+ # @param data [String] Header data
108
+ # @return [Boolean] true if all zeros
109
+ def self.all_zeros?(data)
110
+ data.bytes.all?(&:zero?)
111
+ end
112
+
113
+ # Extract a null-terminated string from header
114
+ #
115
+ # @param header [String] Header data
116
+ # @param offset [Integer] Field offset
117
+ # @param size [Integer] Field size
118
+ # @return [String] Extracted string
119
+ def self.extract_string(header, offset, size)
120
+ field = header[offset, size]
121
+ return "" if field.nil?
122
+
123
+ # Find null terminator
124
+ null_pos = field.index("\0")
125
+ null_pos ? field[0...null_pos] : field
126
+ end
127
+
128
+ # Extract an octal number from header
129
+ #
130
+ # @param header [String] Header data
131
+ # @param offset [Integer] Field offset
132
+ # @param size [Integer] Field size
133
+ # @return [Integer] Extracted number
134
+ def self.extract_octal(header, offset, size)
135
+ field = extract_string(header, offset, size)
136
+ field.strip.to_i(8)
137
+ end
138
+
139
+ # Split a path for the ustar name (100) + prefix (155)
140
+ # fields. Paths under 100 bytes pass through; longer paths
141
+ # split at a "/" boundary, preferring the longest prefix
142
+ # that keeps both halves in bounds. Raises when no ustar
143
+ # representation exists — silent truncation corrupts
144
+ # archives.
145
+ #
146
+ # @param path [String] Full entry path
147
+ # @param prefix [String] Explicit prefix (wins when given)
148
+ # @return [Array<String>] [name, prefix] pair
149
+ def self.split_long_name(path, prefix = nil)
150
+ path = path.to_s
151
+ prefix = prefix.to_s
152
+ return [path, prefix] if !prefix.empty? || path.bytesize < NAME_SIZE
153
+
154
+ best = nil
155
+ offset = -1
156
+ while (slash = path.index("/", offset + 1))
157
+ candidate_prefix = path[0...slash]
158
+ candidate_name = path[(slash + 1)..]
159
+ offset = slash
160
+
161
+ next if candidate_prefix.bytesize >= PREFIX_SIZE
162
+ next if candidate_name.bytesize >= NAME_SIZE
163
+
164
+ best = [candidate_name, candidate_prefix]
165
+ end
166
+
167
+ return best if best
168
+
169
+ raise Omnizip::FormatError,
170
+ "Path too long for the ustar name+prefix fields " \
171
+ "(no PAX/GNU long-name support): #{path}"
172
+ end
173
+
174
+ # Write a string to header
175
+ #
176
+ # @param header [String] Header data
177
+ # @param value [String] Value to write
178
+ # @param offset [Integer] Field offset
179
+ # @param size [Integer] Field size
180
+ def self.write_string(header, value, offset, size)
181
+ value = value.to_s
182
+ # Truncate if too long
183
+ value = value[0, size - 1] if value.bytesize >= size
184
+ header[offset, value.bytesize] = value
185
+ end
186
+
187
+ # Write an octal number to header
188
+ #
189
+ # @param header [String] Header data
190
+ # @param value [Integer] Value to write
191
+ # @param offset [Integer] Field offset
192
+ # @param size [Integer] Field size
193
+ def self.write_octal(header, value, offset, size)
194
+ # Format as octal with leading zeros
195
+ octal_str = format("%0#{size - 1}o", value.to_i)
196
+ # Truncate if too long
197
+ octal_str = octal_str[(-size + 1)..] if octal_str.bytesize >= size
198
+ header[offset, octal_str.bytesize] = octal_str
199
+ end
200
+
201
+ private_class_method :extract_string, :extract_octal
202
+ private_class_method :write_string, :write_octal, :all_zeros?
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ module Omnizip
6
+ module Formats
7
+ module Tar
8
+ # TAR archive reader
9
+ #
10
+ # Reads and extracts TAR archives
11
+ class Reader
12
+ include Omnizip::Formats::Tar::Constants
13
+
14
+ attr_reader :file_path, :entries
15
+
16
+ # Initialize TAR reader
17
+ #
18
+ # @param file_path [String] Path to TAR archive
19
+ def initialize(file_path)
20
+ @file_path = file_path
21
+ @entries = []
22
+ @file = nil
23
+ end
24
+
25
+ # Read TAR archive and parse all entries
26
+ #
27
+ # @return [self] Returns self for method chaining
28
+ def read
29
+ File.open(@file_path, "rb") do |file|
30
+ @file = file
31
+ parse_entries
32
+ end
33
+ self
34
+ end
35
+
36
+ # Extract all entries to a directory
37
+ #
38
+ # @param output_dir [String] Output directory path
39
+ def extract_all(output_dir)
40
+ read unless @entries.any?
41
+
42
+ FileUtils.mkdir_p(output_dir)
43
+
44
+ @entries.each do |entry|
45
+ extract_entry(entry, output_dir)
46
+ end
47
+ end
48
+
49
+ # Extract a specific entry
50
+ #
51
+ # @param entry [Entry] Entry to extract
52
+ # @param output_dir [String] Output directory
53
+ def extract_entry(entry, output_dir)
54
+ full_path = File.join(output_dir, entry.full_name)
55
+
56
+ if entry.directory?
57
+ FileUtils.mkdir_p(full_path)
58
+ elsif entry.file?
59
+ FileUtils.mkdir_p(File.dirname(full_path))
60
+ File.binwrite(full_path, entry.data)
61
+ File.chmod(entry.mode, full_path) if entry.mode
62
+ File.utime(entry.mtime, entry.mtime, full_path) if entry.mtime
63
+ elsif entry.symlink?
64
+ FileUtils.mkdir_p(File.dirname(full_path))
65
+ File.symlink(entry.linkname, full_path)
66
+ end
67
+ end
68
+
69
+ # List all entries
70
+ #
71
+ # @return [Array<Entry>] List of entries
72
+ def list_entries
73
+ read unless @entries.any?
74
+ @entries
75
+ end
76
+
77
+ # Open TAR archive and yield reader
78
+ #
79
+ # @param file_path [String] Path to TAR archive
80
+ # @yield [Reader] Reader instance
81
+ def self.open(file_path)
82
+ reader = new(file_path)
83
+ reader.read
84
+ yield reader if block_given?
85
+ reader
86
+ end
87
+
88
+ private
89
+
90
+ # Parse all entries from TAR archive
91
+ def parse_entries
92
+ @entries = []
93
+
94
+ loop do
95
+ header_data = @file.read(HEADER_SIZE)
96
+ break if header_data.nil? || header_data.bytesize < HEADER_SIZE
97
+
98
+ entry = Header.parse(header_data)
99
+ break if entry.nil?
100
+
101
+ # Read entry data
102
+ if entry.size.positive?
103
+ entry.data = @file.read(entry.size)
104
+
105
+ # Skip to next block boundary
106
+ remainder = entry.size % BLOCK_SIZE
107
+ if remainder.positive?
108
+ padding = BLOCK_SIZE - remainder
109
+ @file.read(padding)
110
+ end
111
+ end
112
+
113
+ @entries << entry
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end