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,652 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "zlib"
5
+ require "stringio"
6
+ require "digest"
7
+
8
+ module Omnizip
9
+ module Formats
10
+ module Rpm
11
+ # RPM package writer
12
+ #
13
+ # Creates RPM packages with binary payload (CPIO archive).
14
+ # Supports multiple compression algorithms: gzip, bzip2, xz, zstd.
15
+ #
16
+ # @example Create an RPM package with gzip compression (default)
17
+ # writer = Rpm::Writer.new(
18
+ # name: "myapp",
19
+ # version: "1.0.0",
20
+ # release: "1",
21
+ # arch: "x86_64"
22
+ # )
23
+ # writer.add_file("/usr/bin/myapp", content, mode: 0755)
24
+ # writer.write("myapp-1.0.0-1.x86_64.rpm")
25
+ #
26
+ # @example Create an RPM with xz compression
27
+ # writer = Rpm::Writer.new(
28
+ # name: "myapp",
29
+ # version: "1.0.0",
30
+ # release: "1",
31
+ # compression: :xz
32
+ # )
33
+ #
34
+ class Writer
35
+ include Omnizip::Formats::Rpm::Constants
36
+
37
+ # Supported compression types and their properties
38
+ COMPRESSION_INFO = {
39
+ gzip: { name: "gzip", flags: "9" },
40
+ bzip2: { name: "bzip2", flags: "9" },
41
+ xz: { name: "xz", flags: "9" },
42
+ zstd: { name: "zstd", flags: "19" },
43
+ none: { name: nil, flags: nil },
44
+ }.freeze
45
+
46
+ # Architecture mapping
47
+ ARCHITECTURES = {
48
+ "noarch" => 0,
49
+ "i386" => 1,
50
+ "i486" => 2,
51
+ "i586" => 3,
52
+ "i686" => 4,
53
+ "x86_64" => 9,
54
+ "amd64" => 9,
55
+ "ia64" => 11,
56
+ "ppc" => 5,
57
+ "ppc64" => 16,
58
+ "sparc" => 6,
59
+ "sparc64" => 7,
60
+ "alpha" => 8,
61
+ "s390" => 14,
62
+ "s390x" => 15,
63
+ "arm" => 12,
64
+ "aarch64" => 19,
65
+ }.freeze
66
+
67
+ # Tag ID mapping (reverse of Tag::TAG_IDS)
68
+ TAG_NAMES = {
69
+ # Header tags
70
+ name: 1000,
71
+ version: 1001,
72
+ release: 1002,
73
+ epoch: 1003,
74
+ summary: 1004,
75
+ description: 1005,
76
+ buildtime: 1006,
77
+ buildhost: 1007,
78
+ size: 1009,
79
+ distribution: 1010,
80
+ vendor: 1011,
81
+ license: 1014,
82
+ packager: 1015,
83
+ group: 1016,
84
+ url: 1020,
85
+ os: 1021,
86
+ arch: 1022,
87
+ prein: 1023,
88
+ postin: 1024,
89
+ preun: 1025,
90
+ postun: 1026,
91
+ filesizes: 1028,
92
+ filemodes: 1030,
93
+ fileuids: 1031,
94
+ filegids: 1032,
95
+ filemtimes: 1034,
96
+ filedigests: 1035,
97
+ filelinktos: 1036,
98
+ fileflags: 1037,
99
+ fileusername: 1039,
100
+ filegroupname: 1040,
101
+ archivesize: 1046,
102
+ rpmversion: 1064,
103
+ dirindexes: 1116,
104
+ basenames: 1117,
105
+ dirnames: 1118,
106
+ payloadformat: 1124,
107
+ payloadcompressor: 1125,
108
+ payloadflags: 1126,
109
+
110
+ # Signature tags
111
+ sigsize: 257,
112
+ sha1header: 269,
113
+ }.freeze
114
+
115
+ # @return [String] Package name
116
+ attr_reader :name
117
+
118
+ # @return [String] Package version
119
+ attr_reader :version
120
+
121
+ # @return [String] Package release
122
+ attr_reader :release
123
+
124
+ # @return [String, nil] Package epoch
125
+ attr_reader :epoch
126
+
127
+ # @return [String] Architecture
128
+ attr_reader :arch
129
+
130
+ # @return [Symbol] Compression type
131
+ attr_reader :compression
132
+
133
+ # @return [Hash<String, String>] File contents
134
+ attr_reader :files
135
+
136
+ # @return [Hash] Additional metadata
137
+ attr_reader :metadata
138
+
139
+ # Initialize RPM writer
140
+ #
141
+ # @param name [String] Package name
142
+ # @param version [String] Package version
143
+ # @param release [String] Package release
144
+ # @param arch [String] Architecture (default: "noarch")
145
+ # @param epoch [String, nil] Optional epoch
146
+ # @param compression [Symbol] Compression type (:gzip, :bzip2, :xz, :zstd, :none)
147
+ # @param metadata [Hash] Additional metadata
148
+ def initialize(name:, version:, release:, arch: "noarch", epoch: nil,
149
+ compression: :gzip, **metadata)
150
+ @name = name
151
+ @version = version
152
+ @release = release
153
+ @arch = arch
154
+ @epoch = epoch
155
+ @compression = validate_compression(compression)
156
+ @metadata = metadata
157
+ @files = []
158
+ @directories = []
159
+ end
160
+
161
+ # Validate compression type
162
+ #
163
+ # @param comp [Symbol] Compression type
164
+ # @return [Symbol] Validated compression type
165
+ # @raise [ArgumentError] If compression type is invalid
166
+ def validate_compression(comp)
167
+ return :gzip unless comp
168
+
169
+ unless COMPRESSION_INFO.key?(comp)
170
+ raise ArgumentError, "Unsupported compression: #{comp}. " \
171
+ "Supported: #{COMPRESSION_INFO.keys.join(', ')}"
172
+ end
173
+ comp
174
+ end
175
+
176
+ # Get compression info
177
+ #
178
+ # @return [Hash] Compression info with :name and :flags
179
+ def compression_info
180
+ COMPRESSION_INFO[@compression]
181
+ end
182
+
183
+ # Add file to package
184
+ #
185
+ # @param path [String] File path in package (absolute path)
186
+ # @param content [String] File content
187
+ # @param mode [Integer] File permissions (default: 0644)
188
+ # @param owner [String] File owner (default: "root")
189
+ # @param group [String] File group (default: "root")
190
+ # @param mtime [Integer] Modification time (default: now)
191
+ def add_file(path, content, mode: 0o644, owner: "root", group: "root",
192
+ mtime: nil)
193
+ @files << {
194
+ path: path,
195
+ content: content,
196
+ mode: mode,
197
+ owner: owner,
198
+ group: group,
199
+ mtime: mtime || Time.now.to_i,
200
+ }
201
+ end
202
+
203
+ # Add directory to package
204
+ #
205
+ # @param path [String] Directory path in package (absolute path)
206
+ # @param mode [Integer] Directory permissions (default: 0755)
207
+ # @param owner [String] Directory owner (default: "root")
208
+ # @param group [String] Directory group (default: "root")
209
+ def add_directory(path, mode: 0o755, owner: "root", group: "root")
210
+ @directories << {
211
+ path: path,
212
+ mode: mode,
213
+ owner: owner,
214
+ group: group,
215
+ }
216
+ end
217
+
218
+ # Write RPM package to file
219
+ #
220
+ # @param output_path [String] Output file path
221
+ # @return [String] Output path
222
+ def write(output_path)
223
+ File.open(output_path, "wb") do |io|
224
+ write_to_io(io)
225
+ end
226
+ output_path
227
+ end
228
+
229
+ # Write RPM package to IO
230
+ #
231
+ # @param io [IO] Output IO
232
+ def write_to_io(io)
233
+ # Build payload (compressed CPIO)
234
+ payload_io = StringIO.new("".b)
235
+ cpio_data = build_cpio_payload
236
+ compress_payload(cpio_data, payload_io)
237
+ payload_io.rewind
238
+ payload_data = payload_io.read
239
+
240
+ # Build headers
241
+ main_header = build_main_header(payload_data.bytesize)
242
+ sig_header = build_signature_header(main_header.bytesize,
243
+ payload_data.bytesize)
244
+
245
+ # Build lead
246
+ lead = build_lead
247
+
248
+ # Write RPM in order
249
+ io.write(lead)
250
+ io.write(sig_header)
251
+ io.write(main_header)
252
+ io.write(payload_data)
253
+ end
254
+
255
+ private
256
+
257
+ # Build lead (96 bytes)
258
+ #
259
+ # @return [String] Packed lead
260
+ def build_lead
261
+ name_field = "#{@name}-#{@version}-#{@release}"
262
+ name_field = name_field[0, 65] # Truncate to 65 chars + null
263
+ name_padded = name_field.ljust(66, "\0")
264
+
265
+ arch_num = ARCHITECTURES.fetch(@arch.downcase, 0)
266
+
267
+ # Pack format:
268
+ # A4 = magic (4 bytes)
269
+ # CC = major/minor version (2 bytes)
270
+ # n = package type (2 bytes, 0 = binary)
271
+ # n = architecture (2 bytes)
272
+ # A66 = name (66 bytes)
273
+ # n = os (2 bytes, 1 = Linux)
274
+ # n = signature type (2 bytes, 5 = signed)
275
+ # A16 = reserved (16 bytes)
276
+ [LEAD_MAGIC, 3, 0, PACKAGE_BINARY, arch_num, name_padded, 1,
277
+ HEADER_SIGNED_TYPE, "\0" * 16].pack("A4 CC n n A66 n n A16")
278
+ end
279
+
280
+ # Build signature header
281
+ #
282
+ # @param header_size [Integer] Main header size
283
+ # @param payload_size [Integer] Payload size
284
+ # @return [String] Packed signature header
285
+ def build_signature_header(header_size, payload_size)
286
+ tags = [
287
+ { id: TAG_NAMES[:sigsize], type: TYPE_INT32,
288
+ value: [header_size + payload_size] },
289
+ { id: TAG_NAMES[:sha1header], type: TYPE_STRING, value: "" },
290
+ ]
291
+ build_header_data(tags)
292
+ end
293
+
294
+ # Build main header
295
+ #
296
+ # @param payload_size [Integer] Payload size (uncompressed)
297
+ # @return [String] Packed main header
298
+ def build_main_header(payload_size)
299
+ # Build file lists
300
+ dirnames = []
301
+ basenames = []
302
+ dirindexes = []
303
+ filemodes = []
304
+ filesizes = []
305
+ fileowners = []
306
+ filegroups = []
307
+ filemtimes = []
308
+ filedigests = []
309
+ filelinktos = []
310
+ fileflags = []
311
+
312
+ # Process directories first
313
+ dir_set = Set.new
314
+ @directories.each do |dir|
315
+ dir_path = dir[:path]
316
+ parent = File.dirname(dir_path.sub(%r{/+$}, ""))
317
+ dir_name = File.basename(dir_path.sub(%r{/+$}, ""))
318
+
319
+ dir_set.size
320
+ dir_set << dir_path
321
+
322
+ # Parent directory for relative path
323
+ parent_dir = parent == "." ? "/" : parent
324
+ dirnames.size
325
+ dirnames << parent_dir unless dirnames.include?(parent_dir)
326
+ parent_index = dirnames.index(parent_dir)
327
+
328
+ basenames << dir_name
329
+ dirindexes << parent_index
330
+ filemodes << (dir[:mode] | 0o040000) # Directory flag
331
+ filesizes << 4096 # Typical directory size
332
+ fileowners << dir[:owner]
333
+ filegroups << dir[:group]
334
+ filemtimes << Time.now.to_i
335
+ filedigests << ""
336
+ filelinktos << ""
337
+ fileflags << 0
338
+ end
339
+
340
+ # Process files
341
+ @files.each do |file|
342
+ file_path = file[:path]
343
+ parent_dir = File.dirname(file_path)
344
+ base_name = File.basename(file_path)
345
+
346
+ # Ensure directory is in list
347
+ dir_index = dirnames.index(parent_dir)
348
+ dir_index ||= dirnames.size.tap { dirnames << parent_dir }
349
+
350
+ basenames << base_name
351
+ dirindexes << dir_index
352
+ filemodes << file[:mode]
353
+ filesizes << file[:content].bytesize
354
+ fileowners << file[:owner]
355
+ filegroups << file[:group]
356
+ filemtimes << file[:mtime]
357
+ filedigests << Digest::MD5.hexdigest(file[:content])
358
+ filelinktos << ""
359
+ fileflags << 0
360
+ end
361
+
362
+ tags = [
363
+ { id: TAG_NAMES[:name], type: TYPE_STRING, value: @name },
364
+ { id: TAG_NAMES[:version], type: TYPE_STRING, value: @version },
365
+ { id: TAG_NAMES[:release], type: TYPE_STRING, value: @release },
366
+ { id: TAG_NAMES[:arch], type: TYPE_STRING, value: @arch },
367
+ { id: TAG_NAMES[:os], type: TYPE_STRING, value: "linux" },
368
+ { id: TAG_NAMES[:rpmversion], type: TYPE_STRING, value: "4.16.0" },
369
+ { id: TAG_NAMES[:payloadformat], type: TYPE_STRING, value: "cpio" },
370
+ ]
371
+
372
+ # Add compression-specific tags
373
+ comp_info = compression_info
374
+ if comp_info[:name]
375
+ tags << { id: TAG_NAMES[:payloadcompressor], type: TYPE_STRING,
376
+ value: comp_info[:name] }
377
+ tags << { id: TAG_NAMES[:payloadflags], type: TYPE_STRING,
378
+ value: comp_info[:flags] }
379
+ end
380
+
381
+ tags << { id: TAG_NAMES[:archivesize], type: TYPE_INT32,
382
+ value: [payload_size] }
383
+ tags.push(
384
+ { id: TAG_NAMES[:dirnames], type: TYPE_STRING_ARRAY,
385
+ value: dirnames },
386
+ { id: TAG_NAMES[:basenames], type: TYPE_STRING_ARRAY,
387
+ value: basenames },
388
+ { id: TAG_NAMES[:dirindexes], type: TYPE_INT32,
389
+ value: dirindexes },
390
+ { id: TAG_NAMES[:filemodes], type: TYPE_INT16,
391
+ value: filemodes },
392
+ { id: TAG_NAMES[:filesizes], type: TYPE_INT32,
393
+ value: filesizes },
394
+ { id: TAG_NAMES[:fileusername], type: TYPE_STRING_ARRAY,
395
+ value: fileowners },
396
+ { id: TAG_NAMES[:filegroupname], type: TYPE_STRING_ARRAY,
397
+ value: filegroups },
398
+ { id: TAG_NAMES[:filemtimes], type: TYPE_INT32,
399
+ value: filemtimes },
400
+ { id: TAG_NAMES[:filedigests], type: TYPE_STRING_ARRAY,
401
+ value: filedigests },
402
+ { id: TAG_NAMES[:filelinktos], type: TYPE_STRING_ARRAY,
403
+ value: filelinktos },
404
+ { id: TAG_NAMES[:fileflags], type: TYPE_INT32,
405
+ value: fileflags },
406
+ )
407
+
408
+ # Add optional metadata
409
+ {
410
+ summary: TYPE_STRING,
411
+ description: TYPE_STRING,
412
+ license: TYPE_STRING,
413
+ group: TYPE_STRING,
414
+ url: TYPE_STRING,
415
+ vendor: TYPE_STRING,
416
+ packager: TYPE_STRING,
417
+ }.each do |key, type|
418
+ value = @metadata[key]
419
+ tags << { id: TAG_NAMES[key], type: type, value: value } if value
420
+ end
421
+
422
+ if @epoch
423
+ tags << { id: TAG_NAMES[:epoch], type: TYPE_INT32,
424
+ value: [@epoch.to_i] }
425
+ end
426
+
427
+ build_header_data(tags)
428
+ end
429
+
430
+ # Build header data structure
431
+ #
432
+ # @param tags [Array<Hash>] Array of tag definitions
433
+ # @return [String] Packed header
434
+ def build_header_data(tags)
435
+ # Build data blob and tag entries
436
+ data_blob = "".b
437
+ tag_entries = []
438
+
439
+ tags.each do |tag_def|
440
+ offset = data_blob.bytesize
441
+ value = tag_def[:value]
442
+ type = tag_def[:type]
443
+
444
+ packed_data = pack_tag_value(type, value)
445
+ data_blob << packed_data
446
+
447
+ count = case type
448
+ when TYPE_STRING_ARRAY
449
+ value.is_a?(Array) ? value.size : 1
450
+ when TYPE_STRING
451
+ 1
452
+ else
453
+ value.is_a?(Array) ? value.size : 1
454
+ end
455
+
456
+ tag_entries << [tag_def[:id], type, offset, count].pack("NNNN")
457
+ end
458
+
459
+ # Build complete header
460
+ entry_count = tags.size
461
+ data_length = data_blob.bytesize
462
+
463
+ # Pad data blob to 8-byte boundary
464
+ padding = (8 - (data_length % 8)) % 8
465
+ data_blob << ("\0" * padding)
466
+
467
+ # Header header: magic (8) + entry_count (4) + data_length (4)
468
+ header_header = [HEADER_MAGIC, entry_count,
469
+ data_blob.bytesize].pack("A8 NN")
470
+
471
+ header_header + tag_entries.join + data_blob
472
+ end
473
+
474
+ # Pack tag value based on type
475
+ #
476
+ # @param type [Integer] Tag type
477
+ # @param value [Object] Value to pack
478
+ # @return [String] Packed data
479
+ def pack_tag_value(type, value)
480
+ case type
481
+ when TYPE_STRING
482
+ "#{value}\0".b
483
+ when TYPE_STRING_ARRAY
484
+ value.map { |v| "#{v}\0" }.join.b
485
+ when TYPE_INT8
486
+ [value].flatten.pack("C*")
487
+ when TYPE_INT16
488
+ [value].flatten.pack("n*")
489
+ when TYPE_INT32
490
+ [value].flatten.pack("N*")
491
+ when TYPE_INT64
492
+ [value].flatten.pack("Q>")
493
+ when TYPE_BINARY
494
+ value.b
495
+ else
496
+ value.to_s.b
497
+ end
498
+ end
499
+
500
+ # Build CPIO payload
501
+ #
502
+ # @return [String] CPIO archive data
503
+ def build_cpio_payload
504
+ cpio_io = StringIO.new("".b)
505
+
506
+ # Write directories
507
+ @directories.each do |dir|
508
+ entry_data = build_cpio_directory_entry(dir)
509
+ cpio_io.write(entry_data)
510
+ end
511
+
512
+ # Write files
513
+ @files.each do |file|
514
+ entry_data = build_cpio_file_entry(file)
515
+ cpio_io.write(entry_data)
516
+ end
517
+
518
+ # Write trailer
519
+ cpio_io.write(build_cpio_trailer)
520
+
521
+ cpio_io.string
522
+ end
523
+
524
+ # Build CPIO directory entry
525
+ #
526
+ # @param dir [Hash] Directory info
527
+ # @return [String] Packed CPIO entry
528
+ def build_cpio_directory_entry(dir)
529
+ mode = dir[:mode] | 0o040000 # Directory flag
530
+ path = dir[:path].sub(%r{/+$}, "") # Remove trailing slashes
531
+
532
+ build_cpio_entry(path, "", mode)
533
+ end
534
+
535
+ # Build CPIO file entry
536
+ #
537
+ # @param file [Hash] File info
538
+ # @return [String] Packed CPIO entry
539
+ def build_cpio_file_entry(file)
540
+ build_cpio_entry(file[:path], file[:content], file[:mode])
541
+ end
542
+
543
+ # Build CPIO entry (newc format)
544
+ #
545
+ # @param path [String] Entry path
546
+ # @param data [String] Entry data
547
+ # @param mode [Integer] File mode
548
+ # @return [String] Packed CPIO entry
549
+ def build_cpio_entry(path, data, mode)
550
+ name = path.start_with?("/") ? path[1..] : path
551
+ namesize = name.bytesize + 1
552
+ filesize = data.bytesize
553
+
554
+ inode = @inode_counter ||= 1
555
+ @inode_counter += 1
556
+
557
+ # Build header (110 bytes for newc)
558
+ header = format(
559
+ "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%s\x00",
560
+ inode, # inode
561
+ mode, # mode
562
+ 0, # uid
563
+ 0, # gid
564
+ 1, # nlink
565
+ Time.now.to_i, # mtime
566
+ filesize, # filesize
567
+ 0, # devmajor
568
+ 0, # devminor
569
+ 0, # rdevmajor
570
+ 0, # rdevminor
571
+ namesize, # namesize
572
+ 0, # checksum (0 for newc)
573
+ name, # name
574
+ )
575
+
576
+ # Pad header to 4-byte boundary
577
+ header_padding = (4 - (header.bytesize % 4)) % 4
578
+ header << ("\0" * header_padding)
579
+
580
+ # Pad data to 4-byte boundary
581
+ data_padding = (4 - (filesize % 4)) % 4
582
+
583
+ header + data + ("\0" * data_padding)
584
+ end
585
+
586
+ # Build CPIO trailer
587
+ #
588
+ # @return [String] Trailer entry
589
+ def build_cpio_trailer
590
+ build_cpio_entry("TRAILER!!!", "", 0)
591
+ end
592
+
593
+ # Compress payload
594
+ #
595
+ # @param data [String] Uncompressed data
596
+ # @param output [IO] Output IO for compressed data
597
+ def compress_payload(data, output)
598
+ case @compression
599
+ when :gzip
600
+ compress_gzip(data, output)
601
+ when :bzip2
602
+ compress_bzip2(data, output)
603
+ when :xz
604
+ compress_xz(data, output)
605
+ when :zstd
606
+ compress_zstd(data, output)
607
+ when :none
608
+ output.write(data)
609
+ else
610
+ raise ArgumentError, "Unsupported compression: #{@compression}"
611
+ end
612
+ end
613
+
614
+ # Compress with gzip
615
+ #
616
+ # @param data [String] Uncompressed data
617
+ # @param output [IO] Output IO
618
+ def compress_gzip(data, output)
619
+ gz = Zlib::GzipWriter.new(output, 9)
620
+ gz.write(data)
621
+ gz.finish
622
+ end
623
+
624
+ # Compress with bzip2
625
+ #
626
+ # @param data [String] Uncompressed data
627
+ # @param output [IO] Output IO
628
+ def compress_bzip2(data, output)
629
+ input_io = StringIO.new(data)
630
+ Bzip2File.compress_stream(input_io, output, level: 9)
631
+ end
632
+
633
+ # Compress with xz
634
+ #
635
+ # @param data [String] Uncompressed data
636
+ # @param output [IO] Output IO
637
+ def compress_xz(data, output)
638
+ Xz.create(data, output, dict_size: 8 * 1024 * 1024)
639
+ end
640
+
641
+ # Compress with zstd
642
+ #
643
+ # @param data [String] Uncompressed data
644
+ # @param output [IO] Output IO
645
+ def compress_zstd(data, output)
646
+ encoder = Algorithms::Zstandard::Encoder.new(output, level: 19)
647
+ encoder.encode_stream(data)
648
+ end
649
+ end
650
+ end
651
+ end
652
+ end