omnizip 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (511) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +754 -0
  5. data/COPYING +502 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE +12 -0
  8. data/README.adoc +1045 -0
  9. data/Rakefile +12 -0
  10. data/benchmark/README.md +260 -0
  11. data/benchmark/benchmark_suite.rb +125 -0
  12. data/benchmark/compression_bench.rb +181 -0
  13. data/benchmark/filter_bench.rb +180 -0
  14. data/benchmark/models/benchmark_result.rb +59 -0
  15. data/benchmark/models/comparison_result.rb +69 -0
  16. data/benchmark/profile_suite.rb +167 -0
  17. data/benchmark/reporter.rb +150 -0
  18. data/benchmark/run_benchmarks.rb +66 -0
  19. data/benchmark/test_data.rb +137 -0
  20. data/config/formats/rar3_spec.yml +91 -0
  21. data/config/formats/rar5_spec.yml +102 -0
  22. data/docs/.github/workflows/docs.yml +142 -0
  23. data/docs/.gitignore +21 -0
  24. data/docs/.lychee.toml +67 -0
  25. data/docs/Gemfile +13 -0
  26. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  27. data/docs/README.md +101 -0
  28. data/docs/_config.yml +112 -0
  29. data/docs/assets/logo.svg +1 -0
  30. data/docs/assets/omnizip-logo.pdf +1540 -11
  31. data/docs/comparison/feature-matrix.adoc +694 -0
  32. data/docs/comparison/index.adoc +113 -0
  33. data/docs/comparison/vs-7zip.adoc +309 -0
  34. data/docs/comparison/vs-peazip.adoc +77 -0
  35. data/docs/comparison/vs-rubyzip.adoc +342 -0
  36. data/docs/comparison/vs-winrar.adoc +100 -0
  37. data/docs/compatibility.adoc +579 -0
  38. data/docs/concepts/index.adoc +129 -0
  39. data/docs/developer/architecture.adoc +256 -0
  40. data/docs/developer/contributing.adoc +158 -0
  41. data/docs/developer/index.adoc +25 -0
  42. data/docs/developer/testing.adoc +212 -0
  43. data/docs/getting-started/basic-usage.adoc +271 -0
  44. data/docs/getting-started/index.adoc +42 -0
  45. data/docs/getting-started/installation.adoc +138 -0
  46. data/docs/getting-started/quick-start.adoc +185 -0
  47. data/docs/getting-started/your-first-archive.adoc +218 -0
  48. data/docs/guides/advanced-features/encryption.adoc +300 -0
  49. data/docs/guides/advanced-features/index.adoc +49 -0
  50. data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
  51. data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
  52. data/docs/guides/advanced-features/streaming.adoc +212 -0
  53. data/docs/guides/archive-formats/gzip-format.adoc +107 -0
  54. data/docs/guides/archive-formats/index.adoc +130 -0
  55. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  56. data/docs/guides/archive-formats/rar5.adoc +521 -0
  57. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  58. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  59. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  60. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  61. data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
  62. data/docs/guides/compression-algorithms/deflate.adoc +319 -0
  63. data/docs/guides/compression-algorithms/index.adoc +190 -0
  64. data/docs/guides/compression-algorithms/lzma.adoc +398 -0
  65. data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
  66. data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
  67. data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
  68. data/docs/guides/creating-archives.adoc +354 -0
  69. data/docs/guides/extracting-archives.adoc +53 -0
  70. data/docs/guides/format-conversion.adoc +64 -0
  71. data/docs/guides/index.adoc +49 -0
  72. data/docs/guides/migration-rubyzip.adoc +217 -0
  73. data/docs/guides/parity-archives.adoc +605 -0
  74. data/docs/guides/performance-tuning.adoc +88 -0
  75. data/docs/index.adoc +218 -0
  76. data/docs/lychee.toml +67 -0
  77. data/docs/reference/api/overview.adoc +188 -0
  78. data/docs/reference/cli/compress-command.adoc +114 -0
  79. data/docs/reference/cli/overview.adoc +140 -0
  80. data/docs/reference/index.adoc +26 -0
  81. data/docs/resources/faq.adoc +185 -0
  82. data/docs/resources/quick-reference.adoc +222 -0
  83. data/docs/troubleshooting/index.adoc +208 -0
  84. data/examples/api_comparison.rb +205 -0
  85. data/examples/deflate64_example.rb +96 -0
  86. data/examples/par2_demo.rb +121 -0
  87. data/examples/quick_start_native.rb +150 -0
  88. data/examples/quick_start_rubyzip.rb +115 -0
  89. data/examples/rubyzip_compatibility_demo.rb +194 -0
  90. data/exe/omnizip +27 -0
  91. data/lib/omnizip/algorithm.rb +130 -0
  92. data/lib/omnizip/algorithm_registry.rb +86 -0
  93. data/lib/omnizip/algorithms/.keep +0 -0
  94. data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
  95. data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
  96. data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
  97. data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
  98. data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
  99. data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
  100. data/lib/omnizip/algorithms/bzip2.rb +130 -0
  101. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  102. data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
  103. data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
  104. data/lib/omnizip/algorithms/deflate.rb +128 -0
  105. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  106. data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
  107. data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
  108. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
  109. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
  110. data/lib/omnizip/algorithms/deflate64.rb +109 -0
  111. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  112. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  113. data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
  114. data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
  115. data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
  116. data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
  117. data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
  118. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
  119. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
  120. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
  121. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
  122. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  123. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  124. data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
  125. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  126. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
  127. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
  128. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  129. data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
  130. data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
  131. data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
  132. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  133. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
  134. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
  135. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
  136. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
  137. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
  138. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
  139. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  140. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
  141. data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
  142. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
  143. data/lib/omnizip/algorithms/lzma.rb +238 -0
  144. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
  145. data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
  146. data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
  147. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
  148. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  149. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
  150. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  151. data/lib/omnizip/algorithms/lzma2.rb +141 -0
  152. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  153. data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
  154. data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
  155. data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
  156. data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
  157. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  158. data/lib/omnizip/algorithms/ppmd7.rb +116 -0
  159. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  160. data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
  161. data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
  162. data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
  163. data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
  164. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  165. data/lib/omnizip/algorithms/ppmd8.rb +82 -0
  166. data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
  167. data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
  168. data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
  169. data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
  170. data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
  171. data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
  172. data/lib/omnizip/algorithms/zstandard.rb +138 -0
  173. data/lib/omnizip/buffer/memory_archive.rb +251 -0
  174. data/lib/omnizip/buffer/memory_extractor.rb +224 -0
  175. data/lib/omnizip/buffer.rb +176 -0
  176. data/lib/omnizip/checksum_registry.rb +114 -0
  177. data/lib/omnizip/checksums/crc32.rb +100 -0
  178. data/lib/omnizip/checksums/crc64.rb +101 -0
  179. data/lib/omnizip/checksums/crc_base.rb +158 -0
  180. data/lib/omnizip/checksums/verifier.rb +131 -0
  181. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  182. data/lib/omnizip/chunked/reader.rb +78 -0
  183. data/lib/omnizip/chunked/writer.rb +120 -0
  184. data/lib/omnizip/chunked.rb +129 -0
  185. data/lib/omnizip/cli/output_formatter.rb +104 -0
  186. data/lib/omnizip/cli.rb +572 -0
  187. data/lib/omnizip/commands/.keep +0 -0
  188. data/lib/omnizip/commands/archive_create_command.rb +427 -0
  189. data/lib/omnizip/commands/archive_extract_command.rb +272 -0
  190. data/lib/omnizip/commands/archive_list_command.rb +218 -0
  191. data/lib/omnizip/commands/archive_repair_command.rb +131 -0
  192. data/lib/omnizip/commands/archive_verify_command.rb +117 -0
  193. data/lib/omnizip/commands/compress_command.rb +117 -0
  194. data/lib/omnizip/commands/decompress_command.rb +120 -0
  195. data/lib/omnizip/commands/list_command.rb +53 -0
  196. data/lib/omnizip/commands/metadata_command.rb +153 -0
  197. data/lib/omnizip/commands/parity_create_command.rb +122 -0
  198. data/lib/omnizip/commands/parity_repair_command.rb +122 -0
  199. data/lib/omnizip/commands/parity_verify_command.rb +124 -0
  200. data/lib/omnizip/commands/profile_list_command.rb +56 -0
  201. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  202. data/lib/omnizip/convenience.rb +359 -0
  203. data/lib/omnizip/converter/conversion_registry.rb +49 -0
  204. data/lib/omnizip/converter/conversion_strategy.rb +121 -0
  205. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
  206. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
  207. data/lib/omnizip/converter.rb +105 -0
  208. data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
  209. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  210. data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
  211. data/lib/omnizip/crypto/aes256.rb +102 -0
  212. data/lib/omnizip/error.rb +106 -0
  213. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
  214. data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
  215. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  216. data/lib/omnizip/eta/sample_history.rb +143 -0
  217. data/lib/omnizip/eta/time_estimator.rb +106 -0
  218. data/lib/omnizip/eta.rb +63 -0
  219. data/lib/omnizip/extraction/filter_chain.rb +177 -0
  220. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  221. data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
  222. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  223. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  224. data/lib/omnizip/extraction/selective_extractor.rb +240 -0
  225. data/lib/omnizip/extraction.rb +111 -0
  226. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  227. data/lib/omnizip/file_type.rb +113 -0
  228. data/lib/omnizip/filter.rb +139 -0
  229. data/lib/omnizip/filter_pipeline.rb +108 -0
  230. data/lib/omnizip/filter_registry.rb +166 -0
  231. data/lib/omnizip/filters/bcj.rb +279 -0
  232. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  233. data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
  234. data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
  235. data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
  236. data/lib/omnizip/filters/bcj2.rb +99 -0
  237. data/lib/omnizip/filters/bcj_arm.rb +176 -0
  238. data/lib/omnizip/filters/bcj_arm64.rb +244 -0
  239. data/lib/omnizip/filters/bcj_ia64.rb +196 -0
  240. data/lib/omnizip/filters/bcj_ppc.rb +190 -0
  241. data/lib/omnizip/filters/bcj_sparc.rb +176 -0
  242. data/lib/omnizip/filters/bcj_x86.rb +193 -0
  243. data/lib/omnizip/filters/delta.rb +196 -0
  244. data/lib/omnizip/filters/filter_base.rb +72 -0
  245. data/lib/omnizip/filters/registry.rb +123 -0
  246. data/lib/omnizip/filters/xz_delta.rb +258 -0
  247. data/lib/omnizip/format_detector.rb +162 -0
  248. data/lib/omnizip/format_registry.rb +59 -0
  249. data/lib/omnizip/formats/.keep +0 -0
  250. data/lib/omnizip/formats/bzip2_file.rb +172 -0
  251. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  252. data/lib/omnizip/formats/cpio/entry.rb +385 -0
  253. data/lib/omnizip/formats/cpio/reader.rb +196 -0
  254. data/lib/omnizip/formats/cpio/writer.rb +234 -0
  255. data/lib/omnizip/formats/cpio.rb +140 -0
  256. data/lib/omnizip/formats/format_spec_loader.rb +230 -0
  257. data/lib/omnizip/formats/gzip.rb +238 -0
  258. data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
  259. data/lib/omnizip/formats/iso/directory_record.rb +152 -0
  260. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  261. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  262. data/lib/omnizip/formats/iso/reader.rb +197 -0
  263. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  264. data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
  265. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  266. data/lib/omnizip/formats/iso/writer.rb +530 -0
  267. data/lib/omnizip/formats/iso.rb +140 -0
  268. data/lib/omnizip/formats/lzip.rb +175 -0
  269. data/lib/omnizip/formats/lzma_alone.rb +171 -0
  270. data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
  271. data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
  272. data/lib/omnizip/formats/rar/block_parser.rb +243 -0
  273. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  274. data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
  275. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
  276. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
  277. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  278. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  279. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  280. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  281. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
  282. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
  283. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
  284. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  285. data/lib/omnizip/formats/rar/constants.rb +82 -0
  286. data/lib/omnizip/formats/rar/decompressor.rb +238 -0
  287. data/lib/omnizip/formats/rar/external_writer.rb +312 -0
  288. data/lib/omnizip/formats/rar/header.rb +192 -0
  289. data/lib/omnizip/formats/rar/license_validator.rb +109 -0
  290. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  291. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  292. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  293. data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
  294. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
  295. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
  296. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  297. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  298. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
  299. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  300. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
  301. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  302. data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
  303. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  304. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  305. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  306. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  307. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  308. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
  309. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  310. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
  311. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
  312. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
  313. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  314. data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
  315. data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
  316. data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
  317. data/lib/omnizip/formats/rar/reader.rb +366 -0
  318. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  319. data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
  320. data/lib/omnizip/formats/rar/writer.rb +431 -0
  321. data/lib/omnizip/formats/rar.rb +205 -0
  322. data/lib/omnizip/formats/rar3/compressor.rb +73 -0
  323. data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
  324. data/lib/omnizip/formats/rar3/reader.rb +386 -0
  325. data/lib/omnizip/formats/rar3/writer.rb +219 -0
  326. data/lib/omnizip/formats/rar5/compressor.rb +73 -0
  327. data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
  328. data/lib/omnizip/formats/rar5/reader.rb +342 -0
  329. data/lib/omnizip/formats/rar5/writer.rb +214 -0
  330. data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
  331. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  332. data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
  333. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
  334. data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
  335. data/lib/omnizip/formats/seven_zip/header.rb +106 -0
  336. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
  337. data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
  338. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  339. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
  340. data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
  341. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  342. data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
  343. data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
  344. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
  345. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
  346. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  347. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
  348. data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
  349. data/lib/omnizip/formats/seven_zip.rb +93 -0
  350. data/lib/omnizip/formats/tar/constants.rb +73 -0
  351. data/lib/omnizip/formats/tar/entry.rb +94 -0
  352. data/lib/omnizip/formats/tar/header.rb +168 -0
  353. data/lib/omnizip/formats/tar/reader.rb +121 -0
  354. data/lib/omnizip/formats/tar/writer.rb +216 -0
  355. data/lib/omnizip/formats/tar.rb +84 -0
  356. data/lib/omnizip/formats/xz/reader.rb +116 -0
  357. data/lib/omnizip/formats/xz.rb +237 -0
  358. data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
  359. data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
  360. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  361. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
  362. data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
  363. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  364. data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
  365. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
  366. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
  367. data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
  368. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
  369. data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
  370. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
  371. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  372. data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
  373. data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
  374. data/lib/omnizip/formats/zip/constants.rb +69 -0
  375. data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
  376. data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
  377. data/lib/omnizip/formats/zip/reader.rb +250 -0
  378. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  379. data/lib/omnizip/formats/zip/writer.rb +375 -0
  380. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
  381. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
  382. data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
  383. data/lib/omnizip/formats/zip.rb +50 -0
  384. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  385. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  386. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  387. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  388. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  389. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
  390. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
  391. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
  392. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
  393. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
  394. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
  395. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
  396. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
  397. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
  398. data/lib/omnizip/io/buffered_input.rb +146 -0
  399. data/lib/omnizip/io/buffered_output.rb +105 -0
  400. data/lib/omnizip/io/stream_manager.rb +115 -0
  401. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  402. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  403. data/lib/omnizip/link_handler.rb +124 -0
  404. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  405. data/lib/omnizip/metadata/entry_metadata.rb +146 -0
  406. data/lib/omnizip/metadata/metadata_editor.rb +171 -0
  407. data/lib/omnizip/metadata/metadata_registry.rb +64 -0
  408. data/lib/omnizip/metadata/metadata_validator.rb +99 -0
  409. data/lib/omnizip/metadata.rb +57 -0
  410. data/lib/omnizip/models/.keep +0 -0
  411. data/lib/omnizip/models/algorithm_metadata.rb +73 -0
  412. data/lib/omnizip/models/compression_options.rb +71 -0
  413. data/lib/omnizip/models/conversion_options.rb +87 -0
  414. data/lib/omnizip/models/conversion_result.rb +135 -0
  415. data/lib/omnizip/models/eta_result.rb +46 -0
  416. data/lib/omnizip/models/extraction_rule.rb +115 -0
  417. data/lib/omnizip/models/filter_chain.rb +144 -0
  418. data/lib/omnizip/models/filter_config.rb +183 -0
  419. data/lib/omnizip/models/match_result.rb +124 -0
  420. data/lib/omnizip/models/optimization_suggestion.rb +91 -0
  421. data/lib/omnizip/models/parallel_options.rb +104 -0
  422. data/lib/omnizip/models/performance_result.rb +79 -0
  423. data/lib/omnizip/models/profile_report.rb +82 -0
  424. data/lib/omnizip/models/progress_options.rb +38 -0
  425. data/lib/omnizip/models/split_options.rb +116 -0
  426. data/lib/omnizip/optimization_registry.rb +81 -0
  427. data/lib/omnizip/parallel/job_queue.rb +209 -0
  428. data/lib/omnizip/parallel/job_scheduler.rb +203 -0
  429. data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
  430. data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
  431. data/lib/omnizip/parallel/worker_pool.rb +223 -0
  432. data/lib/omnizip/parallel.rb +149 -0
  433. data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
  434. data/lib/omnizip/parity/galois16.rb +145 -0
  435. data/lib/omnizip/parity/models/creator_packet.rb +73 -0
  436. data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
  437. data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
  438. data/lib/omnizip/parity/models/main_packet.rb +128 -0
  439. data/lib/omnizip/parity/models/packet.rb +156 -0
  440. data/lib/omnizip/parity/models/packet_registry.rb +109 -0
  441. data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
  442. data/lib/omnizip/parity/par2_creator.rb +531 -0
  443. data/lib/omnizip/parity/par2_repairer.rb +407 -0
  444. data/lib/omnizip/parity/par2_verifier.rb +364 -0
  445. data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
  446. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  447. data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
  448. data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
  449. data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
  450. data/lib/omnizip/parity.rb +186 -0
  451. data/lib/omnizip/password/encryption_registry.rb +65 -0
  452. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  453. data/lib/omnizip/password/password_validator.rb +129 -0
  454. data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
  455. data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
  456. data/lib/omnizip/password.rb +87 -0
  457. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  458. data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
  459. data/lib/omnizip/pipe.rb +121 -0
  460. data/lib/omnizip/platform/ntfs_streams.rb +201 -0
  461. data/lib/omnizip/platform.rb +189 -0
  462. data/lib/omnizip/profile/archive_profile.rb +39 -0
  463. data/lib/omnizip/profile/balanced_profile.rb +33 -0
  464. data/lib/omnizip/profile/binary_profile.rb +36 -0
  465. data/lib/omnizip/profile/compression_profile.rb +158 -0
  466. data/lib/omnizip/profile/custom_profile.rb +157 -0
  467. data/lib/omnizip/profile/fast_profile.rb +33 -0
  468. data/lib/omnizip/profile/maximum_profile.rb +33 -0
  469. data/lib/omnizip/profile/profile_detector.rb +110 -0
  470. data/lib/omnizip/profile/profile_registry.rb +161 -0
  471. data/lib/omnizip/profile/text_profile.rb +36 -0
  472. data/lib/omnizip/profile.rb +190 -0
  473. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  474. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  475. data/lib/omnizip/profiler/report_generator.rb +169 -0
  476. data/lib/omnizip/profiler.rb +204 -0
  477. data/lib/omnizip/progress/callback_reporter.rb +36 -0
  478. data/lib/omnizip/progress/console_reporter.rb +62 -0
  479. data/lib/omnizip/progress/log_reporter.rb +91 -0
  480. data/lib/omnizip/progress/operation_progress.rb +118 -0
  481. data/lib/omnizip/progress/progress_bar.rb +156 -0
  482. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  483. data/lib/omnizip/progress/progress_tracker.rb +190 -0
  484. data/lib/omnizip/progress/silent_reporter.rb +24 -0
  485. data/lib/omnizip/progress.rb +127 -0
  486. data/lib/omnizip/rubyzip_compat.rb +63 -0
  487. data/lib/omnizip/temp/safe_extract.rb +168 -0
  488. data/lib/omnizip/temp/temp_file.rb +124 -0
  489. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  490. data/lib/omnizip/temp.rb +181 -0
  491. data/lib/omnizip/version.rb +5 -0
  492. data/lib/omnizip/zip/entry.rb +156 -0
  493. data/lib/omnizip/zip/file.rb +485 -0
  494. data/lib/omnizip/zip/input_stream.rb +273 -0
  495. data/lib/omnizip/zip/output_stream.rb +324 -0
  496. data/lib/omnizip.rb +156 -0
  497. data/readme-docs/advanced-features.adoc +515 -0
  498. data/readme-docs/api-usage.adoc +444 -0
  499. data/readme-docs/architecture.adoc +449 -0
  500. data/readme-docs/archive-formats.adoc +479 -0
  501. data/readme-docs/cli-usage.adoc +222 -0
  502. data/readme-docs/compression-algorithms.adoc +442 -0
  503. data/readme-docs/compression-profiles.adoc +247 -0
  504. data/readme-docs/encryption-checksums.adoc +328 -0
  505. data/readme-docs/format-converter.adoc +325 -0
  506. data/readme-docs/installation.adoc +228 -0
  507. data/readme-docs/par2-archives.adoc +608 -0
  508. data/readme-docs/performance-profiler.adoc +389 -0
  509. data/readme-docs/preprocessing-filters.adoc +280 -0
  510. data/xz-file-format-1.2.1.txt +1174 -0
  511. metadata +617 -0
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require_relative "constants"
5
+ require_relative "entry"
6
+
7
+ module Omnizip
8
+ module Formats
9
+ module Cpio
10
+ # CPIO archive reader
11
+ #
12
+ # Reads CPIO archives in newc, CRC, ODC, and binary formats.
13
+ # Automatically detects format from magic number.
14
+ #
15
+ # @example Read CPIO archive
16
+ # reader = Cpio::Reader.new('archive.cpio')
17
+ # reader.open
18
+ # reader.entries.each { |entry| puts entry.name }
19
+ #
20
+ # @example Extract CPIO archive
21
+ # reader = Cpio::Reader.new('archive.cpio')
22
+ # reader.open
23
+ # reader.extract_all('output/')
24
+ class Reader
25
+ include Constants
26
+
27
+ # @return [String] Archive file path
28
+ attr_reader :file_path
29
+
30
+ # @return [Array<Entry>] Parsed entries
31
+ attr_reader :entries
32
+
33
+ # @return [Symbol, nil] Detected format
34
+ attr_reader :format
35
+
36
+ # Initialize CPIO reader
37
+ #
38
+ # @param file_path [String] Path to CPIO archive
39
+ def initialize(file_path)
40
+ @file_path = file_path
41
+ @entries = []
42
+ @format = nil
43
+ end
44
+
45
+ # Open and parse CPIO archive
46
+ #
47
+ # @raise [RuntimeError] if file cannot be opened or parsed
48
+ def open
49
+ File.open(@file_path, "rb") do |io|
50
+ parse_archive(io)
51
+ end
52
+ self
53
+ end
54
+
55
+ # List all entries
56
+ #
57
+ # @return [Array<Entry>] All entries except trailer
58
+ def list
59
+ @entries.reject(&:trailer?)
60
+ end
61
+
62
+ # Extract entry to output path
63
+ #
64
+ # @param entry_name [String] Entry name to extract
65
+ # @param output_path [String] Destination path
66
+ # @raise [RuntimeError] if entry not found
67
+ def extract_entry(entry_name, output_path)
68
+ entry = @entries.find { |e| e.name == entry_name }
69
+ raise "Entry not found: #{entry_name}" unless entry
70
+
71
+ extract_single_entry(entry, output_path)
72
+ end
73
+
74
+ # Extract all entries to directory
75
+ #
76
+ # @param output_dir [String] Output directory
77
+ def extract_all(output_dir)
78
+ FileUtils.mkdir_p(output_dir)
79
+
80
+ @entries.each do |entry|
81
+ next if entry.trailer?
82
+
83
+ output_path = File.join(output_dir, entry.name)
84
+ extract_single_entry(entry, output_path)
85
+ end
86
+ end
87
+
88
+ # Get archive format
89
+ #
90
+ # @return [String] Human-readable format name
91
+ def format_name
92
+ case @format
93
+ when :newc then "CPIO newc (SVR4)"
94
+ when :crc then "CPIO newc with CRC"
95
+ when :odc then "CPIO ODC (portable)"
96
+ when :binary then "CPIO binary (old)"
97
+ else "Unknown"
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ # Parse archive contents
104
+ #
105
+ # @param io [IO] Input stream
106
+ def parse_archive(io)
107
+ while !io.eof?
108
+ begin
109
+ entry = Entry.parse(io, format: @format)
110
+
111
+ # Detect format from first entry
112
+ @format ||= Entry.detect_format(entry.magic)
113
+
114
+ # Add entry (including trailer)
115
+ @entries << entry
116
+
117
+ # Stop at trailer
118
+ break if entry.trailer?
119
+ rescue StandardError => e
120
+ warn "Failed to parse CPIO entry: #{e.message}"
121
+ break
122
+ end
123
+ end
124
+ end
125
+
126
+ # Extract single entry
127
+ #
128
+ # @param entry [Entry] Entry to extract
129
+ # @param output_path [String] Destination path
130
+ def extract_single_entry(entry, output_path)
131
+ if entry.directory?
132
+ extract_directory(entry, output_path)
133
+ elsif entry.symlink?
134
+ extract_symlink(entry, output_path)
135
+ elsif entry.device?
136
+ # Skip device files (require root privileges)
137
+ warn "Skipping device file: #{entry.name}"
138
+ else
139
+ extract_file(entry, output_path)
140
+ end
141
+
142
+ # Set permissions and timestamps
143
+ set_entry_attributes(entry, output_path) unless entry.symlink?
144
+ end
145
+
146
+ # Extract directory
147
+ #
148
+ # @param entry [Entry] Directory entry
149
+ # @param output_path [String] Destination path
150
+ def extract_directory(_entry, output_path)
151
+ FileUtils.mkdir_p(output_path)
152
+ end
153
+
154
+ # Extract regular file
155
+ #
156
+ # @param entry [Entry] File entry
157
+ # @param output_path [String] Destination path
158
+ def extract_file(entry, output_path)
159
+ FileUtils.mkdir_p(File.dirname(output_path))
160
+ File.binwrite(output_path, entry.data)
161
+ end
162
+
163
+ # Extract symbolic link
164
+ #
165
+ # @param entry [Entry] Symlink entry
166
+ # @param output_path [String] Destination path
167
+ def extract_symlink(entry, output_path)
168
+ FileUtils.mkdir_p(File.dirname(output_path))
169
+
170
+ # Remove existing file/link if present
171
+ File.unlink(output_path) if File.exist?(output_path) || File.symlink?(output_path)
172
+
173
+ # Create symbolic link
174
+ File.symlink(entry.data, output_path)
175
+ end
176
+
177
+ # Set file attributes (permissions and timestamps)
178
+ #
179
+ # @param entry [Entry] Entry with attributes
180
+ # @param path [String] File path
181
+ def set_entry_attributes(entry, path)
182
+ # Set modification time
183
+ if entry.mtime&.positive?
184
+ mtime = Time.at(entry.mtime)
185
+ File.utime(mtime, mtime, path)
186
+ end
187
+
188
+ # Set permissions
189
+ File.chmod(entry.mode & 0o7777, path) if entry.mode
190
+ rescue Errno::EPERM, Errno::ENOENT
191
+ # Permission errors are non-fatal
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require_relative "constants"
5
+ require_relative "entry"
6
+
7
+ module Omnizip
8
+ module Formats
9
+ module Cpio
10
+ # CPIO archive writer
11
+ #
12
+ # Creates CPIO archives in newc, CRC, or ODC format.
13
+ # Ported from libarchive's archive_write_set_format_cpio_newc.c
14
+ #
15
+ # @example Create CPIO archive
16
+ # writer = Cpio::Writer.new('archive.cpio')
17
+ # writer.add_file('file.txt')
18
+ # writer.add_directory('dir/')
19
+ # writer.write
20
+ #
21
+ # @example With CRC format
22
+ # writer = Cpio::Writer.new('archive.cpio', format: :crc)
23
+ # writer.add_directory('initramfs/')
24
+ # writer.write
25
+ class Writer
26
+ include Constants
27
+
28
+ # @return [String] Output archive path
29
+ attr_reader :output_path
30
+
31
+ # @return [Symbol] CPIO format (:newc, :crc, :odc)
32
+ attr_reader :format
33
+
34
+ # @return [Array<Entry>] Entries to write
35
+ attr_reader :entries
36
+
37
+ # Initialize CPIO writer
38
+ #
39
+ # @param output_path [String] Output CPIO file path
40
+ # @param format [Symbol] CPIO format (:newc, :crc, :odc)
41
+ def initialize(output_path, format: :newc)
42
+ @output_path = output_path
43
+ @format = validate_format(format)
44
+ @entries = []
45
+ @inode_counter = 1
46
+ end
47
+
48
+ # Add file to archive
49
+ #
50
+ # @param file_path [String] Source file path
51
+ # @param cpio_path [String, nil] Path in archive (defaults to file_path)
52
+ # @raise [ArgumentError] if file doesn't exist
53
+ def add_file(file_path, cpio_path = nil)
54
+ raise ArgumentError, "File not found: #{file_path}" unless
55
+ File.exist?(file_path) || File.symlink?(file_path)
56
+
57
+ # Default to basename if no cpio_path specified
58
+ cpio_path = File.basename(file_path) if cpio_path.nil?
59
+ # Use lstat to not follow symlinks
60
+ stat = File.lstat(file_path)
61
+
62
+ # Normalize path: remove leading slashes to make relative
63
+ cpio_path = cpio_path.sub(%r{^/+}, "")
64
+
65
+ # Read file data unless it's a symlink
66
+ data = if File.symlink?(file_path)
67
+ File.readlink(file_path)
68
+ elsif stat.file?
69
+ File.binread(file_path)
70
+ else
71
+ ""
72
+ end
73
+
74
+ entry = create_entry_from_stat(cpio_path, stat, data)
75
+ @entries << entry
76
+ @inode_counter += 1
77
+ end
78
+
79
+ # Add directory to archive
80
+ #
81
+ # @param dir_path [String] Source directory path
82
+ # @param recursive [Boolean] Include subdirectories
83
+ # @param cpio_path [String, nil] Path in archive
84
+ # @raise [ArgumentError] if directory doesn't exist
85
+ def add_directory(dir_path, recursive: true, cpio_path: nil)
86
+ raise ArgumentError, "Directory not found: #{dir_path}" unless
87
+ Dir.exist?(dir_path)
88
+
89
+ # Default to basename if no cpio_path specified
90
+ cpio_path = File.basename(dir_path) if cpio_path.nil?
91
+ # Normalize path: remove leading slashes to make relative
92
+ cpio_path = cpio_path.sub(%r{^/+}, "")
93
+ stat = File.lstat(dir_path)
94
+
95
+ # Add directory entry
96
+ entry = create_entry_from_stat(cpio_path, stat, "")
97
+ @entries << entry
98
+ @inode_counter += 1
99
+
100
+ # Add contents if recursive
101
+ if recursive
102
+ Dir.foreach(dir_path) do |item|
103
+ next if [".", ".."].include?(item)
104
+
105
+ item_path = File.join(dir_path, item)
106
+ item_cpio_path = "#{cpio_path}/#{item}"
107
+
108
+ if File.directory?(item_path)
109
+ add_directory(item_path, recursive: true,
110
+ cpio_path: item_cpio_path)
111
+ else
112
+ add_file(item_path, item_cpio_path)
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ # Write CPIO archive
119
+ #
120
+ # @raise [IOError] if write fails
121
+ def write
122
+ File.open(@output_path, "wb") do |io|
123
+ # Write all entries
124
+ @entries.each do |entry|
125
+ write_entry(io, entry)
126
+ end
127
+
128
+ # Write trailer
129
+ write_trailer(io)
130
+ end
131
+
132
+ @output_path
133
+ end
134
+
135
+ private
136
+
137
+ # Validate format
138
+ #
139
+ # @param format [Symbol] Format to validate
140
+ # @return [Symbol] Validated format
141
+ # @raise [ArgumentError] if format invalid
142
+ def validate_format(format)
143
+ unless %i[newc crc odc].include?(format)
144
+ raise ArgumentError, "Invalid CPIO format: #{format}. " \
145
+ "Must be :newc, :crc, or :odc"
146
+ end
147
+ format
148
+ end
149
+
150
+ # Create entry from file stat
151
+ #
152
+ # @param path [String] Entry path
153
+ # @param stat [File::Stat] File statistics
154
+ # @param data [String] File data
155
+ # @return [Entry] Created entry
156
+ def create_entry_from_stat(path, stat, data)
157
+ Entry.new(
158
+ magic: format_magic,
159
+ ino: @inode_counter,
160
+ mode: stat.mode,
161
+ uid: stat.uid,
162
+ gid: stat.gid,
163
+ nlink: stat.nlink,
164
+ mtime: stat.mtime.to_i,
165
+ filesize: data.bytesize,
166
+ dev_major: (stat.dev >> 8) & 0xFF,
167
+ dev_minor: stat.dev & 0xFF,
168
+ rdev_major: stat.rdev ? (stat.rdev >> 8) & 0xFF : 0,
169
+ rdev_minor: stat.rdev ? (stat.rdev & 0xFF) : 0,
170
+ namesize: path.bytesize + 1,
171
+ checksum: @format == :crc ? calculate_checksum(data) : 0,
172
+ name: path,
173
+ data: data,
174
+ )
175
+ end
176
+
177
+ # Get magic number for current format
178
+ #
179
+ # @return [String] Magic number
180
+ def format_magic
181
+ case @format
182
+ when :newc then MAGIC_NEWC
183
+ when :crc then MAGIC_CRC
184
+ when :odc then MAGIC_ODC
185
+ end
186
+ end
187
+
188
+ # Write entry to archive
189
+ #
190
+ # @param io [IO] Output stream
191
+ # @param entry [Entry] Entry to write
192
+ def write_entry(io, entry)
193
+ binary_data = entry.to_binary(format: @format)
194
+ io.write(binary_data)
195
+ end
196
+
197
+ # Write trailer entry
198
+ #
199
+ # @param io [IO] Output stream
200
+ def write_trailer(io)
201
+ trailer = Entry.new(
202
+ magic: format_magic,
203
+ ino: 0,
204
+ mode: 0,
205
+ uid: 0,
206
+ gid: 0,
207
+ nlink: 1,
208
+ mtime: 0,
209
+ filesize: 0,
210
+ dev_major: 0,
211
+ dev_minor: 0,
212
+ rdev_major: 0,
213
+ rdev_minor: 0,
214
+ namesize: TRAILER_NAME.bytesize + 1,
215
+ checksum: 0,
216
+ name: TRAILER_NAME,
217
+ data: "",
218
+ )
219
+
220
+ write_entry(io, trailer)
221
+ end
222
+
223
+ # Calculate checksum for CRC format
224
+ #
225
+ # @param data [String] Data to checksum
226
+ # @return [Integer] CRC32 checksum
227
+ def calculate_checksum(data)
228
+ require "zlib"
229
+ Zlib.crc32(data) & 0xFFFFFFFF
230
+ end
231
+ end
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cpio/constants"
4
+ require_relative "cpio/entry"
5
+ require_relative "cpio/writer"
6
+ require_relative "cpio/reader"
7
+
8
+ module Omnizip
9
+ module Formats
10
+ # CPIO archive format support
11
+ #
12
+ # Provides read and write access to CPIO archives in multiple formats:
13
+ # - newc (SVR4 new ASCII format) - Most common, used in initramfs
14
+ # - CRC (newc with CRC checksums)
15
+ # - ODC (Old portable ASCII format)
16
+ #
17
+ # CPIO is commonly used for:
18
+ # - Linux initramfs/initrd
19
+ # - RPM package contents
20
+ # - Unix system backups
21
+ #
22
+ # @example Create CPIO archive
23
+ # Omnizip::Formats::Cpio.create('archive.cpio') do |cpio|
24
+ # cpio.add_directory('files/')
25
+ # end
26
+ #
27
+ # @example Extract CPIO archive
28
+ # Omnizip::Formats::Cpio.extract('archive.cpio', 'output/')
29
+ module Cpio
30
+ class << self
31
+ # Create CPIO archive
32
+ #
33
+ # @param path [String] Output CPIO file path
34
+ # @param format [Symbol] CPIO format (:newc, :crc, :odc)
35
+ # @yield [writer] Block for adding files/directories
36
+ # @yieldparam writer [Writer] CPIO writer
37
+ # @return [String] Path to created archive
38
+ #
39
+ # @example Create newc format archive
40
+ # Omnizip::Formats::Cpio.create('archive.cpio') do |cpio|
41
+ # cpio.add_file('kernel.img')
42
+ # cpio.add_directory('modules/')
43
+ # end
44
+ #
45
+ # @example Create with CRC checksums
46
+ # Omnizip::Formats::Cpio.create('archive.cpio', format: :crc) do |cpio|
47
+ # cpio.add_directory('initramfs/')
48
+ # end
49
+ def create(path, format: :newc)
50
+ writer = Writer.new(path, format: format)
51
+
52
+ yield writer if block_given?
53
+
54
+ writer.write
55
+ end
56
+
57
+ # Open CPIO archive for reading
58
+ #
59
+ # @param path [String] Path to CPIO file
60
+ # @yield [reader] Block for reading archive
61
+ # @yieldparam reader [Reader] CPIO reader
62
+ # @return [Reader] CPIO reader
63
+ #
64
+ # @example Read CPIO archive
65
+ # Omnizip::Formats::Cpio.open('archive.cpio') do |cpio|
66
+ # cpio.entries.each { |entry| puts entry.name }
67
+ # end
68
+ def open(path)
69
+ reader = Reader.new(path)
70
+ reader.open
71
+
72
+ if block_given?
73
+ yield reader
74
+ else
75
+ reader
76
+ end
77
+ end
78
+
79
+ # List CPIO archive contents
80
+ #
81
+ # @param path [String] Path to CPIO file
82
+ # @return [Array<Entry>] Archive entries
83
+ #
84
+ # @example List archive contents
85
+ # entries = Omnizip::Formats::Cpio.list('archive.cpio')
86
+ # entries.each { |e| puts "#{e.name} (#{e.filesize} bytes)" }
87
+ def list(path)
88
+ open(path, &:list)
89
+ end
90
+
91
+ # Extract CPIO archive
92
+ #
93
+ # @param cpio_path [String] Path to CPIO file
94
+ # @param output_dir [String] Output directory
95
+ #
96
+ # @example Extract archive
97
+ # Omnizip::Formats::Cpio.extract('archive.cpio', 'output/')
98
+ def extract(cpio_path, output_dir)
99
+ open(cpio_path) do |cpio|
100
+ cpio.extract_all(output_dir)
101
+ end
102
+ end
103
+
104
+ # Get archive information
105
+ #
106
+ # @param path [String] Path to CPIO file
107
+ # @return [Hash] Archive information
108
+ #
109
+ # @example Get archive info
110
+ # info = Omnizip::Formats::Cpio.info('archive.cpio')
111
+ # puts "Format: #{info[:format]}"
112
+ # puts "Files: #{info[:file_count]}"
113
+ def info(path)
114
+ open(path) do |cpio|
115
+ entries = cpio.list
116
+
117
+ {
118
+ format: cpio.format_name,
119
+ format_type: cpio.format,
120
+ entry_count: entries.size,
121
+ file_count: entries.count(&:file?),
122
+ directory_count: entries.count(&:directory?),
123
+ symlink_count: entries.count(&:symlink?),
124
+ total_size: entries.sum(&:filesize),
125
+ }
126
+ end
127
+ end
128
+
129
+ # Auto-register CPIO format when loaded
130
+ def register!
131
+ require_relative "../format_registry"
132
+ FormatRegistry.register(".cpio", Reader)
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ # Auto-register on load
140
+ Omnizip::Formats::Cpio.register!