zstd-native-ruby 1.0.0

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 (651) hide show
  1. checksums.yaml +7 -0
  2. data/CLAUDE.md +101 -0
  3. data/LICENSE +19 -0
  4. data/README.md +47 -0
  5. data/ext/zstd_ruby/extconf.rb +35 -0
  6. data/ext/zstd_ruby/zstd_ruby.c +221 -0
  7. data/lib/zstd_ruby.rb +68 -0
  8. data/vendor/zstd/CHANGELOG +863 -0
  9. data/vendor/zstd/CMakeLists.txt +11 -0
  10. data/vendor/zstd/CODE_OF_CONDUCT.md +5 -0
  11. data/vendor/zstd/CONTRIBUTING.md +494 -0
  12. data/vendor/zstd/COPYING +339 -0
  13. data/vendor/zstd/LICENSE +30 -0
  14. data/vendor/zstd/Makefile +470 -0
  15. data/vendor/zstd/Package.swift +36 -0
  16. data/vendor/zstd/README.md +244 -0
  17. data/vendor/zstd/SECURITY.md +15 -0
  18. data/vendor/zstd/TESTING.md +43 -0
  19. data/vendor/zstd/build/LICENSE +0 -0
  20. data/vendor/zstd/build/README.md +56 -0
  21. data/vendor/zstd/build/VS2008/fullbench/fullbench.vcproj +549 -0
  22. data/vendor/zstd/build/VS2008/fuzzer/fuzzer.vcproj +585 -0
  23. data/vendor/zstd/build/VS2008/zstd/zstd.vcproj +677 -0
  24. data/vendor/zstd/build/VS2008/zstd.sln +56 -0
  25. data/vendor/zstd/build/VS2008/zstdlib/zstdlib.vcproj +635 -0
  26. data/vendor/zstd/build/VS2010/CompileAsCpp.props +8 -0
  27. data/vendor/zstd/build/VS2010/datagen/datagen.vcxproj +170 -0
  28. data/vendor/zstd/build/VS2010/fullbench/fullbench.vcxproj +220 -0
  29. data/vendor/zstd/build/VS2010/fuzzer/fuzzer.vcxproj +224 -0
  30. data/vendor/zstd/build/VS2010/libzstd/libzstd.vcxproj +243 -0
  31. data/vendor/zstd/build/VS2010/libzstd-dll/libzstd-dll.rc +51 -0
  32. data/vendor/zstd/build/VS2010/libzstd-dll/libzstd-dll.vcxproj +250 -0
  33. data/vendor/zstd/build/VS2010/zstd/zstd.rc +51 -0
  34. data/vendor/zstd/build/VS2010/zstd/zstd.vcxproj +266 -0
  35. data/vendor/zstd/build/VS2010/zstd.sln +84 -0
  36. data/vendor/zstd/build/VS_scripts/README.md +64 -0
  37. data/vendor/zstd/build/VS_scripts/build.VS2010.cmd +7 -0
  38. data/vendor/zstd/build/VS_scripts/build.VS2012.cmd +6 -0
  39. data/vendor/zstd/build/VS_scripts/build.VS2013.cmd +7 -0
  40. data/vendor/zstd/build/VS_scripts/build.VS2015.cmd +7 -0
  41. data/vendor/zstd/build/VS_scripts/build.VS2017.cmd +7 -0
  42. data/vendor/zstd/build/VS_scripts/build.VS2017Community.cmd +7 -0
  43. data/vendor/zstd/build/VS_scripts/build.VS2017Enterprise.cmd +7 -0
  44. data/vendor/zstd/build/VS_scripts/build.VS2017Professional.cmd +7 -0
  45. data/vendor/zstd/build/VS_scripts/build.VSPreview.cmd +7 -0
  46. data/vendor/zstd/build/VS_scripts/build.generic.cmd +67 -0
  47. data/vendor/zstd/build/cmake/CMakeLists.txt +81 -0
  48. data/vendor/zstd/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake +138 -0
  49. data/vendor/zstd/build/cmake/CMakeModules/FindLibLZ4.cmake +49 -0
  50. data/vendor/zstd/build/cmake/CMakeModules/GetZstdLibraryVersion.cmake +10 -0
  51. data/vendor/zstd/build/cmake/CMakeModules/JoinPaths.cmake +23 -0
  52. data/vendor/zstd/build/cmake/CMakeModules/ZstdBuild.cmake +42 -0
  53. data/vendor/zstd/build/cmake/CMakeModules/ZstdDependencies.cmake +30 -0
  54. data/vendor/zstd/build/cmake/CMakeModules/ZstdOptions.cmake +68 -0
  55. data/vendor/zstd/build/cmake/CMakeModules/ZstdPackage.cmake +42 -0
  56. data/vendor/zstd/build/cmake/CMakeModules/ZstdVersion.cmake +31 -0
  57. data/vendor/zstd/build/cmake/README.md +155 -0
  58. data/vendor/zstd/build/cmake/contrib/CMakeLists.txt +13 -0
  59. data/vendor/zstd/build/cmake/contrib/gen_html/CMakeLists.txt +30 -0
  60. data/vendor/zstd/build/cmake/contrib/pzstd/CMakeLists.txt +39 -0
  61. data/vendor/zstd/build/cmake/lib/CMakeLists.txt +298 -0
  62. data/vendor/zstd/build/cmake/lib/cmake_uninstall.cmake.in +22 -0
  63. data/vendor/zstd/build/cmake/programs/CMakeLists.txt +144 -0
  64. data/vendor/zstd/build/cmake/tests/CMakeLists.txt +118 -0
  65. data/vendor/zstd/build/cmake/zstdConfig.cmake.in +10 -0
  66. data/vendor/zstd/build/meson/GetZstdLibraryVersion.py +39 -0
  67. data/vendor/zstd/build/meson/InstallSymlink.py +55 -0
  68. data/vendor/zstd/build/meson/README.md +38 -0
  69. data/vendor/zstd/build/meson/contrib/gen_html/meson.build +30 -0
  70. data/vendor/zstd/build/meson/contrib/meson.build +12 -0
  71. data/vendor/zstd/build/meson/contrib/pzstd/meson.build +25 -0
  72. data/vendor/zstd/build/meson/lib/meson.build +175 -0
  73. data/vendor/zstd/build/meson/meson.build +155 -0
  74. data/vendor/zstd/build/meson/meson_options.txt +36 -0
  75. data/vendor/zstd/build/meson/programs/meson.build +124 -0
  76. data/vendor/zstd/build/meson/tests/meson.build +217 -0
  77. data/vendor/zstd/build/meson/tests/valgrindTest.py +90 -0
  78. data/vendor/zstd/build/single_file_libs/README.md +33 -0
  79. data/vendor/zstd/build/single_file_libs/build_decoder_test.sh +91 -0
  80. data/vendor/zstd/build/single_file_libs/build_library_test.sh +98 -0
  81. data/vendor/zstd/build/single_file_libs/combine.py +234 -0
  82. data/vendor/zstd/build/single_file_libs/combine.sh +249 -0
  83. data/vendor/zstd/build/single_file_libs/create_single_file_decoder.sh +19 -0
  84. data/vendor/zstd/build/single_file_libs/create_single_file_library.sh +19 -0
  85. data/vendor/zstd/build/single_file_libs/examples/README.md +11 -0
  86. data/vendor/zstd/build/single_file_libs/examples/emscripten.c +340 -0
  87. data/vendor/zstd/build/single_file_libs/examples/roundtrip.c +83 -0
  88. data/vendor/zstd/build/single_file_libs/examples/shell.html +31 -0
  89. data/vendor/zstd/build/single_file_libs/examples/simple.c +75 -0
  90. data/vendor/zstd/build/single_file_libs/examples/testcard-dxt1.inl +2731 -0
  91. data/vendor/zstd/build/single_file_libs/examples/testcard-zstd.inl +261 -0
  92. data/vendor/zstd/build/single_file_libs/examples/testcard.png +0 -0
  93. data/vendor/zstd/build/single_file_libs/zstd-in.c +91 -0
  94. data/vendor/zstd/build/single_file_libs/zstddeclib-in.c +62 -0
  95. data/vendor/zstd/contrib/VS2005/README.md +3 -0
  96. data/vendor/zstd/contrib/VS2005/fullbench/fullbench.vcproj +440 -0
  97. data/vendor/zstd/contrib/VS2005/fuzzer/fuzzer.vcproj +488 -0
  98. data/vendor/zstd/contrib/VS2005/zstd/zstd.vcproj +552 -0
  99. data/vendor/zstd/contrib/VS2005/zstd.sln +55 -0
  100. data/vendor/zstd/contrib/VS2005/zstdlib/zstdlib.vcproj +546 -0
  101. data/vendor/zstd/contrib/cleanTabs +2 -0
  102. data/vendor/zstd/contrib/diagnose_corruption/Makefile +35 -0
  103. data/vendor/zstd/contrib/diagnose_corruption/check_flipped_bits.c +400 -0
  104. data/vendor/zstd/contrib/docker/Dockerfile +20 -0
  105. data/vendor/zstd/contrib/docker/README.md +20 -0
  106. data/vendor/zstd/contrib/externalSequenceProducer/Makefile +40 -0
  107. data/vendor/zstd/contrib/externalSequenceProducer/README.md +14 -0
  108. data/vendor/zstd/contrib/externalSequenceProducer/main.c +108 -0
  109. data/vendor/zstd/contrib/externalSequenceProducer/sequence_producer.c +80 -0
  110. data/vendor/zstd/contrib/externalSequenceProducer/sequence_producer.h +26 -0
  111. data/vendor/zstd/contrib/freestanding_lib/freestanding.py +774 -0
  112. data/vendor/zstd/contrib/gen_html/Makefile +51 -0
  113. data/vendor/zstd/contrib/gen_html/README.md +31 -0
  114. data/vendor/zstd/contrib/gen_html/gen-zstd-manual.sh +9 -0
  115. data/vendor/zstd/contrib/gen_html/gen_html.cpp +225 -0
  116. data/vendor/zstd/contrib/largeNbDicts/Makefile +58 -0
  117. data/vendor/zstd/contrib/largeNbDicts/README.md +33 -0
  118. data/vendor/zstd/contrib/largeNbDicts/largeNbDicts.c +1087 -0
  119. data/vendor/zstd/contrib/linux-kernel/Makefile +108 -0
  120. data/vendor/zstd/contrib/linux-kernel/README.md +14 -0
  121. data/vendor/zstd/contrib/linux-kernel/btrfs-benchmark.sh +104 -0
  122. data/vendor/zstd/contrib/linux-kernel/btrfs-extract-benchmark.sh +99 -0
  123. data/vendor/zstd/contrib/linux-kernel/decompress_sources.h +34 -0
  124. data/vendor/zstd/contrib/linux-kernel/linux.mk +44 -0
  125. data/vendor/zstd/contrib/linux-kernel/linux_zstd.h +691 -0
  126. data/vendor/zstd/contrib/linux-kernel/mem.h +262 -0
  127. data/vendor/zstd/contrib/linux-kernel/squashfs-benchmark.sh +39 -0
  128. data/vendor/zstd/contrib/linux-kernel/test/Makefile +49 -0
  129. data/vendor/zstd/contrib/linux-kernel/test/include/linux/compiler.h +23 -0
  130. data/vendor/zstd/contrib/linux-kernel/test/include/linux/errno.h +15 -0
  131. data/vendor/zstd/contrib/linux-kernel/test/include/linux/kernel.h +19 -0
  132. data/vendor/zstd/contrib/linux-kernel/test/include/linux/limits.h +15 -0
  133. data/vendor/zstd/contrib/linux-kernel/test/include/linux/math64.h +15 -0
  134. data/vendor/zstd/contrib/linux-kernel/test/include/linux/module.h +20 -0
  135. data/vendor/zstd/contrib/linux-kernel/test/include/linux/printk.h +15 -0
  136. data/vendor/zstd/contrib/linux-kernel/test/include/linux/stddef.h +15 -0
  137. data/vendor/zstd/contrib/linux-kernel/test/include/linux/swab.h +16 -0
  138. data/vendor/zstd/contrib/linux-kernel/test/include/linux/types.h +16 -0
  139. data/vendor/zstd/contrib/linux-kernel/test/include/linux/unaligned.h +187 -0
  140. data/vendor/zstd/contrib/linux-kernel/test/include/linux/xxhash.h +745 -0
  141. data/vendor/zstd/contrib/linux-kernel/test/macro-test.sh +44 -0
  142. data/vendor/zstd/contrib/linux-kernel/test/static_test.c +52 -0
  143. data/vendor/zstd/contrib/linux-kernel/test/test.c +229 -0
  144. data/vendor/zstd/contrib/linux-kernel/zstd_common_module.c +29 -0
  145. data/vendor/zstd/contrib/linux-kernel/zstd_compress_module.c +286 -0
  146. data/vendor/zstd/contrib/linux-kernel/zstd_decompress_module.c +141 -0
  147. data/vendor/zstd/contrib/linux-kernel/zstd_deps.h +121 -0
  148. data/vendor/zstd/contrib/match_finders/README.md +42 -0
  149. data/vendor/zstd/contrib/match_finders/zstd_edist.c +558 -0
  150. data/vendor/zstd/contrib/match_finders/zstd_edist.h +70 -0
  151. data/vendor/zstd/contrib/premake/premake4.lua +6 -0
  152. data/vendor/zstd/contrib/premake/zstd.lua +81 -0
  153. data/vendor/zstd/contrib/pzstd/BUCK +72 -0
  154. data/vendor/zstd/contrib/pzstd/ErrorHolder.h +54 -0
  155. data/vendor/zstd/contrib/pzstd/Logging.h +73 -0
  156. data/vendor/zstd/contrib/pzstd/Makefile +265 -0
  157. data/vendor/zstd/contrib/pzstd/Options.cpp +424 -0
  158. data/vendor/zstd/contrib/pzstd/Options.h +71 -0
  159. data/vendor/zstd/contrib/pzstd/Pzstd.cpp +626 -0
  160. data/vendor/zstd/contrib/pzstd/Pzstd.h +153 -0
  161. data/vendor/zstd/contrib/pzstd/README.md +56 -0
  162. data/vendor/zstd/contrib/pzstd/SkippableFrame.cpp +30 -0
  163. data/vendor/zstd/contrib/pzstd/SkippableFrame.h +64 -0
  164. data/vendor/zstd/contrib/pzstd/images/Cspeed.png +0 -0
  165. data/vendor/zstd/contrib/pzstd/images/Dspeed.png +0 -0
  166. data/vendor/zstd/contrib/pzstd/main.cpp +27 -0
  167. data/vendor/zstd/contrib/pzstd/test/BUCK +37 -0
  168. data/vendor/zstd/contrib/pzstd/test/OptionsTest.cpp +536 -0
  169. data/vendor/zstd/contrib/pzstd/test/PzstdTest.cpp +147 -0
  170. data/vendor/zstd/contrib/pzstd/test/RoundTrip.h +86 -0
  171. data/vendor/zstd/contrib/pzstd/test/RoundTripTest.cpp +84 -0
  172. data/vendor/zstd/contrib/pzstd/utils/BUCK +75 -0
  173. data/vendor/zstd/contrib/pzstd/utils/Buffer.h +99 -0
  174. data/vendor/zstd/contrib/pzstd/utils/FileSystem.h +96 -0
  175. data/vendor/zstd/contrib/pzstd/utils/Likely.h +28 -0
  176. data/vendor/zstd/contrib/pzstd/utils/Portability.h +16 -0
  177. data/vendor/zstd/contrib/pzstd/utils/Range.h +133 -0
  178. data/vendor/zstd/contrib/pzstd/utils/ResourcePool.h +96 -0
  179. data/vendor/zstd/contrib/pzstd/utils/ScopeGuard.h +50 -0
  180. data/vendor/zstd/contrib/pzstd/utils/ThreadPool.h +58 -0
  181. data/vendor/zstd/contrib/pzstd/utils/WorkQueue.h +182 -0
  182. data/vendor/zstd/contrib/pzstd/utils/test/BUCK +35 -0
  183. data/vendor/zstd/contrib/pzstd/utils/test/BufferTest.cpp +89 -0
  184. data/vendor/zstd/contrib/pzstd/utils/test/RangeTest.cpp +82 -0
  185. data/vendor/zstd/contrib/pzstd/utils/test/ResourcePoolTest.cpp +72 -0
  186. data/vendor/zstd/contrib/pzstd/utils/test/ScopeGuardTest.cpp +28 -0
  187. data/vendor/zstd/contrib/pzstd/utils/test/ThreadPoolTest.cpp +71 -0
  188. data/vendor/zstd/contrib/pzstd/utils/test/WorkQueueTest.cpp +282 -0
  189. data/vendor/zstd/contrib/recovery/Makefile +35 -0
  190. data/vendor/zstd/contrib/recovery/recover_directory.c +152 -0
  191. data/vendor/zstd/contrib/seekable_format/README.md +42 -0
  192. data/vendor/zstd/contrib/seekable_format/examples/Makefile +55 -0
  193. data/vendor/zstd/contrib/seekable_format/examples/parallel_compression.c +254 -0
  194. data/vendor/zstd/contrib/seekable_format/examples/parallel_processing.c +191 -0
  195. data/vendor/zstd/contrib/seekable_format/examples/seekable_compression.c +136 -0
  196. data/vendor/zstd/contrib/seekable_format/examples/seekable_decompression.c +141 -0
  197. data/vendor/zstd/contrib/seekable_format/examples/seekable_decompression_mem.c +147 -0
  198. data/vendor/zstd/contrib/seekable_format/tests/Makefile +58 -0
  199. data/vendor/zstd/contrib/seekable_format/tests/seekable_tests.c +375 -0
  200. data/vendor/zstd/contrib/seekable_format/zstd_seekable.h +226 -0
  201. data/vendor/zstd/contrib/seekable_format/zstd_seekable_compression_format.md +116 -0
  202. data/vendor/zstd/contrib/seekable_format/zstdseek_compress.c +365 -0
  203. data/vendor/zstd/contrib/seekable_format/zstdseek_decompress.c +600 -0
  204. data/vendor/zstd/contrib/seqBench/Makefile +58 -0
  205. data/vendor/zstd/contrib/seqBench/seqBench.c +53 -0
  206. data/vendor/zstd/contrib/snap/snapcraft.yaml +28 -0
  207. data/vendor/zstd/doc/README.md +26 -0
  208. data/vendor/zstd/doc/decompressor_errata.md +148 -0
  209. data/vendor/zstd/doc/decompressor_permissive.md +80 -0
  210. data/vendor/zstd/doc/educational_decoder/Makefile +62 -0
  211. data/vendor/zstd/doc/educational_decoder/README.md +36 -0
  212. data/vendor/zstd/doc/educational_decoder/harness.c +119 -0
  213. data/vendor/zstd/doc/educational_decoder/zstd_decompress.c +2323 -0
  214. data/vendor/zstd/doc/educational_decoder/zstd_decompress.h +61 -0
  215. data/vendor/zstd/doc/images/CSpeed2.png +0 -0
  216. data/vendor/zstd/doc/images/DCspeed5.png +0 -0
  217. data/vendor/zstd/doc/images/DSpeed3.png +0 -0
  218. data/vendor/zstd/doc/images/cdict_v136.png +0 -0
  219. data/vendor/zstd/doc/images/dict-cr.png +0 -0
  220. data/vendor/zstd/doc/images/dict-cs.png +0 -0
  221. data/vendor/zstd/doc/images/dict-ds.png +0 -0
  222. data/vendor/zstd/doc/images/zstd_cdict_v1_3_5.png +0 -0
  223. data/vendor/zstd/doc/images/zstd_logo86.png +0 -0
  224. data/vendor/zstd/doc/zstd_compression_format.md +1772 -0
  225. data/vendor/zstd/doc/zstd_manual.html +2244 -0
  226. data/vendor/zstd/examples/Makefile +93 -0
  227. data/vendor/zstd/examples/README.md +46 -0
  228. data/vendor/zstd/examples/common.h +246 -0
  229. data/vendor/zstd/examples/dictionary_compression.c +107 -0
  230. data/vendor/zstd/examples/dictionary_decompression.c +99 -0
  231. data/vendor/zstd/examples/multiple_simple_compression.c +116 -0
  232. data/vendor/zstd/examples/multiple_streaming_compression.c +133 -0
  233. data/vendor/zstd/examples/simple_compression.c +68 -0
  234. data/vendor/zstd/examples/simple_decompression.c +65 -0
  235. data/vendor/zstd/examples/streaming_compression.c +146 -0
  236. data/vendor/zstd/examples/streaming_compression_thread_pool.c +180 -0
  237. data/vendor/zstd/examples/streaming_decompression.c +100 -0
  238. data/vendor/zstd/examples/streaming_memory_usage.c +137 -0
  239. data/vendor/zstd/lib/BUCK +232 -0
  240. data/vendor/zstd/lib/Makefile +389 -0
  241. data/vendor/zstd/lib/README.md +267 -0
  242. data/vendor/zstd/lib/common/allocations.h +55 -0
  243. data/vendor/zstd/lib/common/bits.h +205 -0
  244. data/vendor/zstd/lib/common/bitstream.h +454 -0
  245. data/vendor/zstd/lib/common/compiler.h +482 -0
  246. data/vendor/zstd/lib/common/cpu.h +249 -0
  247. data/vendor/zstd/lib/common/debug.c +30 -0
  248. data/vendor/zstd/lib/common/debug.h +107 -0
  249. data/vendor/zstd/lib/common/debug.o +0 -0
  250. data/vendor/zstd/lib/common/entropy_common.c +340 -0
  251. data/vendor/zstd/lib/common/entropy_common.o +0 -0
  252. data/vendor/zstd/lib/common/error_private.c +64 -0
  253. data/vendor/zstd/lib/common/error_private.h +158 -0
  254. data/vendor/zstd/lib/common/error_private.o +0 -0
  255. data/vendor/zstd/lib/common/fse.h +625 -0
  256. data/vendor/zstd/lib/common/fse_decompress.c +315 -0
  257. data/vendor/zstd/lib/common/fse_decompress.o +0 -0
  258. data/vendor/zstd/lib/common/huf.h +277 -0
  259. data/vendor/zstd/lib/common/mem.h +422 -0
  260. data/vendor/zstd/lib/common/pool.c +371 -0
  261. data/vendor/zstd/lib/common/pool.h +81 -0
  262. data/vendor/zstd/lib/common/pool.o +0 -0
  263. data/vendor/zstd/lib/common/portability_macros.h +190 -0
  264. data/vendor/zstd/lib/common/threading.c +196 -0
  265. data/vendor/zstd/lib/common/threading.h +142 -0
  266. data/vendor/zstd/lib/common/threading.o +0 -0
  267. data/vendor/zstd/lib/common/xxhash.c +18 -0
  268. data/vendor/zstd/lib/common/xxhash.h +7094 -0
  269. data/vendor/zstd/lib/common/xxhash.o +0 -0
  270. data/vendor/zstd/lib/common/zstd_common.c +57 -0
  271. data/vendor/zstd/lib/common/zstd_common.o +0 -0
  272. data/vendor/zstd/lib/common/zstd_deps.h +123 -0
  273. data/vendor/zstd/lib/common/zstd_internal.h +326 -0
  274. data/vendor/zstd/lib/common/zstd_trace.h +156 -0
  275. data/vendor/zstd/lib/compress/clevels.h +134 -0
  276. data/vendor/zstd/lib/compress/fse_compress.c +625 -0
  277. data/vendor/zstd/lib/compress/fse_compress.o +0 -0
  278. data/vendor/zstd/lib/compress/hist.c +446 -0
  279. data/vendor/zstd/lib/compress/hist.h +86 -0
  280. data/vendor/zstd/lib/compress/hist.o +0 -0
  281. data/vendor/zstd/lib/compress/huf_compress.c +1465 -0
  282. data/vendor/zstd/lib/compress/huf_compress.o +0 -0
  283. data/vendor/zstd/lib/compress/zstd_compress.c +8362 -0
  284. data/vendor/zstd/lib/compress/zstd_compress.o +0 -0
  285. data/vendor/zstd/lib/compress/zstd_compress_internal.h +1636 -0
  286. data/vendor/zstd/lib/compress/zstd_compress_literals.c +235 -0
  287. data/vendor/zstd/lib/compress/zstd_compress_literals.h +39 -0
  288. data/vendor/zstd/lib/compress/zstd_compress_literals.o +0 -0
  289. data/vendor/zstd/lib/compress/zstd_compress_sequences.c +442 -0
  290. data/vendor/zstd/lib/compress/zstd_compress_sequences.h +55 -0
  291. data/vendor/zstd/lib/compress/zstd_compress_sequences.o +0 -0
  292. data/vendor/zstd/lib/compress/zstd_compress_superblock.c +688 -0
  293. data/vendor/zstd/lib/compress/zstd_compress_superblock.h +32 -0
  294. data/vendor/zstd/lib/compress/zstd_compress_superblock.o +0 -0
  295. data/vendor/zstd/lib/compress/zstd_cwksp.h +765 -0
  296. data/vendor/zstd/lib/compress/zstd_double_fast.c +778 -0
  297. data/vendor/zstd/lib/compress/zstd_double_fast.h +42 -0
  298. data/vendor/zstd/lib/compress/zstd_double_fast.o +0 -0
  299. data/vendor/zstd/lib/compress/zstd_fast.c +985 -0
  300. data/vendor/zstd/lib/compress/zstd_fast.h +30 -0
  301. data/vendor/zstd/lib/compress/zstd_fast.o +0 -0
  302. data/vendor/zstd/lib/compress/zstd_lazy.c +2243 -0
  303. data/vendor/zstd/lib/compress/zstd_lazy.h +193 -0
  304. data/vendor/zstd/lib/compress/zstd_lazy.o +0 -0
  305. data/vendor/zstd/lib/compress/zstd_ldm.c +745 -0
  306. data/vendor/zstd/lib/compress/zstd_ldm.h +109 -0
  307. data/vendor/zstd/lib/compress/zstd_ldm.o +0 -0
  308. data/vendor/zstd/lib/compress/zstd_ldm_geartab.h +106 -0
  309. data/vendor/zstd/lib/compress/zstd_opt.c +1572 -0
  310. data/vendor/zstd/lib/compress/zstd_opt.h +72 -0
  311. data/vendor/zstd/lib/compress/zstd_opt.o +0 -0
  312. data/vendor/zstd/lib/compress/zstd_preSplit.c +238 -0
  313. data/vendor/zstd/lib/compress/zstd_preSplit.h +33 -0
  314. data/vendor/zstd/lib/compress/zstd_preSplit.o +0 -0
  315. data/vendor/zstd/lib/compress/zstdmt_compress.c +1924 -0
  316. data/vendor/zstd/lib/compress/zstdmt_compress.h +102 -0
  317. data/vendor/zstd/lib/compress/zstdmt_compress.o +0 -0
  318. data/vendor/zstd/lib/decompress/huf_decompress.c +1953 -0
  319. data/vendor/zstd/lib/decompress/huf_decompress.o +0 -0
  320. data/vendor/zstd/lib/decompress/huf_decompress_amd64.S +766 -0
  321. data/vendor/zstd/lib/decompress/zstd_ddict.c +244 -0
  322. data/vendor/zstd/lib/decompress/zstd_ddict.h +44 -0
  323. data/vendor/zstd/lib/decompress/zstd_ddict.o +0 -0
  324. data/vendor/zstd/lib/decompress/zstd_decompress.c +2410 -0
  325. data/vendor/zstd/lib/decompress/zstd_decompress.o +0 -0
  326. data/vendor/zstd/lib/decompress/zstd_decompress_block.c +2311 -0
  327. data/vendor/zstd/lib/decompress/zstd_decompress_block.h +73 -0
  328. data/vendor/zstd/lib/decompress/zstd_decompress_block.o +0 -0
  329. data/vendor/zstd/lib/decompress/zstd_decompress_internal.h +240 -0
  330. data/vendor/zstd/lib/deprecated/zbuff.h +214 -0
  331. data/vendor/zstd/lib/deprecated/zbuff_common.c +26 -0
  332. data/vendor/zstd/lib/deprecated/zbuff_compress.c +167 -0
  333. data/vendor/zstd/lib/deprecated/zbuff_decompress.c +77 -0
  334. data/vendor/zstd/lib/dictBuilder/cover.c +1333 -0
  335. data/vendor/zstd/lib/dictBuilder/cover.h +152 -0
  336. data/vendor/zstd/lib/dictBuilder/divsufsort.c +1913 -0
  337. data/vendor/zstd/lib/dictBuilder/divsufsort.h +57 -0
  338. data/vendor/zstd/lib/dictBuilder/fastcover.c +765 -0
  339. data/vendor/zstd/lib/dictBuilder/zdict.c +1137 -0
  340. data/vendor/zstd/lib/dll/example/Makefile +48 -0
  341. data/vendor/zstd/lib/dll/example/README.md +63 -0
  342. data/vendor/zstd/lib/dll/example/build_package.bat +55 -0
  343. data/vendor/zstd/lib/dll/example/fullbench-dll.sln +25 -0
  344. data/vendor/zstd/lib/dll/example/fullbench-dll.vcxproj +181 -0
  345. data/vendor/zstd/lib/install_oses.mk +17 -0
  346. data/vendor/zstd/lib/legacy/zstd_legacy.h +452 -0
  347. data/vendor/zstd/lib/legacy/zstd_v01.c +2128 -0
  348. data/vendor/zstd/lib/legacy/zstd_v01.h +94 -0
  349. data/vendor/zstd/lib/legacy/zstd_v02.c +3465 -0
  350. data/vendor/zstd/lib/legacy/zstd_v02.h +93 -0
  351. data/vendor/zstd/lib/legacy/zstd_v03.c +3105 -0
  352. data/vendor/zstd/lib/legacy/zstd_v03.h +93 -0
  353. data/vendor/zstd/lib/legacy/zstd_v04.c +3598 -0
  354. data/vendor/zstd/lib/legacy/zstd_v04.h +142 -0
  355. data/vendor/zstd/lib/legacy/zstd_v05.c +4005 -0
  356. data/vendor/zstd/lib/legacy/zstd_v05.h +162 -0
  357. data/vendor/zstd/lib/legacy/zstd_v06.c +4110 -0
  358. data/vendor/zstd/lib/legacy/zstd_v06.h +172 -0
  359. data/vendor/zstd/lib/legacy/zstd_v07.c +4490 -0
  360. data/vendor/zstd/lib/legacy/zstd_v07.h +187 -0
  361. data/vendor/zstd/lib/libzstd.mk +238 -0
  362. data/vendor/zstd/lib/libzstd.pc.in +17 -0
  363. data/vendor/zstd/lib/module.modulemap +35 -0
  364. data/vendor/zstd/lib/zdict.h +481 -0
  365. data/vendor/zstd/lib/zstd.h +3209 -0
  366. data/vendor/zstd/lib/zstd_errors.h +107 -0
  367. data/vendor/zstd/programs/BUCK +44 -0
  368. data/vendor/zstd/programs/Makefile +445 -0
  369. data/vendor/zstd/programs/README.md +344 -0
  370. data/vendor/zstd/programs/benchfn.c +256 -0
  371. data/vendor/zstd/programs/benchfn.h +173 -0
  372. data/vendor/zstd/programs/benchzstd.c +1270 -0
  373. data/vendor/zstd/programs/benchzstd.h +191 -0
  374. data/vendor/zstd/programs/datagen.c +186 -0
  375. data/vendor/zstd/programs/datagen.h +38 -0
  376. data/vendor/zstd/programs/dibio.c +447 -0
  377. data/vendor/zstd/programs/dibio.h +39 -0
  378. data/vendor/zstd/programs/fileio.c +3717 -0
  379. data/vendor/zstd/programs/fileio.h +171 -0
  380. data/vendor/zstd/programs/fileio_asyncio.c +663 -0
  381. data/vendor/zstd/programs/fileio_asyncio.h +195 -0
  382. data/vendor/zstd/programs/fileio_common.h +121 -0
  383. data/vendor/zstd/programs/fileio_types.h +86 -0
  384. data/vendor/zstd/programs/lorem.c +285 -0
  385. data/vendor/zstd/programs/lorem.h +32 -0
  386. data/vendor/zstd/programs/platform.h +217 -0
  387. data/vendor/zstd/programs/timefn.c +170 -0
  388. data/vendor/zstd/programs/timefn.h +59 -0
  389. data/vendor/zstd/programs/util.c +1731 -0
  390. data/vendor/zstd/programs/util.h +364 -0
  391. data/vendor/zstd/programs/windres/verrsrc.h +17 -0
  392. data/vendor/zstd/programs/windres/zstd.rc +51 -0
  393. data/vendor/zstd/programs/windres/zstd32.res +0 -0
  394. data/vendor/zstd/programs/windres/zstd64.res +0 -0
  395. data/vendor/zstd/programs/zstd.1 +580 -0
  396. data/vendor/zstd/programs/zstd.1.md +714 -0
  397. data/vendor/zstd/programs/zstdcli.c +1675 -0
  398. data/vendor/zstd/programs/zstdcli_trace.c +173 -0
  399. data/vendor/zstd/programs/zstdcli_trace.h +24 -0
  400. data/vendor/zstd/programs/zstdgrep +134 -0
  401. data/vendor/zstd/programs/zstdgrep.1 +26 -0
  402. data/vendor/zstd/programs/zstdgrep.1.md +30 -0
  403. data/vendor/zstd/programs/zstdless +8 -0
  404. data/vendor/zstd/programs/zstdless.1 +14 -0
  405. data/vendor/zstd/programs/zstdless.1.md +16 -0
  406. data/vendor/zstd/tests/DEPRECATED-test-zstd-speed.py +378 -0
  407. data/vendor/zstd/tests/Makefile +485 -0
  408. data/vendor/zstd/tests/README.md +184 -0
  409. data/vendor/zstd/tests/automated_benchmarking.py +326 -0
  410. data/vendor/zstd/tests/checkTag.c +65 -0
  411. data/vendor/zstd/tests/check_size.py +31 -0
  412. data/vendor/zstd/tests/cli-tests/README.md +258 -0
  413. data/vendor/zstd/tests/cli-tests/basic/args.sh +10 -0
  414. data/vendor/zstd/tests/cli-tests/basic/args.sh.exit +1 -0
  415. data/vendor/zstd/tests/cli-tests/basic/args.sh.stderr.glob +28 -0
  416. data/vendor/zstd/tests/cli-tests/basic/help.sh +10 -0
  417. data/vendor/zstd/tests/cli-tests/basic/help.sh.stdout.glob +34 -0
  418. data/vendor/zstd/tests/cli-tests/basic/memlimit.sh +40 -0
  419. data/vendor/zstd/tests/cli-tests/basic/memlimit.sh.stderr.exact +13 -0
  420. data/vendor/zstd/tests/cli-tests/basic/memlimit.sh.stdout.exact +13 -0
  421. data/vendor/zstd/tests/cli-tests/basic/output_dir.sh +7 -0
  422. data/vendor/zstd/tests/cli-tests/basic/output_dir.sh.stderr.exact +2 -0
  423. data/vendor/zstd/tests/cli-tests/basic/output_dir.sh.stdout.exact +2 -0
  424. data/vendor/zstd/tests/cli-tests/basic/version.sh +6 -0
  425. data/vendor/zstd/tests/cli-tests/basic/version.sh.stdout.glob +2 -0
  426. data/vendor/zstd/tests/cli-tests/bin/cmp_size +44 -0
  427. data/vendor/zstd/tests/cli-tests/bin/datagen +3 -0
  428. data/vendor/zstd/tests/cli-tests/bin/die +4 -0
  429. data/vendor/zstd/tests/cli-tests/bin/println +2 -0
  430. data/vendor/zstd/tests/cli-tests/bin/unzstd +1 -0
  431. data/vendor/zstd/tests/cli-tests/bin/zstd +9 -0
  432. data/vendor/zstd/tests/cli-tests/bin/zstdcat +1 -0
  433. data/vendor/zstd/tests/cli-tests/bin/zstdgrep +2 -0
  434. data/vendor/zstd/tests/cli-tests/bin/zstdless +2 -0
  435. data/vendor/zstd/tests/cli-tests/cltools/setup +6 -0
  436. data/vendor/zstd/tests/cli-tests/cltools/zstdgrep.sh +8 -0
  437. data/vendor/zstd/tests/cli-tests/cltools/zstdgrep.sh.exit +1 -0
  438. data/vendor/zstd/tests/cli-tests/cltools/zstdgrep.sh.stderr.exact +1 -0
  439. data/vendor/zstd/tests/cli-tests/cltools/zstdgrep.sh.stdout.glob +4 -0
  440. data/vendor/zstd/tests/cli-tests/cltools/zstdless.sh +10 -0
  441. data/vendor/zstd/tests/cli-tests/cltools/zstdless.sh.stderr.exact +2 -0
  442. data/vendor/zstd/tests/cli-tests/cltools/zstdless.sh.stdout.glob +5 -0
  443. data/vendor/zstd/tests/cli-tests/common/format.sh +19 -0
  444. data/vendor/zstd/tests/cli-tests/common/mtime.sh +13 -0
  445. data/vendor/zstd/tests/cli-tests/common/permissions.sh +18 -0
  446. data/vendor/zstd/tests/cli-tests/common/platform.sh +47 -0
  447. data/vendor/zstd/tests/cli-tests/compression/adapt.sh +14 -0
  448. data/vendor/zstd/tests/cli-tests/compression/basic.sh +36 -0
  449. data/vendor/zstd/tests/cli-tests/compression/compress-literals.sh +10 -0
  450. data/vendor/zstd/tests/cli-tests/compression/format.sh +16 -0
  451. data/vendor/zstd/tests/cli-tests/compression/golden.sh +16 -0
  452. data/vendor/zstd/tests/cli-tests/compression/gzip-compat.sh +17 -0
  453. data/vendor/zstd/tests/cli-tests/compression/levels.sh +75 -0
  454. data/vendor/zstd/tests/cli-tests/compression/levels.sh.stderr.exact +80 -0
  455. data/vendor/zstd/tests/cli-tests/compression/long-distance-matcher.sh +7 -0
  456. data/vendor/zstd/tests/cli-tests/compression/multi-threaded.sh +22 -0
  457. data/vendor/zstd/tests/cli-tests/compression/multi-threaded.sh.stderr.exact +21 -0
  458. data/vendor/zstd/tests/cli-tests/compression/multiple-files.sh +21 -0
  459. data/vendor/zstd/tests/cli-tests/compression/multiple-files.sh.stdout.exact +12 -0
  460. data/vendor/zstd/tests/cli-tests/compression/row-match-finder.sh +7 -0
  461. data/vendor/zstd/tests/cli-tests/compression/setup +7 -0
  462. data/vendor/zstd/tests/cli-tests/compression/stream-size.sh +7 -0
  463. data/vendor/zstd/tests/cli-tests/compression/verbose-wlog.sh +11 -0
  464. data/vendor/zstd/tests/cli-tests/compression/verbose-wlog.sh.stderr.glob +5 -0
  465. data/vendor/zstd/tests/cli-tests/compression/verbose-wlog.sh.stdout.glob +5 -0
  466. data/vendor/zstd/tests/cli-tests/compression/window-resize.sh +9 -0
  467. data/vendor/zstd/tests/cli-tests/compression/window-resize.sh.stderr.ignore +0 -0
  468. data/vendor/zstd/tests/cli-tests/compression/window-resize.sh.stdout.glob +3 -0
  469. data/vendor/zstd/tests/cli-tests/decompression/detectErrors.sh +11 -0
  470. data/vendor/zstd/tests/cli-tests/decompression/golden.sh +7 -0
  471. data/vendor/zstd/tests/cli-tests/decompression/pass-through.sh +57 -0
  472. data/vendor/zstd/tests/cli-tests/decompression/pass-through.sh.stderr.exact +11 -0
  473. data/vendor/zstd/tests/cli-tests/decompression/pass-through.sh.stdout.exact +25 -0
  474. data/vendor/zstd/tests/cli-tests/determinism/basic.sh +36 -0
  475. data/vendor/zstd/tests/cli-tests/determinism/basic.sh.stderr.exact +0 -0
  476. data/vendor/zstd/tests/cli-tests/determinism/basic.sh.stdout.exact +880 -0
  477. data/vendor/zstd/tests/cli-tests/determinism/multithread.sh +45 -0
  478. data/vendor/zstd/tests/cli-tests/determinism/multithread.sh.stderr.exact +0 -0
  479. data/vendor/zstd/tests/cli-tests/determinism/multithread.sh.stdout.exact +260 -0
  480. data/vendor/zstd/tests/cli-tests/determinism/reuse.sh +44 -0
  481. data/vendor/zstd/tests/cli-tests/determinism/reuse.sh.stderr.exact +0 -0
  482. data/vendor/zstd/tests/cli-tests/determinism/reuse.sh.stdout.exact +19 -0
  483. data/vendor/zstd/tests/cli-tests/determinism/setup +5 -0
  484. data/vendor/zstd/tests/cli-tests/determinism/setup_once +30 -0
  485. data/vendor/zstd/tests/cli-tests/dict-builder/empty-input.sh +9 -0
  486. data/vendor/zstd/tests/cli-tests/dict-builder/empty-input.sh.stderr.exact +1 -0
  487. data/vendor/zstd/tests/cli-tests/dict-builder/no-inputs.sh +3 -0
  488. data/vendor/zstd/tests/cli-tests/dict-builder/no-inputs.sh.exit +1 -0
  489. data/vendor/zstd/tests/cli-tests/dict-builder/no-inputs.sh.stderr.exact +5 -0
  490. data/vendor/zstd/tests/cli-tests/dictionaries/dictionary-mismatch.sh +29 -0
  491. data/vendor/zstd/tests/cli-tests/dictionaries/dictionary-mismatch.sh.stderr.exact +7 -0
  492. data/vendor/zstd/tests/cli-tests/dictionaries/golden.sh +9 -0
  493. data/vendor/zstd/tests/cli-tests/dictionaries/setup +6 -0
  494. data/vendor/zstd/tests/cli-tests/dictionaries/setup_once +24 -0
  495. data/vendor/zstd/tests/cli-tests/file-handling/directory-mirror.sh +49 -0
  496. data/vendor/zstd/tests/cli-tests/file-handling/directory-mirror.sh.stderr.exact +0 -0
  497. data/vendor/zstd/tests/cli-tests/file-handling/directory-mirror.sh.stdout.exact +0 -0
  498. data/vendor/zstd/tests/cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh +12 -0
  499. data/vendor/zstd/tests/cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh.stderr.exact +30 -0
  500. data/vendor/zstd/tests/cli-tests/file-stat/compress-file-to-file.sh +9 -0
  501. data/vendor/zstd/tests/cli-tests/file-stat/compress-file-to-file.sh.stderr.glob +46 -0
  502. data/vendor/zstd/tests/cli-tests/file-stat/compress-file-to-stdout.sh +8 -0
  503. data/vendor/zstd/tests/cli-tests/file-stat/compress-file-to-stdout.sh.stderr.exact +24 -0
  504. data/vendor/zstd/tests/cli-tests/file-stat/compress-stdin-to-file.sh +8 -0
  505. data/vendor/zstd/tests/cli-tests/file-stat/compress-stdin-to-file.sh.stderr.glob +28 -0
  506. data/vendor/zstd/tests/cli-tests/file-stat/compress-stdin-to-stdout.sh +8 -0
  507. data/vendor/zstd/tests/cli-tests/file-stat/compress-stdin-to-stdout.sh.stderr.exact +18 -0
  508. data/vendor/zstd/tests/cli-tests/file-stat/decompress-file-to-file.sh +8 -0
  509. data/vendor/zstd/tests/cli-tests/file-stat/decompress-file-to-file.sh.stderr.glob +42 -0
  510. data/vendor/zstd/tests/cli-tests/file-stat/decompress-file-to-stdout.sh +7 -0
  511. data/vendor/zstd/tests/cli-tests/file-stat/decompress-file-to-stdout.sh.stderr.exact +18 -0
  512. data/vendor/zstd/tests/cli-tests/file-stat/decompress-stdin-to-file.sh +7 -0
  513. data/vendor/zstd/tests/cli-tests/file-stat/decompress-stdin-to-file.sh.stderr.glob +24 -0
  514. data/vendor/zstd/tests/cli-tests/file-stat/decompress-stdin-to-stdout.sh +7 -0
  515. data/vendor/zstd/tests/cli-tests/file-stat/decompress-stdin-to-stdout.sh.stderr.exact +14 -0
  516. data/vendor/zstd/tests/cli-tests/progress/no-progress.sh +46 -0
  517. data/vendor/zstd/tests/cli-tests/progress/no-progress.sh.stderr.glob +96 -0
  518. data/vendor/zstd/tests/cli-tests/progress/progress.sh +41 -0
  519. data/vendor/zstd/tests/cli-tests/progress/progress.sh.stderr.glob +62 -0
  520. data/vendor/zstd/tests/cli-tests/run.py +732 -0
  521. data/vendor/zstd/tests/cli-tests/zstd-symlinks/setup +6 -0
  522. data/vendor/zstd/tests/cli-tests/zstd-symlinks/zstdcat.sh +12 -0
  523. data/vendor/zstd/tests/cli-tests/zstd-symlinks/zstdcat.sh.stdout.exact +8 -0
  524. data/vendor/zstd/tests/datagencli.c +149 -0
  525. data/vendor/zstd/tests/decodecorpus.c +1998 -0
  526. data/vendor/zstd/tests/dict-files/zero-weight-dict +0 -0
  527. data/vendor/zstd/tests/external_matchfinder.c +140 -0
  528. data/vendor/zstd/tests/external_matchfinder.h +39 -0
  529. data/vendor/zstd/tests/fullbench.c +1210 -0
  530. data/vendor/zstd/tests/fuzz/Makefile +278 -0
  531. data/vendor/zstd/tests/fuzz/README.md +161 -0
  532. data/vendor/zstd/tests/fuzz/block_decompress.c +53 -0
  533. data/vendor/zstd/tests/fuzz/block_round_trip.c +103 -0
  534. data/vendor/zstd/tests/fuzz/decompress_cross_format.c +130 -0
  535. data/vendor/zstd/tests/fuzz/decompress_dstSize_tooSmall.c +74 -0
  536. data/vendor/zstd/tests/fuzz/dictionary_decompress.c +77 -0
  537. data/vendor/zstd/tests/fuzz/dictionary_loader.c +106 -0
  538. data/vendor/zstd/tests/fuzz/dictionary_round_trip.c +155 -0
  539. data/vendor/zstd/tests/fuzz/dictionary_stream_round_trip.c +209 -0
  540. data/vendor/zstd/tests/fuzz/fse_read_ncount.c +100 -0
  541. data/vendor/zstd/tests/fuzz/fuzz.h +57 -0
  542. data/vendor/zstd/tests/fuzz/fuzz.py +910 -0
  543. data/vendor/zstd/tests/fuzz/fuzz_data_producer.c +95 -0
  544. data/vendor/zstd/tests/fuzz/fuzz_data_producer.h +66 -0
  545. data/vendor/zstd/tests/fuzz/fuzz_helpers.c +47 -0
  546. data/vendor/zstd/tests/fuzz/fuzz_helpers.h +82 -0
  547. data/vendor/zstd/tests/fuzz/fuzz_third_party_seq_prod.h +116 -0
  548. data/vendor/zstd/tests/fuzz/generate_sequences.c +88 -0
  549. data/vendor/zstd/tests/fuzz/huf_decompress.c +68 -0
  550. data/vendor/zstd/tests/fuzz/huf_round_trip.c +137 -0
  551. data/vendor/zstd/tests/fuzz/raw_dictionary_round_trip.c +119 -0
  552. data/vendor/zstd/tests/fuzz/regression_driver.c +90 -0
  553. data/vendor/zstd/tests/fuzz/seekable_roundtrip.c +88 -0
  554. data/vendor/zstd/tests/fuzz/seq_prod_fuzz_example/Makefile +16 -0
  555. data/vendor/zstd/tests/fuzz/seq_prod_fuzz_example/README.md +12 -0
  556. data/vendor/zstd/tests/fuzz/seq_prod_fuzz_example/example_seq_prod.c +52 -0
  557. data/vendor/zstd/tests/fuzz/sequence_compression_api.c +452 -0
  558. data/vendor/zstd/tests/fuzz/simple_compress.c +60 -0
  559. data/vendor/zstd/tests/fuzz/simple_decompress.c +59 -0
  560. data/vendor/zstd/tests/fuzz/simple_round_trip.c +182 -0
  561. data/vendor/zstd/tests/fuzz/stream_decompress.c +119 -0
  562. data/vendor/zstd/tests/fuzz/stream_round_trip.c +218 -0
  563. data/vendor/zstd/tests/fuzz/zstd_frame_info.c +43 -0
  564. data/vendor/zstd/tests/fuzz/zstd_helpers.c +208 -0
  565. data/vendor/zstd/tests/fuzz/zstd_helpers.h +56 -0
  566. data/vendor/zstd/tests/fuzzer.c +5482 -0
  567. data/vendor/zstd/tests/golden-compression/PR-3517-block-splitter-corruption-test +1 -0
  568. data/vendor/zstd/tests/golden-compression/http +1 -0
  569. data/vendor/zstd/tests/golden-compression/huffman-compressed-larger +0 -0
  570. data/vendor/zstd/tests/golden-compression/large-literal-and-match-lengths +0 -0
  571. data/vendor/zstd/tests/golden-decompression/block-128k.zst +0 -0
  572. data/vendor/zstd/tests/golden-decompression/empty-block.zst +0 -0
  573. data/vendor/zstd/tests/golden-decompression/rle-first-block.zst +0 -0
  574. data/vendor/zstd/tests/golden-decompression/zeroSeq_2B.zst +0 -0
  575. data/vendor/zstd/tests/golden-decompression-errors/off0.bin.zst +0 -0
  576. data/vendor/zstd/tests/golden-decompression-errors/truncated_huff_state.zst +0 -0
  577. data/vendor/zstd/tests/golden-decompression-errors/zeroSeq_extraneous.zst +0 -0
  578. data/vendor/zstd/tests/golden-dictionaries/http-dict-missing-symbols +0 -0
  579. data/vendor/zstd/tests/gzip/Makefile +45 -0
  580. data/vendor/zstd/tests/gzip/gzip-env.sh +46 -0
  581. data/vendor/zstd/tests/gzip/helin-segv.sh +31 -0
  582. data/vendor/zstd/tests/gzip/help-version.sh +270 -0
  583. data/vendor/zstd/tests/gzip/hufts-segv.gz +0 -0
  584. data/vendor/zstd/tests/gzip/hufts.sh +34 -0
  585. data/vendor/zstd/tests/gzip/init.cfg +5 -0
  586. data/vendor/zstd/tests/gzip/init.sh +616 -0
  587. data/vendor/zstd/tests/gzip/keep.sh +51 -0
  588. data/vendor/zstd/tests/gzip/list.sh +31 -0
  589. data/vendor/zstd/tests/gzip/memcpy-abuse.sh +34 -0
  590. data/vendor/zstd/tests/gzip/mixed.sh +68 -0
  591. data/vendor/zstd/tests/gzip/null-suffix-clobber.sh +35 -0
  592. data/vendor/zstd/tests/gzip/stdin.sh +31 -0
  593. data/vendor/zstd/tests/gzip/test-driver.sh +150 -0
  594. data/vendor/zstd/tests/gzip/trailing-nul.sh +37 -0
  595. data/vendor/zstd/tests/gzip/unpack-invalid.sh +36 -0
  596. data/vendor/zstd/tests/gzip/z-suffix.sh +30 -0
  597. data/vendor/zstd/tests/gzip/zdiff.sh +48 -0
  598. data/vendor/zstd/tests/gzip/zgrep-context.sh +47 -0
  599. data/vendor/zstd/tests/gzip/zgrep-f.sh +43 -0
  600. data/vendor/zstd/tests/gzip/zgrep-signal.sh +64 -0
  601. data/vendor/zstd/tests/gzip/znew-k.sh +40 -0
  602. data/vendor/zstd/tests/invalidDictionaries.c +61 -0
  603. data/vendor/zstd/tests/largeDictionary.c +131 -0
  604. data/vendor/zstd/tests/legacy.c +262 -0
  605. data/vendor/zstd/tests/libzstd_builds.sh +104 -0
  606. data/vendor/zstd/tests/longmatch.c +123 -0
  607. data/vendor/zstd/tests/loremOut.c +50 -0
  608. data/vendor/zstd/tests/loremOut.h +15 -0
  609. data/vendor/zstd/tests/paramgrill.c +2965 -0
  610. data/vendor/zstd/tests/playTests.sh +1926 -0
  611. data/vendor/zstd/tests/poolTests.c +271 -0
  612. data/vendor/zstd/tests/rateLimiter.py +41 -0
  613. data/vendor/zstd/tests/regression/Makefile +60 -0
  614. data/vendor/zstd/tests/regression/README.md +28 -0
  615. data/vendor/zstd/tests/regression/config.c +404 -0
  616. data/vendor/zstd/tests/regression/config.h +91 -0
  617. data/vendor/zstd/tests/regression/data.c +631 -0
  618. data/vendor/zstd/tests/regression/data.h +121 -0
  619. data/vendor/zstd/tests/regression/levels.h +59 -0
  620. data/vendor/zstd/tests/regression/method.c +701 -0
  621. data/vendor/zstd/tests/regression/method.h +65 -0
  622. data/vendor/zstd/tests/regression/result.c +30 -0
  623. data/vendor/zstd/tests/regression/result.h +103 -0
  624. data/vendor/zstd/tests/regression/results.csv +1480 -0
  625. data/vendor/zstd/tests/regression/test.c +362 -0
  626. data/vendor/zstd/tests/roundTripCrash.c +241 -0
  627. data/vendor/zstd/tests/seqgen.c +260 -0
  628. data/vendor/zstd/tests/seqgen.h +58 -0
  629. data/vendor/zstd/tests/test-license.py +156 -0
  630. data/vendor/zstd/tests/test-variants.sh +115 -0
  631. data/vendor/zstd/tests/test-zstd-versions.py +308 -0
  632. data/vendor/zstd/tests/test_process_substitution.bash +92 -0
  633. data/vendor/zstd/tests/zstreamtest.c +3467 -0
  634. data/vendor/zstd/zlibWrapper/BUCK +22 -0
  635. data/vendor/zstd/zlibWrapper/Makefile +120 -0
  636. data/vendor/zstd/zlibWrapper/README.md +163 -0
  637. data/vendor/zstd/zlibWrapper/examples/example.c +598 -0
  638. data/vendor/zstd/zlibWrapper/examples/example_original.c +599 -0
  639. data/vendor/zstd/zlibWrapper/examples/fitblk.c +254 -0
  640. data/vendor/zstd/zlibWrapper/examples/fitblk_original.c +233 -0
  641. data/vendor/zstd/zlibWrapper/examples/minigzip.c +605 -0
  642. data/vendor/zstd/zlibWrapper/examples/zwrapbench.c +1018 -0
  643. data/vendor/zstd/zlibWrapper/gzclose.c +26 -0
  644. data/vendor/zstd/zlibWrapper/gzcompatibility.h +68 -0
  645. data/vendor/zstd/zlibWrapper/gzguts.h +229 -0
  646. data/vendor/zstd/zlibWrapper/gzlib.c +587 -0
  647. data/vendor/zstd/zlibWrapper/gzread.c +637 -0
  648. data/vendor/zstd/zlibWrapper/gzwrite.c +632 -0
  649. data/vendor/zstd/zlibWrapper/zstd_zlibwrapper.c +1200 -0
  650. data/vendor/zstd/zlibWrapper/zstd_zlibwrapper.h +91 -0
  651. metadata +738 -0
@@ -0,0 +1,3717 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
11
+
12
+ /* *************************************
13
+ * Compiler Options
14
+ ***************************************/
15
+ #ifdef _MSC_VER /* Visual */
16
+ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
17
+ # pragma warning(disable : 4204) /* non-constant aggregate initializer */
18
+ #endif
19
+ #if defined(__MINGW32__) && !defined(_POSIX_SOURCE)
20
+ # define _POSIX_SOURCE 1 /* disable %llu warnings with MinGW on Windows */
21
+ #endif
22
+
23
+ /*-*************************************
24
+ * Includes
25
+ ***************************************/
26
+ #include "platform.h" /* Large Files support, SET_BINARY_MODE */
27
+ #include "util.h" /* UTIL_getFileSize, UTIL_isRegularFile, UTIL_isSameFile */
28
+ #include <stdio.h> /* fprintf, open, fdopen, fread, _fileno, stdin, stdout */
29
+ #include <stdlib.h> /* malloc, free */
30
+ #include <string.h> /* strcmp, strlen */
31
+ #include <time.h> /* clock_t, to measure process time */
32
+ #include <fcntl.h> /* O_WRONLY */
33
+ #include <assert.h>
34
+ #include <errno.h> /* errno */
35
+ #include <limits.h> /* INT_MAX */
36
+ #include <signal.h>
37
+ #include "timefn.h" /* UTIL_getTime, UTIL_clockSpanMicro */
38
+
39
+ #if defined (_MSC_VER)
40
+ # include <sys/stat.h>
41
+ # include <io.h>
42
+ #endif
43
+
44
+ #include "fileio.h"
45
+ #include "fileio_asyncio.h"
46
+ #include "fileio_common.h"
47
+
48
+ FIO_display_prefs_t g_display_prefs = {2, FIO_ps_auto};
49
+ UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
50
+
51
+ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */
52
+ #include "../lib/zstd.h"
53
+ #include "../lib/zstd_errors.h" /* ZSTD_error_frameParameter_windowTooLarge */
54
+
55
+ #if defined(ZSTD_GZCOMPRESS) || defined(ZSTD_GZDECOMPRESS)
56
+ # include <zlib.h>
57
+ # if !defined(z_const)
58
+ # define z_const
59
+ # endif
60
+ #endif
61
+
62
+ #if defined(ZSTD_LZMACOMPRESS) || defined(ZSTD_LZMADECOMPRESS)
63
+ # include <lzma.h>
64
+ #endif
65
+
66
+ #define LZ4_MAGICNUMBER 0x184D2204
67
+ #if defined(ZSTD_LZ4COMPRESS) || defined(ZSTD_LZ4DECOMPRESS)
68
+ # define LZ4F_ENABLE_OBSOLETE_ENUMS
69
+ # include <lz4frame.h>
70
+ # include <lz4.h>
71
+ #endif
72
+
73
+ char const* FIO_zlibVersion(void)
74
+ {
75
+ #if defined(ZSTD_GZCOMPRESS) || defined(ZSTD_GZDECOMPRESS)
76
+ return zlibVersion();
77
+ #else
78
+ return "Unsupported";
79
+ #endif
80
+ }
81
+
82
+ char const* FIO_lz4Version(void)
83
+ {
84
+ #if defined(ZSTD_LZ4COMPRESS) || defined(ZSTD_LZ4DECOMPRESS)
85
+ /* LZ4_versionString() added in v1.7.3 */
86
+ # if LZ4_VERSION_NUMBER >= 10703
87
+ return LZ4_versionString();
88
+ # else
89
+ # define ZSTD_LZ4_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
90
+ # define ZSTD_LZ4_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LZ4_VERSION)
91
+ return ZSTD_LZ4_VERSION_STRING;
92
+ # endif
93
+ #else
94
+ return "Unsupported";
95
+ #endif
96
+ }
97
+
98
+ char const* FIO_lzmaVersion(void)
99
+ {
100
+ #if defined(ZSTD_LZMACOMPRESS) || defined(ZSTD_LZMADECOMPRESS)
101
+ return lzma_version_string();
102
+ #else
103
+ return "Unsupported";
104
+ #endif
105
+ }
106
+
107
+
108
+ /*-*************************************
109
+ * Constants
110
+ ***************************************/
111
+ #define ADAPT_WINDOWLOG_DEFAULT 23 /* 8 MB */
112
+ #define DICTSIZE_MAX (32 MB) /* protection against large input (attack scenario) */
113
+
114
+ #define FNSPACE 30
115
+
116
+ /* Default file permissions 0666 (modulated by umask) */
117
+ /* Temporary restricted file permissions are used when we're going to
118
+ * chmod/chown at the end of the operation. */
119
+ #if !defined(_WIN32)
120
+ /* These macros aren't defined on windows. */
121
+ #define DEFAULT_FILE_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
122
+ #define TEMPORARY_FILE_PERMISSIONS (S_IRUSR|S_IWUSR)
123
+ #else
124
+ #define DEFAULT_FILE_PERMISSIONS (0666)
125
+ #define TEMPORARY_FILE_PERMISSIONS (0600)
126
+ #endif
127
+
128
+
129
+ #ifndef ZSTD_NOCOMPRESS
130
+
131
+ /* *************************************
132
+ * Synchronous compression IO helpers
133
+ * Lightweight wrapper used by compression paths to manage buffered
134
+ * reads/writes without the async job machinery.
135
+ ***************************************/
136
+ typedef struct {
137
+ const FIO_prefs_t* prefs;
138
+ FILE* srcFile;
139
+ FILE* dstFile;
140
+ unsigned storedSkips;
141
+ U8* inBuffer;
142
+ size_t inCapacity;
143
+ U8* srcBuffer;
144
+ size_t srcBufferLoaded;
145
+ U8* outBuffer;
146
+ size_t outCapacity;
147
+ } FIO_SyncCompressIO;
148
+
149
+ static void FIO_SyncCompressIO_init(FIO_SyncCompressIO* io,
150
+ const FIO_prefs_t* prefs,
151
+ size_t inCapacity,
152
+ size_t outCapacity);
153
+ static void FIO_SyncCompressIO_destroy(FIO_SyncCompressIO* io);
154
+ static void FIO_SyncCompressIO_setSrc(FIO_SyncCompressIO* io, FILE* file);
155
+ static void FIO_SyncCompressIO_clearSrc(FIO_SyncCompressIO* io);
156
+ static void FIO_SyncCompressIO_setDst(FIO_SyncCompressIO* io, FILE* file);
157
+ static int FIO_SyncCompressIO_closeDst(FIO_SyncCompressIO* io);
158
+ static size_t FIO_SyncCompressIO_fillBuffer(FIO_SyncCompressIO* io, size_t minToHave);
159
+ static void FIO_SyncCompressIO_consumeBytes(FIO_SyncCompressIO* io, size_t n);
160
+ static void FIO_SyncCompressIO_commitOut(FIO_SyncCompressIO* io, const void* buffer, size_t size);
161
+ static void FIO_SyncCompressIO_finish(FIO_SyncCompressIO* io);
162
+
163
+
164
+ static unsigned FIO_sparseWrite(FILE* file,
165
+ const void* buffer, size_t bufferSize,
166
+ const FIO_prefs_t* const prefs,
167
+ unsigned storedSkips)
168
+ {
169
+ const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */
170
+ size_t bufferSizeT = bufferSize / sizeof(size_t);
171
+ const size_t* const bufferTEnd = bufferT + bufferSizeT;
172
+ const size_t* ptrT = bufferT;
173
+ static const size_t segmentSizeT = (32 KB) / sizeof(size_t); /* check every 32 KB */
174
+
175
+ if (prefs->testMode) return 0; /* do not output anything in test mode */
176
+
177
+ if (!prefs->sparseFileSupport) { /* normal write */
178
+ size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file);
179
+ if (sizeCheck != bufferSize)
180
+ EXM_THROW(70, "Write error : cannot write block : %s",
181
+ strerror(errno));
182
+ return 0;
183
+ }
184
+
185
+ /* avoid int overflow */
186
+ if (storedSkips > 1 GB) {
187
+ if (LONG_SEEK(file, 1 GB, SEEK_CUR) != 0)
188
+ EXM_THROW(91, "1 GB skip error (sparse file support)");
189
+ storedSkips -= 1 GB;
190
+ }
191
+
192
+ while (ptrT < bufferTEnd) {
193
+ size_t nb0T;
194
+
195
+ /* adjust last segment if < 32 KB */
196
+ size_t seg0SizeT = segmentSizeT;
197
+ if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT;
198
+ bufferSizeT -= seg0SizeT;
199
+
200
+ /* count leading zeroes */
201
+ for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ;
202
+ storedSkips += (unsigned)(nb0T * sizeof(size_t));
203
+
204
+ if (nb0T != seg0SizeT) { /* not all 0s */
205
+ size_t const nbNon0ST = seg0SizeT - nb0T;
206
+ /* skip leading zeros */
207
+ if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0)
208
+ EXM_THROW(92, "Sparse skip error ; try --no-sparse");
209
+ storedSkips = 0;
210
+ /* write the rest */
211
+ if (fwrite(ptrT + nb0T, sizeof(size_t), nbNon0ST, file) != nbNon0ST)
212
+ EXM_THROW(93, "Write error : cannot write block : %s",
213
+ strerror(errno));
214
+ }
215
+ ptrT += seg0SizeT;
216
+ }
217
+
218
+ { static size_t const maskT = sizeof(size_t)-1;
219
+ if (bufferSize & maskT) {
220
+ /* size not multiple of sizeof(size_t) : implies end of block */
221
+ const char* const restStart = (const char*)bufferTEnd;
222
+ const char* restPtr = restStart;
223
+ const char* const restEnd = (const char*)buffer + bufferSize;
224
+ assert(restEnd > restStart && restEnd < restStart + sizeof(size_t));
225
+ for ( ; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ;
226
+ storedSkips += (unsigned) (restPtr - restStart);
227
+ if (restPtr != restEnd) {
228
+ /* not all remaining bytes are 0 */
229
+ size_t const restSize = (size_t)(restEnd - restPtr);
230
+ if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0)
231
+ EXM_THROW(92, "Sparse skip error ; try --no-sparse");
232
+ if (fwrite(restPtr, 1, restSize, file) != restSize)
233
+ EXM_THROW(95, "Write error : cannot write end of decoded block : %s",
234
+ strerror(errno));
235
+ storedSkips = 0;
236
+ } } }
237
+
238
+ return storedSkips;
239
+ }
240
+
241
+ static void FIO_sparseWriteEnd(const FIO_prefs_t* const prefs, FILE* file, unsigned storedSkips)
242
+ {
243
+ if (file == NULL) return;
244
+ if (prefs->testMode) {
245
+ assert(storedSkips == 0);
246
+ return;
247
+ }
248
+ if (storedSkips>0) {
249
+ assert(prefs->sparseFileSupport > 0); /* storedSkips>0 implies sparse support is enabled */
250
+ if (LONG_SEEK(file, storedSkips-1, SEEK_CUR) != 0)
251
+ EXM_THROW(69, "Final skip error (sparse file support)");
252
+ /* last zero must be explicitly written,
253
+ * so that skipped ones get implicitly translated as zero by FS */
254
+ { const char lastZeroByte[1] = { 0 };
255
+ if (fwrite(lastZeroByte, 1, 1, file) != 1)
256
+ EXM_THROW(69, "Write error : cannot write last zero : %s", strerror(errno));
257
+ }
258
+ }
259
+ }
260
+
261
+ static void FIO_SyncCompressIO_init(FIO_SyncCompressIO* io,
262
+ const FIO_prefs_t* prefs,
263
+ size_t inCapacity,
264
+ size_t outCapacity)
265
+ {
266
+ memset(io, 0, sizeof(*io));
267
+ io->prefs = prefs;
268
+ io->inCapacity = inCapacity;
269
+ io->outCapacity = outCapacity;
270
+ io->inBuffer = (U8*)malloc(inCapacity);
271
+ if (!io->inBuffer)
272
+ EXM_THROW(101, "Allocation error : not enough memory");
273
+ io->outBuffer = (U8*)malloc(outCapacity);
274
+ if (!io->outBuffer) {
275
+ free(io->inBuffer);
276
+ io->inBuffer = NULL;
277
+ EXM_THROW(101, "Allocation error : not enough memory");
278
+ }
279
+ io->srcBuffer = io->inBuffer;
280
+ io->srcBufferLoaded = 0;
281
+ }
282
+
283
+ static void FIO_SyncCompressIO_destroy(FIO_SyncCompressIO* io)
284
+ {
285
+ if (!io) return;
286
+ free(io->inBuffer);
287
+ free(io->outBuffer);
288
+ io->inBuffer = NULL;
289
+ io->outBuffer = NULL;
290
+ io->srcBuffer = NULL;
291
+ io->srcBufferLoaded = 0;
292
+ io->srcFile = NULL;
293
+ io->dstFile = NULL;
294
+ io->storedSkips = 0;
295
+ }
296
+
297
+ static void FIO_SyncCompressIO_setSrc(FIO_SyncCompressIO* io, FILE* file)
298
+ {
299
+ io->srcFile = file;
300
+ io->srcBuffer = io->inBuffer;
301
+ io->srcBufferLoaded = 0;
302
+ }
303
+
304
+ static void FIO_SyncCompressIO_clearSrc(FIO_SyncCompressIO* io)
305
+ {
306
+ io->srcFile = NULL;
307
+ io->srcBuffer = io->inBuffer;
308
+ io->srcBufferLoaded = 0;
309
+ }
310
+
311
+ static void FIO_SyncCompressIO_setDst(FIO_SyncCompressIO* io, FILE* file)
312
+ {
313
+ io->dstFile = file;
314
+ io->storedSkips = 0;
315
+ }
316
+
317
+ static int FIO_SyncCompressIO_closeDst(FIO_SyncCompressIO* io)
318
+ {
319
+ int result = 0;
320
+ if (io->dstFile != NULL) {
321
+ FIO_SyncCompressIO_finish(io);
322
+ result = fclose(io->dstFile);
323
+ io->dstFile = NULL;
324
+ }
325
+ return result;
326
+ }
327
+
328
+ static size_t FIO_SyncCompressIO_fillBuffer(FIO_SyncCompressIO* io, size_t minToHave)
329
+ {
330
+ size_t added = 0;
331
+ if (io->srcFile == NULL)
332
+ return 0;
333
+
334
+ if (minToHave > io->inCapacity)
335
+ minToHave = io->inCapacity;
336
+
337
+ if (io->srcBufferLoaded >= minToHave)
338
+ return 0;
339
+
340
+ if (io->srcBuffer != io->inBuffer) {
341
+ if (io->srcBufferLoaded > 0)
342
+ memmove(io->inBuffer, io->srcBuffer, io->srcBufferLoaded);
343
+ io->srcBuffer = io->inBuffer;
344
+ }
345
+
346
+ while (io->srcBufferLoaded < minToHave) {
347
+ size_t const toRead = io->inCapacity - io->srcBufferLoaded;
348
+ size_t const readBytes = fread(io->inBuffer + io->srcBufferLoaded, 1, toRead, io->srcFile);
349
+ if (readBytes == 0) {
350
+ if (ferror(io->srcFile))
351
+ EXM_THROW(37, "Read error");
352
+ break; /* EOF */
353
+ }
354
+ io->srcBufferLoaded += readBytes;
355
+ added += readBytes;
356
+ if (readBytes < toRead)
357
+ break;
358
+ }
359
+
360
+ return added;
361
+ }
362
+
363
+ static void FIO_SyncCompressIO_consumeBytes(FIO_SyncCompressIO* io, size_t n)
364
+ {
365
+ assert(n <= io->srcBufferLoaded);
366
+ io->srcBuffer += n;
367
+ io->srcBufferLoaded -= n;
368
+ if (io->srcBufferLoaded == 0)
369
+ io->srcBuffer = io->inBuffer;
370
+ }
371
+
372
+ static void FIO_SyncCompressIO_commitOut(FIO_SyncCompressIO* io, const void* buffer, size_t size)
373
+ {
374
+ if (size == 0)
375
+ return;
376
+ if (io->dstFile == NULL) {
377
+ assert(io->prefs->testMode);
378
+ return;
379
+ }
380
+ io->storedSkips = FIO_sparseWrite(io->dstFile, buffer, size, io->prefs, io->storedSkips);
381
+ }
382
+
383
+ static void FIO_SyncCompressIO_finish(FIO_SyncCompressIO* io)
384
+ {
385
+ if (io->dstFile == NULL)
386
+ return;
387
+ FIO_sparseWriteEnd(io->prefs, io->dstFile, io->storedSkips);
388
+ io->storedSkips = 0;
389
+ }
390
+
391
+ #endif /* ZSTD_NOCOMPRESS */
392
+
393
+ /*-************************************
394
+ * Signal (Ctrl-C trapping)
395
+ **************************************/
396
+ static const char* g_artefact = NULL;
397
+ static void INThandler(int sig)
398
+ {
399
+ assert(sig==SIGINT); (void)sig;
400
+ #if !defined(_MSC_VER)
401
+ signal(sig, SIG_IGN); /* this invocation generates a buggy warning in Visual Studio */
402
+ #endif
403
+ if (g_artefact) {
404
+ assert(UTIL_isRegularFile(g_artefact));
405
+ remove(g_artefact);
406
+ }
407
+ DISPLAY("\n");
408
+ exit(2);
409
+ }
410
+ static void addHandler(char const* dstFileName)
411
+ {
412
+ if (UTIL_isRegularFile(dstFileName)) {
413
+ g_artefact = dstFileName;
414
+ signal(SIGINT, INThandler);
415
+ } else {
416
+ g_artefact = NULL;
417
+ }
418
+ }
419
+ /* Idempotent */
420
+ static void clearHandler(void)
421
+ {
422
+ if (g_artefact) signal(SIGINT, SIG_DFL);
423
+ g_artefact = NULL;
424
+ }
425
+
426
+
427
+ /*-*********************************************************
428
+ * Termination signal trapping (Print debug stack trace)
429
+ ***********************************************************/
430
+ #if defined(__has_feature) && !defined(BACKTRACE_ENABLE) /* Clang compiler */
431
+ # if (__has_feature(address_sanitizer))
432
+ # define BACKTRACE_ENABLE 0
433
+ # endif /* __has_feature(address_sanitizer) */
434
+ #elif defined(__SANITIZE_ADDRESS__) && !defined(BACKTRACE_ENABLE) /* GCC compiler */
435
+ # define BACKTRACE_ENABLE 0
436
+ #endif
437
+
438
+ #if !defined(BACKTRACE_ENABLE)
439
+ /* automatic detector : backtrace enabled by default on linux+glibc and osx */
440
+ # if (defined(__linux__) && (defined(__GLIBC__) && !defined(__UCLIBC__))) \
441
+ || (defined(__APPLE__) && defined(__MACH__))
442
+ # define BACKTRACE_ENABLE 1
443
+ # else
444
+ # define BACKTRACE_ENABLE 0
445
+ # endif
446
+ #endif
447
+
448
+ /* note : after this point, BACKTRACE_ENABLE is necessarily defined */
449
+
450
+
451
+ #if BACKTRACE_ENABLE
452
+
453
+ #include <execinfo.h> /* backtrace, backtrace_symbols */
454
+
455
+ #define MAX_STACK_FRAMES 50
456
+
457
+ static void ABRThandler(int sig) {
458
+ const char* name;
459
+ void* addrlist[MAX_STACK_FRAMES];
460
+ char** symbollist;
461
+ int addrlen, i;
462
+
463
+ switch (sig) {
464
+ case SIGABRT: name = "SIGABRT"; break;
465
+ case SIGFPE: name = "SIGFPE"; break;
466
+ case SIGILL: name = "SIGILL"; break;
467
+ case SIGINT: name = "SIGINT"; break;
468
+ case SIGSEGV: name = "SIGSEGV"; break;
469
+ default: name = "UNKNOWN";
470
+ }
471
+
472
+ DISPLAY("Caught %s signal, printing stack:\n", name);
473
+ /* Retrieve current stack addresses. */
474
+ addrlen = backtrace(addrlist, MAX_STACK_FRAMES);
475
+ if (addrlen == 0) {
476
+ DISPLAY("\n");
477
+ return;
478
+ }
479
+ /* Create readable strings to each frame. */
480
+ symbollist = backtrace_symbols(addrlist, addrlen);
481
+ /* Print the stack trace, excluding calls handling the signal. */
482
+ for (i = ZSTD_START_SYMBOLLIST_FRAME; i < addrlen; i++) {
483
+ DISPLAY("%s\n", symbollist[i]);
484
+ }
485
+ free(symbollist);
486
+ /* Reset and raise the signal so default handler runs. */
487
+ signal(sig, SIG_DFL);
488
+ raise(sig);
489
+ }
490
+ #endif
491
+
492
+ void FIO_addAbortHandler(void)
493
+ {
494
+ #if BACKTRACE_ENABLE
495
+ signal(SIGABRT, ABRThandler);
496
+ signal(SIGFPE, ABRThandler);
497
+ signal(SIGILL, ABRThandler);
498
+ signal(SIGSEGV, ABRThandler);
499
+ signal(SIGBUS, ABRThandler);
500
+ #endif
501
+ }
502
+
503
+ /*-*************************************
504
+ * Parameters: FIO_ctx_t
505
+ ***************************************/
506
+
507
+ /* typedef'd to FIO_ctx_t within fileio.h */
508
+ struct FIO_ctx_s {
509
+
510
+ /* file i/o info */
511
+ int nbFilesTotal;
512
+ int hasStdinInput;
513
+ int hasStdoutOutput;
514
+
515
+ /* file i/o state */
516
+ int currFileIdx;
517
+ int nbFilesProcessed;
518
+ size_t totalBytesInput;
519
+ size_t totalBytesOutput;
520
+ };
521
+
522
+ static int FIO_shouldDisplayFileSummary(FIO_ctx_t const* fCtx)
523
+ {
524
+ return fCtx->nbFilesTotal <= 1 || g_display_prefs.displayLevel >= 3;
525
+ }
526
+
527
+ static int FIO_shouldDisplayMultipleFileSummary(FIO_ctx_t const* fCtx)
528
+ {
529
+ int const shouldDisplay = (fCtx->nbFilesProcessed >= 1 && fCtx->nbFilesTotal > 1);
530
+ assert(shouldDisplay || FIO_shouldDisplayFileSummary(fCtx) || fCtx->nbFilesProcessed == 0);
531
+ return shouldDisplay;
532
+ }
533
+
534
+
535
+ /*-*************************************
536
+ * Parameters: Initialization
537
+ ***************************************/
538
+
539
+ #define FIO_OVERLAP_LOG_NOTSET 9999
540
+ #define FIO_LDM_PARAM_NOTSET 9999
541
+
542
+
543
+ FIO_prefs_t* FIO_createPreferences(void)
544
+ {
545
+ FIO_prefs_t* const ret = (FIO_prefs_t*)malloc(sizeof(FIO_prefs_t));
546
+ if (!ret) EXM_THROW(21, "Allocation error : not enough memory");
547
+
548
+ ret->compressionType = FIO_zstdCompression;
549
+ ret->overwrite = 0;
550
+ ret->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
551
+ ret->dictIDFlag = 1;
552
+ ret->checksumFlag = 1;
553
+ ret->removeSrcFile = 0;
554
+ ret->memLimit = 0;
555
+ ret->nbWorkers = 1;
556
+ ret->jobSize = 0;
557
+ ret->overlapLog = FIO_OVERLAP_LOG_NOTSET;
558
+ ret->adaptiveMode = 0;
559
+ ret->rsyncable = 0;
560
+ ret->minAdaptLevel = -50; /* initializing this value requires a constant, so ZSTD_minCLevel() doesn't work */
561
+ ret->maxAdaptLevel = 22; /* initializing this value requires a constant, so ZSTD_maxCLevel() doesn't work */
562
+ ret->ldmFlag = 0;
563
+ ret->ldmHashLog = 0;
564
+ ret->ldmMinMatch = 0;
565
+ ret->ldmBucketSizeLog = FIO_LDM_PARAM_NOTSET;
566
+ ret->ldmHashRateLog = FIO_LDM_PARAM_NOTSET;
567
+ ret->streamSrcSize = 0;
568
+ ret->targetCBlockSize = 0;
569
+ ret->srcSizeHint = 0;
570
+ ret->testMode = 0;
571
+ ret->literalCompressionMode = ZSTD_ps_auto;
572
+ ret->excludeCompressedFiles = 0;
573
+ ret->allowBlockDevices = 0;
574
+ ret->asyncIO = AIO_supported();
575
+ ret->passThrough = -1;
576
+ return ret;
577
+ }
578
+
579
+ FIO_ctx_t* FIO_createContext(void)
580
+ {
581
+ FIO_ctx_t* const ret = (FIO_ctx_t*)malloc(sizeof(FIO_ctx_t));
582
+ if (!ret) EXM_THROW(21, "Allocation error : not enough memory");
583
+
584
+ ret->currFileIdx = 0;
585
+ ret->hasStdinInput = 0;
586
+ ret->hasStdoutOutput = 0;
587
+ ret->nbFilesTotal = 1;
588
+ ret->nbFilesProcessed = 0;
589
+ ret->totalBytesInput = 0;
590
+ ret->totalBytesOutput = 0;
591
+ return ret;
592
+ }
593
+
594
+ void FIO_freePreferences(FIO_prefs_t* const prefs)
595
+ {
596
+ free(prefs);
597
+ }
598
+
599
+ void FIO_freeContext(FIO_ctx_t* const fCtx)
600
+ {
601
+ free(fCtx);
602
+ }
603
+
604
+
605
+ /*-*************************************
606
+ * Parameters: Display Options
607
+ ***************************************/
608
+
609
+ void FIO_setNotificationLevel(int level) { g_display_prefs.displayLevel=level; }
610
+
611
+ void FIO_setProgressSetting(FIO_progressSetting_e setting) { g_display_prefs.progressSetting = setting; }
612
+
613
+
614
+ /*-*************************************
615
+ * Parameters: Setters
616
+ ***************************************/
617
+
618
+ /* FIO_prefs_t functions */
619
+
620
+ void FIO_setCompressionType(FIO_prefs_t* const prefs, FIO_compressionType_t compressionType) { prefs->compressionType = compressionType; }
621
+
622
+ void FIO_overwriteMode(FIO_prefs_t* const prefs) { prefs->overwrite = 1; }
623
+
624
+ void FIO_setSparseWrite(FIO_prefs_t* const prefs, int sparse) { prefs->sparseFileSupport = sparse; }
625
+
626
+ void FIO_setDictIDFlag(FIO_prefs_t* const prefs, int dictIDFlag) { prefs->dictIDFlag = dictIDFlag; }
627
+
628
+ void FIO_setChecksumFlag(FIO_prefs_t* const prefs, int checksumFlag) { prefs->checksumFlag = checksumFlag; }
629
+
630
+ void FIO_setRemoveSrcFile(FIO_prefs_t* const prefs, int flag) { prefs->removeSrcFile = (flag!=0); }
631
+
632
+ void FIO_setMemLimit(FIO_prefs_t* const prefs, unsigned memLimit) { prefs->memLimit = memLimit; }
633
+
634
+ void FIO_setNbWorkers(FIO_prefs_t* const prefs, int nbWorkers) {
635
+ #ifndef ZSTD_MULTITHREAD
636
+ if (nbWorkers > 0) DISPLAYLEVEL(2, "Note : multi-threading is disabled \n");
637
+ #endif
638
+ prefs->nbWorkers = nbWorkers;
639
+ }
640
+
641
+ void FIO_setExcludeCompressedFile(FIO_prefs_t* const prefs, int excludeCompressedFiles) { prefs->excludeCompressedFiles = excludeCompressedFiles; }
642
+
643
+ void FIO_setAllowBlockDevices(FIO_prefs_t* const prefs, int allowBlockDevices) { prefs->allowBlockDevices = allowBlockDevices; }
644
+
645
+ void FIO_setJobSize(FIO_prefs_t* const prefs, int jobSize) {
646
+ if (jobSize && prefs->nbWorkers==0)
647
+ DISPLAYLEVEL(2, "Setting block size is useless in single-thread mode \n");
648
+ prefs->jobSize = jobSize;
649
+ }
650
+
651
+ void FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog){
652
+ if (overlapLog && prefs->nbWorkers==0)
653
+ DISPLAYLEVEL(2, "Setting overlapLog is useless in single-thread mode \n");
654
+ prefs->overlapLog = overlapLog;
655
+ }
656
+
657
+ void FIO_setAdaptiveMode(FIO_prefs_t* const prefs, int adapt) {
658
+ if ((adapt>0) && (prefs->nbWorkers==0))
659
+ EXM_THROW(1, "Adaptive mode is not compatible with single thread mode \n");
660
+ prefs->adaptiveMode = adapt;
661
+ }
662
+
663
+ void FIO_setUseRowMatchFinder(FIO_prefs_t* const prefs, int useRowMatchFinder) {
664
+ prefs->useRowMatchFinder = useRowMatchFinder;
665
+ }
666
+
667
+ void FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable) {
668
+ if ((rsyncable>0) && (prefs->nbWorkers==0))
669
+ EXM_THROW(1, "Rsyncable mode is not compatible with single thread mode \n");
670
+ prefs->rsyncable = rsyncable;
671
+ }
672
+
673
+ void FIO_setStreamSrcSize(FIO_prefs_t* const prefs, size_t streamSrcSize) {
674
+ prefs->streamSrcSize = streamSrcSize;
675
+ }
676
+
677
+ void FIO_setTargetCBlockSize(FIO_prefs_t* const prefs, size_t targetCBlockSize) {
678
+ prefs->targetCBlockSize = targetCBlockSize;
679
+ }
680
+
681
+ void FIO_setSrcSizeHint(FIO_prefs_t* const prefs, size_t srcSizeHint) {
682
+ prefs->srcSizeHint = (int)MIN((size_t)INT_MAX, srcSizeHint);
683
+ }
684
+
685
+ void FIO_setTestMode(FIO_prefs_t* const prefs, int testMode) {
686
+ prefs->testMode = (testMode!=0);
687
+ }
688
+
689
+ void FIO_setLiteralCompressionMode(
690
+ FIO_prefs_t* const prefs,
691
+ ZSTD_ParamSwitch_e mode) {
692
+ prefs->literalCompressionMode = mode;
693
+ }
694
+
695
+ void FIO_setAdaptMin(FIO_prefs_t* const prefs, int minCLevel)
696
+ {
697
+ #ifndef ZSTD_NOCOMPRESS
698
+ assert(minCLevel >= ZSTD_minCLevel());
699
+ #endif
700
+ prefs->minAdaptLevel = minCLevel;
701
+ }
702
+
703
+ void FIO_setAdaptMax(FIO_prefs_t* const prefs, int maxCLevel)
704
+ {
705
+ prefs->maxAdaptLevel = maxCLevel;
706
+ }
707
+
708
+ void FIO_setLdmFlag(FIO_prefs_t* const prefs, unsigned ldmFlag) {
709
+ prefs->ldmFlag = (ldmFlag>0);
710
+ }
711
+
712
+ void FIO_setLdmHashLog(FIO_prefs_t* const prefs, int ldmHashLog) {
713
+ prefs->ldmHashLog = ldmHashLog;
714
+ }
715
+
716
+ void FIO_setLdmMinMatch(FIO_prefs_t* const prefs, int ldmMinMatch) {
717
+ prefs->ldmMinMatch = ldmMinMatch;
718
+ }
719
+
720
+ void FIO_setLdmBucketSizeLog(FIO_prefs_t* const prefs, int ldmBucketSizeLog) {
721
+ prefs->ldmBucketSizeLog = ldmBucketSizeLog;
722
+ }
723
+
724
+
725
+ void FIO_setLdmHashRateLog(FIO_prefs_t* const prefs, int ldmHashRateLog) {
726
+ prefs->ldmHashRateLog = ldmHashRateLog;
727
+ }
728
+
729
+ void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value)
730
+ {
731
+ prefs->patchFromMode = value != 0;
732
+ }
733
+
734
+ void FIO_setContentSize(FIO_prefs_t* const prefs, int value)
735
+ {
736
+ prefs->contentSize = value != 0;
737
+ }
738
+
739
+ void FIO_setAsyncIOFlag(FIO_prefs_t* const prefs, int value) {
740
+ #ifdef ZSTD_MULTITHREAD
741
+ prefs->asyncIO = value;
742
+ #else
743
+ (void) prefs;
744
+ (void) value;
745
+ DISPLAYLEVEL(2, "Note : asyncio is disabled (lack of multithreading support) \n");
746
+ #endif
747
+ }
748
+
749
+ void FIO_setPassThroughFlag(FIO_prefs_t* const prefs, int value) {
750
+ prefs->passThrough = (value != 0);
751
+ }
752
+
753
+ void FIO_setMMapDict(FIO_prefs_t* const prefs, ZSTD_ParamSwitch_e value)
754
+ {
755
+ prefs->mmapDict = value;
756
+ }
757
+
758
+ /* FIO_ctx_t functions */
759
+
760
+ void FIO_setHasStdoutOutput(FIO_ctx_t* const fCtx, int value) {
761
+ fCtx->hasStdoutOutput = value;
762
+ }
763
+
764
+ void FIO_setNbFilesTotal(FIO_ctx_t* const fCtx, int value)
765
+ {
766
+ fCtx->nbFilesTotal = value;
767
+ }
768
+
769
+ void FIO_determineHasStdinInput(FIO_ctx_t* const fCtx, const FileNamesTable* const filenames) {
770
+ size_t i = 0;
771
+ for ( ; i < filenames->tableSize; ++i) {
772
+ if (!strcmp(stdinmark, filenames->fileNames[i])) {
773
+ fCtx->hasStdinInput = 1;
774
+ return;
775
+ }
776
+ }
777
+ }
778
+
779
+ /*-*************************************
780
+ * Functions
781
+ ***************************************/
782
+ /** FIO_removeFile() :
783
+ * @result : Unlink `fileName`, even if it's read-only */
784
+ static int FIO_removeFile(const char* path)
785
+ {
786
+ stat_t statbuf;
787
+ if (!UTIL_stat(path, &statbuf)) {
788
+ DISPLAYLEVEL(2, "zstd: Failed to stat %s while trying to remove it\n", path);
789
+ return 0;
790
+ }
791
+ if (!UTIL_isRegularFileStat(&statbuf)) {
792
+ DISPLAYLEVEL(2, "zstd: Refusing to remove non-regular file %s\n", path);
793
+ return 0;
794
+ }
795
+ #if defined(_WIN32)
796
+ /* windows doesn't allow remove read-only files,
797
+ * so try to make it writable first */
798
+ if (!(statbuf.st_mode & _S_IWRITE)) {
799
+ UTIL_chmod(path, &statbuf, _S_IWRITE);
800
+ }
801
+ #endif
802
+ return remove(path);
803
+ }
804
+
805
+ /** FIO_openSrcFile() :
806
+ * condition : `srcFileName` must be non-NULL.
807
+ * optional: `prefs` may be NULL.
808
+ * @result : FILE* to `srcFileName`, or NULL if it fails */
809
+ static FILE* FIO_openSrcFile(const FIO_prefs_t* const prefs, const char* srcFileName, stat_t* statbuf)
810
+ {
811
+ int allowBlockDevices = prefs != NULL ? prefs->allowBlockDevices : 0;
812
+ assert(srcFileName != NULL);
813
+ assert(statbuf != NULL);
814
+
815
+ if (!strcmp(srcFileName, stdinmark)) {
816
+ DISPLAYLEVEL(4,"Using stdin for input \n");
817
+ SET_BINARY_MODE(stdin);
818
+ return stdin;
819
+ }
820
+
821
+ if (!UTIL_stat(srcFileName, statbuf)) {
822
+ DISPLAYLEVEL(1, "zstd: can't stat %s : %s -- ignored \n",
823
+ srcFileName, strerror(errno));
824
+ return NULL;
825
+ }
826
+
827
+ /* Accept regular files, FIFOs, and process substitution file descriptors */
828
+ if (!UTIL_isRegularFileStat(statbuf)
829
+ && !UTIL_isFIFOStat(statbuf)
830
+ && !UTIL_isFileDescriptorPipe(srcFileName) /* Process substitution support */
831
+ && !(allowBlockDevices && UTIL_isBlockDevStat(statbuf))
832
+ ) {
833
+ DISPLAYLEVEL(1, "zstd: %s is not a regular file -- ignored \n",
834
+ srcFileName);
835
+ return NULL;
836
+ }
837
+
838
+ { FILE* const f = fopen(srcFileName, "rb");
839
+ if (f == NULL)
840
+ DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno));
841
+ return f;
842
+ }
843
+ }
844
+
845
+ /** FIO_openDstFile() :
846
+ * condition : `dstFileName` must be non-NULL.
847
+ * @result : FILE* to `dstFileName`, or NULL if it fails */
848
+ static FILE*
849
+ FIO_openDstFile(FIO_ctx_t* fCtx, FIO_prefs_t* const prefs,
850
+ const char* srcFileName, const char* dstFileName,
851
+ const int mode)
852
+ {
853
+ if (prefs->testMode) return NULL; /* do not open file in test mode */
854
+
855
+ assert(dstFileName != NULL);
856
+ if (!strcmp (dstFileName, stdoutmark)) {
857
+ DISPLAYLEVEL(4,"Using stdout for output \n");
858
+ SET_BINARY_MODE(stdout);
859
+ if (prefs->sparseFileSupport == 1) {
860
+ prefs->sparseFileSupport = 0;
861
+ DISPLAYLEVEL(4, "Sparse File Support is automatically disabled on stdout ; try --sparse \n");
862
+ }
863
+ return stdout;
864
+ }
865
+
866
+ /* ensure dst is not the same as src */
867
+ if (srcFileName != NULL && UTIL_isSameFile(srcFileName, dstFileName)) {
868
+ DISPLAYLEVEL(1, "zstd: Refusing to open an output file which will overwrite the input file \n");
869
+ return NULL;
870
+ }
871
+
872
+ if (UTIL_isRegularFile(dstFileName)) {
873
+ /* Check if destination file already exists */
874
+ #if !defined(_WIN32)
875
+ /* this test does not work on Windows :
876
+ * `NUL` and `nul` are detected as regular files */
877
+ if (!strcmp(dstFileName, nulmark)) {
878
+ EXM_THROW(40, "%s is unexpectedly categorized as a regular file",
879
+ dstFileName);
880
+ }
881
+ #endif
882
+ if (!prefs->overwrite) {
883
+ if (g_display_prefs.displayLevel <= 1) {
884
+ /* No interaction possible */
885
+ DISPLAYLEVEL(1, "zstd: %s already exists; not overwritten \n",
886
+ dstFileName);
887
+ return NULL;
888
+ }
889
+ DISPLAY("zstd: %s already exists; ", dstFileName);
890
+ if (UTIL_requireUserConfirmation("overwrite (y/n) ? ", "Not overwritten \n", "yY", fCtx->hasStdinInput))
891
+ return NULL;
892
+ }
893
+ /* need to unlink */
894
+ FIO_removeFile(dstFileName);
895
+ }
896
+
897
+ {
898
+ int isDstRegFile;
899
+ #if defined(_WIN32)
900
+ /* Windows requires opening the file as a "binary" file to avoid
901
+ * mangling. This macro doesn't exist on unix. */
902
+ const int openflags = O_WRONLY|O_CREAT|O_TRUNC|O_BINARY;
903
+ const int fd = _open(dstFileName, openflags, mode);
904
+ FILE* f = NULL;
905
+ if (fd != -1) {
906
+ f = _fdopen(fd, "wb");
907
+ }
908
+ #else
909
+ const int openflags = O_WRONLY|O_CREAT|O_TRUNC;
910
+ const int fd = open(dstFileName, openflags, mode);
911
+ FILE* f = NULL;
912
+ if (fd != -1) {
913
+ f = fdopen(fd, "wb");
914
+ }
915
+ #endif
916
+
917
+ /* Check regular file after opening with O_CREAT */
918
+ isDstRegFile = UTIL_isFdRegularFile(fd);
919
+ if (prefs->sparseFileSupport == 1) {
920
+ prefs->sparseFileSupport = ZSTD_SPARSE_DEFAULT;
921
+ if (!isDstRegFile) {
922
+ prefs->sparseFileSupport = 0;
923
+ DISPLAYLEVEL(4, "Sparse File Support is disabled when output is not a file \n");
924
+ }
925
+ }
926
+
927
+ if (f == NULL) {
928
+ if (UTIL_isFileDescriptorPipe(dstFileName)) {
929
+ DISPLAYLEVEL(1, "zstd: error: no output specified (use -o or -c). \n");
930
+ } else {
931
+ DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno));
932
+ }
933
+ } else {
934
+ /* An increased buffer size can provide a significant performance
935
+ * boost on some platforms. Note that providing a NULL buf with a
936
+ * size that's not 0 is not defined in ANSI C, but is defined in an
937
+ * extension. There are three possibilities here:
938
+ * 1. Libc supports the extended version and everything is good.
939
+ * 2. Libc ignores the size when buf is NULL, in which case
940
+ * everything will continue as if we didn't call `setvbuf()`.
941
+ * 3. We fail the call and execution continues but a warning
942
+ * message might be shown.
943
+ * In all cases due execution continues. For now, I believe that
944
+ * this is a more cost-effective solution than managing the buffers
945
+ * allocations ourselves (will require an API change).
946
+ */
947
+ if (setvbuf(f, NULL, _IOFBF, 1 MB)) {
948
+ DISPLAYLEVEL(2, "Warning: setvbuf failed for %s\n", dstFileName);
949
+ }
950
+ }
951
+ return f;
952
+ }
953
+ }
954
+
955
+
956
+ /* FIO_getDictFileStat() :
957
+ */
958
+ static void FIO_getDictFileStat(const char* fileName, stat_t* dictFileStat) {
959
+ assert(dictFileStat != NULL);
960
+ if (fileName == NULL) return;
961
+
962
+ if (!UTIL_stat(fileName, dictFileStat)) {
963
+ EXM_THROW(31, "Stat failed on dictionary file %s: %s", fileName, strerror(errno));
964
+ }
965
+
966
+ if (!UTIL_isRegularFileStat(dictFileStat)) {
967
+ EXM_THROW(32, "Dictionary %s must be a regular file.", fileName);
968
+ }
969
+ }
970
+
971
+ /* FIO_setDictBufferMalloc() :
972
+ * allocates a buffer, pointed by `dict->dictBuffer`,
973
+ * loads `filename` content into it, up to DICTSIZE_MAX bytes.
974
+ * @return : loaded size
975
+ * if fileName==NULL, returns 0 and a NULL pointer
976
+ */
977
+ static size_t FIO_setDictBufferMalloc(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)
978
+ {
979
+ FILE* fileHandle;
980
+ U64 fileSize;
981
+ void** bufferPtr = &dict->dictBuffer;
982
+
983
+ assert(bufferPtr != NULL);
984
+ assert(dictFileStat != NULL);
985
+ *bufferPtr = NULL;
986
+ if (fileName == NULL) return 0;
987
+
988
+ DISPLAYLEVEL(4,"Loading %s as dictionary \n", fileName);
989
+
990
+ fileHandle = fopen(fileName, "rb");
991
+
992
+ if (fileHandle == NULL) {
993
+ EXM_THROW(33, "Couldn't open dictionary %s: %s", fileName, strerror(errno));
994
+ }
995
+
996
+ fileSize = UTIL_getFileSizeStat(dictFileStat);
997
+ {
998
+ size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;
999
+ if (fileSize > dictSizeMax) {
1000
+ EXM_THROW(34, "Dictionary file %s is too large (> %u bytes)",
1001
+ fileName, (unsigned)dictSizeMax); /* avoid extreme cases */
1002
+ }
1003
+ }
1004
+ *bufferPtr = malloc((size_t)fileSize);
1005
+ if (*bufferPtr==NULL) EXM_THROW(34, "%s", strerror(errno));
1006
+ { size_t const readSize = fread(*bufferPtr, 1, (size_t)fileSize, fileHandle);
1007
+ if (readSize != fileSize) {
1008
+ EXM_THROW(35, "Error reading dictionary file %s : %s",
1009
+ fileName, strerror(errno));
1010
+ }
1011
+ }
1012
+ fclose(fileHandle);
1013
+ return (size_t)fileSize;
1014
+ }
1015
+
1016
+ #if (PLATFORM_POSIX_VERSION > 0)
1017
+ #include <sys/mman.h>
1018
+ static void FIO_munmap(FIO_Dict_t* dict)
1019
+ {
1020
+ munmap(dict->dictBuffer, dict->dictBufferSize);
1021
+ dict->dictBuffer = NULL;
1022
+ dict->dictBufferSize = 0;
1023
+ }
1024
+ static size_t FIO_setDictBufferMMap(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)
1025
+ {
1026
+ int fileHandle;
1027
+ U64 fileSize;
1028
+ void** bufferPtr = &dict->dictBuffer;
1029
+
1030
+ assert(bufferPtr != NULL);
1031
+ assert(dictFileStat != NULL);
1032
+ *bufferPtr = NULL;
1033
+ if (fileName == NULL) return 0;
1034
+
1035
+ DISPLAYLEVEL(4,"Loading %s as dictionary \n", fileName);
1036
+
1037
+ fileHandle = open(fileName, O_RDONLY);
1038
+
1039
+ if (fileHandle == -1) {
1040
+ EXM_THROW(33, "Couldn't open dictionary %s: %s", fileName, strerror(errno));
1041
+ }
1042
+
1043
+ fileSize = UTIL_getFileSizeStat(dictFileStat);
1044
+ {
1045
+ size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;
1046
+ if (fileSize > dictSizeMax) {
1047
+ EXM_THROW(34, "Dictionary file %s is too large (> %u bytes)",
1048
+ fileName, (unsigned)dictSizeMax); /* avoid extreme cases */
1049
+ }
1050
+ }
1051
+
1052
+ *bufferPtr = mmap(NULL, (size_t)fileSize, PROT_READ, MAP_PRIVATE, fileHandle, 0);
1053
+ if (*bufferPtr==NULL) EXM_THROW(34, "%s", strerror(errno));
1054
+
1055
+ close(fileHandle);
1056
+ return (size_t)fileSize;
1057
+ }
1058
+ #elif defined(_MSC_VER) || defined(_WIN32)
1059
+ #include <windows.h>
1060
+ static void FIO_munmap(FIO_Dict_t* dict)
1061
+ {
1062
+ UnmapViewOfFile(dict->dictBuffer);
1063
+ CloseHandle(dict->dictHandle);
1064
+ dict->dictBuffer = NULL;
1065
+ dict->dictBufferSize = 0;
1066
+ }
1067
+ static size_t FIO_setDictBufferMMap(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)
1068
+ {
1069
+ HANDLE fileHandle, mapping;
1070
+ U64 fileSize;
1071
+ void** bufferPtr = &dict->dictBuffer;
1072
+
1073
+ assert(bufferPtr != NULL);
1074
+ assert(dictFileStat != NULL);
1075
+ *bufferPtr = NULL;
1076
+ if (fileName == NULL) return 0;
1077
+
1078
+ DISPLAYLEVEL(4,"Loading %s as dictionary \n", fileName);
1079
+
1080
+ fileHandle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
1081
+
1082
+ if (fileHandle == INVALID_HANDLE_VALUE) {
1083
+ EXM_THROW(33, "Couldn't open dictionary %s: %s", fileName, strerror(errno));
1084
+ }
1085
+
1086
+ fileSize = UTIL_getFileSizeStat(dictFileStat);
1087
+ {
1088
+ size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX;
1089
+ if (fileSize > dictSizeMax) {
1090
+ EXM_THROW(34, "Dictionary file %s is too large (> %u bytes)",
1091
+ fileName, (unsigned)dictSizeMax); /* avoid extreme cases */
1092
+ }
1093
+ }
1094
+
1095
+ mapping = CreateFileMapping(fileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
1096
+ if (mapping == NULL) {
1097
+ EXM_THROW(35, "Couldn't map dictionary %s: %s", fileName, strerror(errno));
1098
+ }
1099
+
1100
+ *bufferPtr = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, (DWORD)fileSize); /* we can only cast to DWORD here because dictSize <= 2GB */
1101
+ if (*bufferPtr==NULL) EXM_THROW(36, "%s", strerror(errno));
1102
+
1103
+ dict->dictHandle = fileHandle;
1104
+ return (size_t)fileSize;
1105
+ }
1106
+ #else
1107
+ static size_t FIO_setDictBufferMMap(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat)
1108
+ {
1109
+ return FIO_setDictBufferMalloc(dict, fileName, prefs, dictFileStat);
1110
+ }
1111
+ static void FIO_munmap(FIO_Dict_t* dict) {
1112
+ free(dict->dictBuffer);
1113
+ dict->dictBuffer = NULL;
1114
+ dict->dictBufferSize = 0;
1115
+ }
1116
+ #endif
1117
+
1118
+ static void FIO_freeDict(FIO_Dict_t* dict) {
1119
+ if (dict->dictBufferType == FIO_mallocDict) {
1120
+ free(dict->dictBuffer);
1121
+ dict->dictBuffer = NULL;
1122
+ dict->dictBufferSize = 0;
1123
+ } else if (dict->dictBufferType == FIO_mmapDict) {
1124
+ FIO_munmap(dict);
1125
+ } else {
1126
+ assert(0); /* Should not reach this case */
1127
+ }
1128
+ }
1129
+
1130
+ static void FIO_initDict(FIO_Dict_t* dict, const char* fileName, FIO_prefs_t* const prefs, stat_t* dictFileStat, FIO_dictBufferType_t dictBufferType) {
1131
+ dict->dictBufferType = dictBufferType;
1132
+ if (dict->dictBufferType == FIO_mallocDict) {
1133
+ dict->dictBufferSize = FIO_setDictBufferMalloc(dict, fileName, prefs, dictFileStat);
1134
+ } else if (dict->dictBufferType == FIO_mmapDict) {
1135
+ dict->dictBufferSize = FIO_setDictBufferMMap(dict, fileName, prefs, dictFileStat);
1136
+ } else {
1137
+ assert(0); /* Should not reach this case */
1138
+ }
1139
+ }
1140
+
1141
+
1142
+ /* FIO_checkFilenameCollisions() :
1143
+ * Checks for and warns if there are any files that would have the same output path
1144
+ */
1145
+ int FIO_checkFilenameCollisions(const char** filenameTable, unsigned nbFiles) {
1146
+ const char **filenameTableSorted, *prevElem, *filename;
1147
+ unsigned u;
1148
+
1149
+ filenameTableSorted = (const char**) malloc(sizeof(char*) * nbFiles);
1150
+ if (!filenameTableSorted) {
1151
+ DISPLAYLEVEL(1, "Allocation error during filename collision checking \n");
1152
+ return 1;
1153
+ }
1154
+
1155
+ for (u = 0; u < nbFiles; ++u) {
1156
+ filename = strrchr(filenameTable[u], PATH_SEP);
1157
+ if (filename == NULL) {
1158
+ filenameTableSorted[u] = filenameTable[u];
1159
+ } else {
1160
+ filenameTableSorted[u] = filename+1;
1161
+ }
1162
+ }
1163
+
1164
+ qsort((void*)filenameTableSorted, nbFiles, sizeof(char*), UTIL_compareStr);
1165
+ prevElem = filenameTableSorted[0];
1166
+ for (u = 1; u < nbFiles; ++u) {
1167
+ if (strcmp(prevElem, filenameTableSorted[u]) == 0) {
1168
+ DISPLAYLEVEL(2, "WARNING: Two files have same filename: %s\n", prevElem);
1169
+ }
1170
+ prevElem = filenameTableSorted[u];
1171
+ }
1172
+
1173
+ free((void*)filenameTableSorted);
1174
+ return 0;
1175
+ }
1176
+
1177
+ static const char*
1178
+ extractFilename(const char* path, char separator)
1179
+ {
1180
+ const char* search = strrchr(path, separator);
1181
+ if (search == NULL) return path;
1182
+ return search+1;
1183
+ }
1184
+
1185
+ /* FIO_createFilename_fromOutDir() :
1186
+ * Takes a source file name and specified output directory, and
1187
+ * allocates memory for and returns a pointer to final path.
1188
+ * This function never returns an error (it may abort() in case of pb)
1189
+ */
1190
+ static char*
1191
+ FIO_createFilename_fromOutDir(const char* path, const char* outDirName, const size_t suffixLen)
1192
+ {
1193
+ const char* filenameStart;
1194
+ char separator;
1195
+ char* result;
1196
+
1197
+ #if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */
1198
+ separator = '\\';
1199
+ #else
1200
+ separator = '/';
1201
+ #endif
1202
+
1203
+ filenameStart = extractFilename(path, separator);
1204
+ #if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) /* windows support */
1205
+ filenameStart = extractFilename(filenameStart, '/'); /* sometimes, '/' separator is also used on Windows (mingw+msys2) */
1206
+ #endif
1207
+
1208
+ result = (char*) calloc(1, strlen(outDirName) + 1 + strlen(filenameStart) + suffixLen + 1);
1209
+ if (!result) {
1210
+ EXM_THROW(30, "zstd: FIO_createFilename_fromOutDir: %s", strerror(errno));
1211
+ }
1212
+
1213
+ memcpy(result, outDirName, strlen(outDirName));
1214
+ if (outDirName[strlen(outDirName)-1] == separator) {
1215
+ memcpy(result + strlen(outDirName), filenameStart, strlen(filenameStart));
1216
+ } else {
1217
+ memcpy(result + strlen(outDirName), &separator, 1);
1218
+ memcpy(result + strlen(outDirName) + 1, filenameStart, strlen(filenameStart));
1219
+ }
1220
+
1221
+ return result;
1222
+ }
1223
+
1224
+ /* FIO_highbit64() :
1225
+ * gives position of highest bit.
1226
+ * note : only works for v > 0 !
1227
+ */
1228
+ static unsigned FIO_highbit64(unsigned long long v)
1229
+ {
1230
+ unsigned count = 0;
1231
+ assert(v != 0);
1232
+ v >>= 1;
1233
+ while (v) { v >>= 1; count++; }
1234
+ return count;
1235
+ }
1236
+
1237
+ static void FIO_adjustMemLimitForPatchFromMode(FIO_prefs_t* const prefs,
1238
+ unsigned long long const dictSize,
1239
+ unsigned long long const maxSrcFileSize)
1240
+ {
1241
+ unsigned long long maxSize = MAX(prefs->memLimit, MAX(dictSize, maxSrcFileSize));
1242
+ unsigned const maxWindowSize = (1U << ZSTD_WINDOWLOG_MAX);
1243
+ if (maxSize == UTIL_FILESIZE_UNKNOWN)
1244
+ EXM_THROW(42, "Using --patch-from with stdin requires --stream-size");
1245
+ assert(maxSize != UTIL_FILESIZE_UNKNOWN);
1246
+ if (maxSize > maxWindowSize)
1247
+ EXM_THROW(42, "Can't handle files larger than %u GB\n", maxWindowSize/(1 GB));
1248
+ FIO_setMemLimit(prefs, (unsigned)maxSize);
1249
+ }
1250
+
1251
+ /* FIO_multiFilesConcatWarning() :
1252
+ * This function handles logic when processing multiple files with -o or -c, displaying the appropriate warnings/prompts.
1253
+ * Returns 1 if the console should abort, 0 if console should proceed.
1254
+ *
1255
+ * If output is stdout or test mode is active, check that `--rm` disabled.
1256
+ *
1257
+ * If there is just 1 file to process, zstd will proceed as usual.
1258
+ * If each file get processed into its own separate destination file, proceed as usual.
1259
+ *
1260
+ * When multiple files are processed into a single output,
1261
+ * display a warning message, then disable --rm if it's set.
1262
+ *
1263
+ * If -f is specified or if output is stdout, just proceed.
1264
+ * If output is set with -o, prompt for confirmation.
1265
+ */
1266
+ static int FIO_multiFilesConcatWarning(const FIO_ctx_t* fCtx, FIO_prefs_t* prefs, const char* outFileName, int displayLevelCutoff)
1267
+ {
1268
+ if (fCtx->hasStdoutOutput) {
1269
+ if (prefs->removeSrcFile)
1270
+ /* this should not happen ; hard fail, to protect user's data
1271
+ * note: this should rather be an assert(), but we want to be certain that user's data will not be wiped out in case it nonetheless happen */
1272
+ EXM_THROW(43, "It's not allowed to remove input files when processed output is piped to stdout. "
1273
+ "This scenario is not supposed to be possible. "
1274
+ "This is a programming error. File an issue for it to be fixed.");
1275
+ }
1276
+ if (prefs->testMode) {
1277
+ if (prefs->removeSrcFile)
1278
+ /* this should not happen ; hard fail, to protect user's data
1279
+ * note: this should rather be an assert(), but we want to be certain that user's data will not be wiped out in case it nonetheless happen */
1280
+ EXM_THROW(43, "Test mode shall not remove input files! "
1281
+ "This scenario is not supposed to be possible. "
1282
+ "This is a programming error. File an issue for it to be fixed.");
1283
+ return 0;
1284
+ }
1285
+
1286
+ if (fCtx->nbFilesTotal == 1) return 0;
1287
+ assert(fCtx->nbFilesTotal > 1);
1288
+
1289
+ if (!outFileName) return 0;
1290
+
1291
+ if (fCtx->hasStdoutOutput) {
1292
+ DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into stdout. \n");
1293
+ } else {
1294
+ DISPLAYLEVEL(2, "zstd: WARNING: all input files will be processed and concatenated into a single output file: %s \n", outFileName);
1295
+ }
1296
+ DISPLAYLEVEL(2, "The concatenated output CANNOT regenerate original file names nor directory structure. \n")
1297
+
1298
+ /* multi-input into single output : --rm is not allowed */
1299
+ if (prefs->removeSrcFile) {
1300
+ DISPLAYLEVEL(2, "Since it's a destructive operation, input files will not be removed. \n");
1301
+ prefs->removeSrcFile = 0;
1302
+ }
1303
+
1304
+ if (fCtx->hasStdoutOutput) return 0;
1305
+ if (prefs->overwrite) return 0;
1306
+
1307
+ /* multiple files concatenated into single destination file using -o without -f */
1308
+ if (g_display_prefs.displayLevel <= displayLevelCutoff) {
1309
+ /* quiet mode => no prompt => fail automatically */
1310
+ DISPLAYLEVEL(1, "Concatenating multiple processed inputs into a single output loses file metadata. \n");
1311
+ DISPLAYLEVEL(1, "Aborting. \n");
1312
+ return 1;
1313
+ }
1314
+ /* normal mode => prompt */
1315
+ return UTIL_requireUserConfirmation("Proceed? (y/n): ", "Aborting...", "yY", fCtx->hasStdinInput);
1316
+ }
1317
+
1318
+ static ZSTD_inBuffer setInBuffer(const void* buf, size_t s, size_t pos)
1319
+ {
1320
+ ZSTD_inBuffer i;
1321
+ i.src = buf;
1322
+ i.size = s;
1323
+ i.pos = pos;
1324
+ return i;
1325
+ }
1326
+
1327
+ static ZSTD_outBuffer setOutBuffer(void* buf, size_t s, size_t pos)
1328
+ {
1329
+ ZSTD_outBuffer o;
1330
+ o.dst = buf;
1331
+ o.size = s;
1332
+ o.pos = pos;
1333
+ return o;
1334
+ }
1335
+
1336
+ #ifndef ZSTD_NOCOMPRESS
1337
+
1338
+ /* **********************************************************************
1339
+ * Compression
1340
+ ************************************************************************/
1341
+ typedef struct {
1342
+ FIO_Dict_t dict;
1343
+ const char* dictFileName;
1344
+ stat_t dictFileStat;
1345
+ ZSTD_CStream* cctx;
1346
+ FIO_SyncCompressIO io;
1347
+ } cRess_t;
1348
+
1349
+ /** ZSTD_cycleLog() :
1350
+ * condition for correct operation : hashLog > 1 */
1351
+ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
1352
+ {
1353
+ U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
1354
+ assert(hashLog > 1);
1355
+ return hashLog - btScale;
1356
+ }
1357
+
1358
+ static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs,
1359
+ ZSTD_compressionParameters* comprParams,
1360
+ unsigned long long const dictSize,
1361
+ unsigned long long const maxSrcFileSize,
1362
+ int cLevel)
1363
+ {
1364
+ unsigned const fileWindowLog = FIO_highbit64(maxSrcFileSize) + 1;
1365
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams(cLevel, (size_t)maxSrcFileSize, (size_t)dictSize);
1366
+ FIO_adjustMemLimitForPatchFromMode(prefs, dictSize, maxSrcFileSize);
1367
+ if (fileWindowLog > ZSTD_WINDOWLOG_MAX)
1368
+ DISPLAYLEVEL(1, "Max window log exceeded by file (compression ratio will suffer)\n");
1369
+ comprParams->windowLog = MAX(ZSTD_WINDOWLOG_MIN, MIN(ZSTD_WINDOWLOG_MAX, fileWindowLog));
1370
+ if (fileWindowLog > ZSTD_cycleLog(cParams.chainLog, cParams.strategy)) {
1371
+ if (!prefs->ldmFlag)
1372
+ DISPLAYLEVEL(2, "long mode automatically triggered\n");
1373
+ FIO_setLdmFlag(prefs, 1);
1374
+ }
1375
+ if (cParams.strategy >= ZSTD_btopt) {
1376
+ DISPLAYLEVEL(4, "[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\n");
1377
+ DISPLAYLEVEL(4, "- Set a larger targetLength (e.g. --zstd=targetLength=4096)\n");
1378
+ DISPLAYLEVEL(4, "- Set a larger chainLog (e.g. --zstd=chainLog=%u)\n", ZSTD_CHAINLOG_MAX);
1379
+ DISPLAYLEVEL(4, "- Set a larger LDM hashLog (e.g. --zstd=ldmHashLog=%u)\n", ZSTD_LDM_HASHLOG_MAX);
1380
+ DISPLAYLEVEL(4, "- Set a smaller LDM rateLog (e.g. --zstd=ldmHashRateLog=%u)\n", ZSTD_LDM_HASHRATELOG_MIN);
1381
+ DISPLAYLEVEL(4, "Also consider playing around with searchLog and hashLog\n");
1382
+ }
1383
+ }
1384
+
1385
+ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs,
1386
+ const char* dictFileName, unsigned long long const maxSrcFileSize,
1387
+ int cLevel, ZSTD_compressionParameters comprParams) {
1388
+ int useMMap = prefs->mmapDict == ZSTD_ps_enable;
1389
+ int forceNoUseMMap = prefs->mmapDict == ZSTD_ps_disable;
1390
+ FIO_dictBufferType_t dictBufferType;
1391
+ cRess_t ress;
1392
+ memset(&ress, 0, sizeof(ress));
1393
+
1394
+ DISPLAYLEVEL(6, "FIO_createCResources \n");
1395
+ ress.cctx = ZSTD_createCCtx();
1396
+ if (ress.cctx == NULL)
1397
+ EXM_THROW(30, "allocation error (%s): can't create ZSTD_CCtx",
1398
+ strerror(errno));
1399
+
1400
+ FIO_getDictFileStat(dictFileName, &ress.dictFileStat);
1401
+
1402
+ /* need to update memLimit before calling createDictBuffer
1403
+ * because of memLimit check inside it */
1404
+ if (prefs->patchFromMode) {
1405
+ U64 const dictSize = UTIL_getFileSizeStat(&ress.dictFileStat);
1406
+ unsigned long long const ssSize = (unsigned long long)prefs->streamSrcSize;
1407
+ useMMap |= dictSize > prefs->memLimit;
1408
+ FIO_adjustParamsForPatchFromMode(prefs, &comprParams, dictSize, ssSize > 0 ? ssSize : maxSrcFileSize, cLevel);
1409
+ }
1410
+
1411
+ dictBufferType = (useMMap && !forceNoUseMMap) ? FIO_mmapDict : FIO_mallocDict;
1412
+ FIO_initDict(&ress.dict, dictFileName, prefs, &ress.dictFileStat, dictBufferType); /* works with dictFileName==NULL */
1413
+
1414
+ FIO_SyncCompressIO_init(&ress.io, prefs, ZSTD_CStreamInSize(), ZSTD_CStreamOutSize());
1415
+
1416
+ /* Advanced parameters, including dictionary */
1417
+ if (dictFileName && (ress.dict.dictBuffer==NULL))
1418
+ EXM_THROW(32, "allocation error : can't create dictBuffer");
1419
+ ress.dictFileName = dictFileName;
1420
+
1421
+ if (prefs->adaptiveMode && !prefs->ldmFlag && !comprParams.windowLog)
1422
+ comprParams.windowLog = ADAPT_WINDOWLOG_DEFAULT;
1423
+
1424
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, prefs->contentSize) ); /* always enable content size when available (note: supposed to be default) */
1425
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, prefs->dictIDFlag) );
1426
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) );
1427
+ /* compression level */
1428
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) );
1429
+ /* max compressed block size */
1430
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetCBlockSize, (int)prefs->targetCBlockSize) );
1431
+ /* source size hint */
1432
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_srcSizeHint, (int)prefs->srcSizeHint) );
1433
+ /* long distance matching */
1434
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, prefs->ldmFlag) );
1435
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, prefs->ldmHashLog) );
1436
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmMinMatch, prefs->ldmMinMatch) );
1437
+ if (prefs->ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET) {
1438
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmBucketSizeLog, prefs->ldmBucketSizeLog) );
1439
+ }
1440
+ if (prefs->ldmHashRateLog != FIO_LDM_PARAM_NOTSET) {
1441
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashRateLog, prefs->ldmHashRateLog) );
1442
+ }
1443
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_useRowMatchFinder, prefs->useRowMatchFinder));
1444
+ /* compression parameters */
1445
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, (int)comprParams.windowLog) );
1446
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, (int)comprParams.chainLog) );
1447
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, (int)comprParams.hashLog) );
1448
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, (int)comprParams.searchLog) );
1449
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_minMatch, (int)comprParams.minMatch) );
1450
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetLength, (int)comprParams.targetLength) );
1451
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_strategy, (int)comprParams.strategy) );
1452
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_literalCompressionMode, (int)prefs->literalCompressionMode) );
1453
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableDedicatedDictSearch, 1) );
1454
+ /* multi-threading */
1455
+ #ifdef ZSTD_MULTITHREAD
1456
+ DISPLAYLEVEL(5,"set nb workers = %u \n", prefs->nbWorkers);
1457
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, prefs->nbWorkers) );
1458
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, prefs->jobSize) );
1459
+ if (prefs->overlapLog != FIO_OVERLAP_LOG_NOTSET) {
1460
+ DISPLAYLEVEL(3,"set overlapLog = %u \n", prefs->overlapLog);
1461
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, prefs->overlapLog) );
1462
+ }
1463
+ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_rsyncable, prefs->rsyncable) );
1464
+ #endif
1465
+ /* dictionary */
1466
+ if (prefs->patchFromMode) {
1467
+ CHECK( ZSTD_CCtx_refPrefix(ress.cctx, ress.dict.dictBuffer, ress.dict.dictBufferSize) );
1468
+ } else {
1469
+ CHECK( ZSTD_CCtx_loadDictionary_byReference(ress.cctx, ress.dict.dictBuffer, ress.dict.dictBufferSize) );
1470
+ }
1471
+
1472
+ return ress;
1473
+ }
1474
+
1475
+ static void FIO_freeCResources(cRess_t* const ress)
1476
+ {
1477
+ FIO_freeDict(&(ress->dict));
1478
+ FIO_SyncCompressIO_destroy(&ress->io);
1479
+ ZSTD_freeCStream(ress->cctx); /* never fails */
1480
+ }
1481
+
1482
+
1483
+ #ifdef ZSTD_GZCOMPRESS
1484
+ static unsigned long long
1485
+ FIO_compressGzFrame(cRess_t* ress,
1486
+ const char* srcFileName, U64 const srcFileSize,
1487
+ int compressionLevel, U64* readsize)
1488
+ {
1489
+ FIO_SyncCompressIO* const syncIO = &ress->io;
1490
+ unsigned long long inFileSize = 0, outFileSize = 0;
1491
+ z_stream strm;
1492
+
1493
+ if (compressionLevel > Z_BEST_COMPRESSION)
1494
+ compressionLevel = Z_BEST_COMPRESSION;
1495
+
1496
+ strm.zalloc = Z_NULL;
1497
+ strm.zfree = Z_NULL;
1498
+ strm.opaque = Z_NULL;
1499
+
1500
+ { int const ret = deflateInit2(&strm, compressionLevel, Z_DEFLATED,
1501
+ 15 /* maxWindowLogSize */ + 16 /* gzip only */,
1502
+ 8, Z_DEFAULT_STRATEGY); /* see https://www.zlib.net/manual.html */
1503
+ if (ret != Z_OK) {
1504
+ EXM_THROW(71, "zstd: %s: deflateInit2 error %d \n", srcFileName, ret);
1505
+ } }
1506
+
1507
+ strm.next_in = 0;
1508
+ strm.avail_in = 0;
1509
+ strm.next_out = (Bytef*)syncIO->outBuffer;
1510
+ strm.avail_out = (uInt)syncIO->outCapacity;
1511
+
1512
+ while (1) {
1513
+ int ret;
1514
+ if (strm.avail_in == 0) {
1515
+ size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());
1516
+ if (syncIO->srcBufferLoaded == 0) break;
1517
+ inFileSize += added;
1518
+ *readsize += added;
1519
+ strm.next_in = (z_const unsigned char*)syncIO->srcBuffer;
1520
+ strm.avail_in = (uInt)syncIO->srcBufferLoaded;
1521
+ }
1522
+
1523
+ {
1524
+ size_t const availBefore = strm.avail_in;
1525
+ ret = deflate(&strm, Z_NO_FLUSH);
1526
+ FIO_SyncCompressIO_consumeBytes(syncIO, availBefore - strm.avail_in);
1527
+ }
1528
+
1529
+ if (ret != Z_OK)
1530
+ EXM_THROW(72, "zstd: %s: deflate error %d \n", srcFileName, ret);
1531
+ { size_t const cSize = (size_t)((uInt)syncIO->outCapacity - strm.avail_out);
1532
+ if (cSize) {
1533
+ FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, cSize);
1534
+ outFileSize += cSize;
1535
+ strm.next_out = (Bytef*)syncIO->outBuffer;
1536
+ strm.avail_out = (uInt)syncIO->outCapacity;
1537
+ } }
1538
+ if (srcFileSize == UTIL_FILESIZE_UNKNOWN) {
1539
+ DISPLAYUPDATE_PROGRESS(
1540
+ "\rRead : %u MB ==> %.2f%% ",
1541
+ (unsigned)(inFileSize>>20),
1542
+ (double)outFileSize/(double)inFileSize*100)
1543
+ } else {
1544
+ DISPLAYUPDATE_PROGRESS(
1545
+ "\rRead : %u / %u MB ==> %.2f%% ",
1546
+ (unsigned)(inFileSize>>20), (unsigned)(srcFileSize>>20),
1547
+ (double)outFileSize/(double)inFileSize*100);
1548
+ } }
1549
+
1550
+ while (1) {
1551
+ int const ret = deflate(&strm, Z_FINISH);
1552
+ { size_t const cSize = (size_t)((uInt)syncIO->outCapacity - strm.avail_out);
1553
+ if (cSize) {
1554
+ FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, cSize);
1555
+ outFileSize += cSize;
1556
+ strm.next_out = (Bytef*)syncIO->outBuffer;
1557
+ strm.avail_out = (uInt)syncIO->outCapacity;
1558
+ } }
1559
+ if (ret == Z_STREAM_END) break;
1560
+ if (ret != Z_BUF_ERROR)
1561
+ EXM_THROW(77, "zstd: %s: deflate error %d \n", srcFileName, ret);
1562
+ }
1563
+
1564
+ { int const ret = deflateEnd(&strm);
1565
+ if (ret != Z_OK) {
1566
+ EXM_THROW(79, "zstd: %s: deflateEnd error %d \n", srcFileName, ret);
1567
+ } }
1568
+ *readsize = inFileSize;
1569
+ FIO_SyncCompressIO_finish(syncIO);
1570
+ return outFileSize;
1571
+ }
1572
+ #endif
1573
+
1574
+
1575
+ #ifdef ZSTD_LZMACOMPRESS
1576
+ static unsigned long long
1577
+ FIO_compressLzmaFrame(cRess_t* ress,
1578
+ const char* srcFileName, U64 const srcFileSize,
1579
+ int compressionLevel, U64* readsize, int plain_lzma)
1580
+ {
1581
+ FIO_SyncCompressIO* const syncIO = &ress->io;
1582
+ unsigned long long inFileSize = 0, outFileSize = 0;
1583
+ lzma_stream strm = LZMA_STREAM_INIT;
1584
+ lzma_action action = LZMA_RUN;
1585
+ lzma_ret ret;
1586
+
1587
+ if (compressionLevel < 0) compressionLevel = 0;
1588
+ if (compressionLevel > 9) compressionLevel = 9;
1589
+
1590
+ if (plain_lzma) {
1591
+ lzma_options_lzma opt_lzma;
1592
+ if (lzma_lzma_preset(&opt_lzma, compressionLevel))
1593
+ EXM_THROW(81, "zstd: %s: lzma_lzma_preset error", srcFileName);
1594
+ ret = lzma_alone_encoder(&strm, &opt_lzma); /* LZMA */
1595
+ if (ret != LZMA_OK)
1596
+ EXM_THROW(82, "zstd: %s: lzma_alone_encoder error %d", srcFileName, ret);
1597
+ } else {
1598
+ ret = lzma_easy_encoder(&strm, compressionLevel, LZMA_CHECK_CRC64); /* XZ */
1599
+ if (ret != LZMA_OK)
1600
+ EXM_THROW(83, "zstd: %s: lzma_easy_encoder error %d", srcFileName, ret);
1601
+ }
1602
+
1603
+ strm.next_out = (BYTE*)syncIO->outBuffer;
1604
+ strm.avail_out = syncIO->outCapacity;
1605
+ strm.next_in = 0;
1606
+ strm.avail_in = 0;
1607
+
1608
+ while (1) {
1609
+ if (strm.avail_in == 0) {
1610
+ size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());
1611
+ if (syncIO->srcBufferLoaded == 0) action = LZMA_FINISH;
1612
+ inFileSize += added;
1613
+ *readsize += added;
1614
+ strm.next_in = (BYTE const*)syncIO->srcBuffer;
1615
+ strm.avail_in = syncIO->srcBufferLoaded;
1616
+ }
1617
+
1618
+ {
1619
+ size_t const availBefore = strm.avail_in;
1620
+ ret = lzma_code(&strm, action);
1621
+ FIO_SyncCompressIO_consumeBytes(syncIO, availBefore - strm.avail_in);
1622
+ }
1623
+
1624
+ if (ret != LZMA_OK && ret != LZMA_STREAM_END)
1625
+ EXM_THROW(84, "zstd: %s: lzma_code encoding error %d", srcFileName, ret);
1626
+ { size_t const compBytes = syncIO->outCapacity - strm.avail_out;
1627
+ if (compBytes) {
1628
+ FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, compBytes);
1629
+ outFileSize += compBytes;
1630
+ strm.next_out = (BYTE*)syncIO->outBuffer;
1631
+ strm.avail_out = syncIO->outCapacity;
1632
+ } }
1633
+ if (srcFileSize == UTIL_FILESIZE_UNKNOWN)
1634
+ DISPLAYUPDATE_PROGRESS("\rRead : %u MB ==> %.2f%%",
1635
+ (unsigned)(inFileSize>>20),
1636
+ (double)outFileSize/(double)inFileSize*100)
1637
+ else
1638
+ DISPLAYUPDATE_PROGRESS("\rRead : %u / %u MB ==> %.2f%%",
1639
+ (unsigned)(inFileSize>>20), (unsigned)(srcFileSize>>20),
1640
+ (double)outFileSize/(double)inFileSize*100);
1641
+ if (ret == LZMA_STREAM_END) break;
1642
+ }
1643
+
1644
+ lzma_end(&strm);
1645
+ *readsize = inFileSize;
1646
+
1647
+ FIO_SyncCompressIO_finish(syncIO);
1648
+
1649
+ return outFileSize;
1650
+ }
1651
+ #endif
1652
+
1653
+ #ifdef ZSTD_LZ4COMPRESS
1654
+
1655
+ #if LZ4_VERSION_NUMBER <= 10600
1656
+ #define LZ4F_blockLinked blockLinked
1657
+ #define LZ4F_max64KB max64KB
1658
+ #endif
1659
+
1660
+ static int FIO_LZ4_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); }
1661
+
1662
+ static unsigned long long
1663
+ FIO_compressLz4Frame(cRess_t* ress,
1664
+ const char* srcFileName, U64 const srcFileSize,
1665
+ int compressionLevel, int checksumFlag,
1666
+ U64* readsize)
1667
+ {
1668
+ FIO_SyncCompressIO* const syncIO = &ress->io;
1669
+ const size_t blockSize = FIO_LZ4_GetBlockSize_FromBlockId(LZ4F_max64KB);
1670
+ unsigned long long inFileSize = 0, outFileSize = 0;
1671
+
1672
+ LZ4F_preferences_t prefs;
1673
+ LZ4F_compressionContext_t ctx;
1674
+
1675
+ LZ4F_errorCode_t const errorCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
1676
+ if (LZ4F_isError(errorCode))
1677
+ EXM_THROW(31, "zstd: failed to create lz4 compression context");
1678
+
1679
+ memset(&prefs, 0, sizeof(prefs));
1680
+
1681
+ assert(blockSize <= syncIO->inCapacity);
1682
+
1683
+ /* autoflush off to mitigate a bug in lz4<=1.9.3 for compression level 12 */
1684
+ prefs.autoFlush = 0;
1685
+ prefs.compressionLevel = compressionLevel;
1686
+ prefs.frameInfo.blockMode = LZ4F_blockLinked;
1687
+ prefs.frameInfo.blockSizeID = LZ4F_max64KB;
1688
+ prefs.frameInfo.contentChecksumFlag = (contentChecksum_t)checksumFlag;
1689
+ #if LZ4_VERSION_NUMBER >= 10600
1690
+ prefs.frameInfo.contentSize = (srcFileSize==UTIL_FILESIZE_UNKNOWN) ? 0 : srcFileSize;
1691
+ #endif
1692
+ assert(LZ4F_compressBound(blockSize, &prefs) <= syncIO->outCapacity);
1693
+
1694
+ {
1695
+ size_t headerSize = LZ4F_compressBegin(ctx, syncIO->outBuffer, syncIO->outCapacity, &prefs);
1696
+ if (LZ4F_isError(headerSize))
1697
+ EXM_THROW(33, "File header generation failed : %s",
1698
+ LZ4F_getErrorName(headerSize));
1699
+ FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, headerSize);
1700
+ outFileSize += headerSize;
1701
+
1702
+ {
1703
+ size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, blockSize);
1704
+ inFileSize += added;
1705
+ *readsize += added;
1706
+ }
1707
+
1708
+ while (syncIO->srcBufferLoaded) {
1709
+ size_t const inSize = MIN(blockSize, syncIO->srcBufferLoaded);
1710
+ size_t const outSize = LZ4F_compressUpdate(ctx, syncIO->outBuffer, syncIO->outCapacity,
1711
+ syncIO->srcBuffer, inSize, NULL);
1712
+ if (LZ4F_isError(outSize))
1713
+ EXM_THROW(35, "zstd: %s: lz4 compression failed : %s",
1714
+ srcFileName, LZ4F_getErrorName(outSize));
1715
+ outFileSize += outSize;
1716
+ if (srcFileSize == UTIL_FILESIZE_UNKNOWN) {
1717
+ DISPLAYUPDATE_PROGRESS("\rRead : %u MB ==> %.2f%%",
1718
+ (unsigned)(inFileSize>>20),
1719
+ (double)outFileSize/(double)inFileSize*100)
1720
+ } else {
1721
+ DISPLAYUPDATE_PROGRESS("\rRead : %u / %u MB ==> %.2f%%",
1722
+ (unsigned)(inFileSize>>20), (unsigned)(srcFileSize>>20),
1723
+ (double)outFileSize/(double)inFileSize*100);
1724
+ }
1725
+
1726
+ FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, outSize);
1727
+
1728
+ FIO_SyncCompressIO_consumeBytes(syncIO, inSize);
1729
+ {
1730
+ size_t const added = FIO_SyncCompressIO_fillBuffer(syncIO, blockSize);
1731
+ inFileSize += added;
1732
+ *readsize += added;
1733
+ }
1734
+ }
1735
+
1736
+ headerSize = LZ4F_compressEnd(ctx, syncIO->outBuffer, syncIO->outCapacity, NULL);
1737
+ if (LZ4F_isError(headerSize))
1738
+ EXM_THROW(38, "zstd: %s: lz4 end of file generation failed : %s",
1739
+ srcFileName, LZ4F_getErrorName(headerSize));
1740
+
1741
+ FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, headerSize);
1742
+ outFileSize += headerSize;
1743
+ }
1744
+
1745
+ LZ4F_freeCompressionContext(ctx);
1746
+ FIO_SyncCompressIO_finish(syncIO);
1747
+
1748
+ return outFileSize;
1749
+ }
1750
+ #endif
1751
+
1752
+ static unsigned long long
1753
+ FIO_compressZstdFrame(FIO_ctx_t* const fCtx,
1754
+ FIO_prefs_t* const prefs,
1755
+ cRess_t* ress,
1756
+ const char* srcFileName, U64 fileSize,
1757
+ int compressionLevel, U64* readsize)
1758
+ {
1759
+ FIO_SyncCompressIO* const syncIO = &ress->io;
1760
+
1761
+ U64 compressedfilesize = 0;
1762
+ ZSTD_EndDirective directive = ZSTD_e_continue;
1763
+ U64 pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
1764
+
1765
+ /* stats */
1766
+ ZSTD_frameProgression previous_zfp_update = { 0, 0, 0, 0, 0, 0 };
1767
+ ZSTD_frameProgression previous_zfp_correction = { 0, 0, 0, 0, 0, 0 };
1768
+ typedef enum { noChange, slower, faster } speedChange_e;
1769
+ speedChange_e speedChange = noChange;
1770
+ unsigned flushWaiting = 0;
1771
+ unsigned inputPresented = 0;
1772
+ unsigned inputBlocked = 0;
1773
+ unsigned lastJobID = 0;
1774
+ UTIL_time_t lastAdaptTime = UTIL_getTime();
1775
+ U64 const adaptEveryMicro = REFRESH_RATE;
1776
+
1777
+ UTIL_HumanReadableSize_t const file_hrs = UTIL_makeHumanReadableSize(fileSize);
1778
+
1779
+ DISPLAYLEVEL(6, "compression using zstd format \n");
1780
+
1781
+ /* init */
1782
+ if (fileSize != UTIL_FILESIZE_UNKNOWN) {
1783
+ pledgedSrcSize = fileSize;
1784
+ CHECK(ZSTD_CCtx_setPledgedSrcSize(ress->cctx, fileSize));
1785
+ } else if (prefs->streamSrcSize > 0) {
1786
+ /* unknown source size; use the declared stream size */
1787
+ pledgedSrcSize = prefs->streamSrcSize;
1788
+ CHECK( ZSTD_CCtx_setPledgedSrcSize(ress->cctx, prefs->streamSrcSize) );
1789
+ }
1790
+
1791
+ { int windowLog;
1792
+ UTIL_HumanReadableSize_t windowSize;
1793
+ CHECK(ZSTD_CCtx_getParameter(ress->cctx, ZSTD_c_windowLog, &windowLog));
1794
+ if (windowLog == 0) {
1795
+ if (prefs->ldmFlag) {
1796
+ /* If long mode is set without a window size libzstd will set this size internally */
1797
+ windowLog = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
1798
+ } else {
1799
+ const ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, fileSize, 0);
1800
+ windowLog = (int)cParams.windowLog;
1801
+ }
1802
+ }
1803
+ windowSize = UTIL_makeHumanReadableSize(MAX(1ULL, MIN(1ULL << windowLog, pledgedSrcSize)));
1804
+ DISPLAYLEVEL(4, "Decompression will require %.*f%s of memory\n", windowSize.precision, windowSize.value, windowSize.suffix);
1805
+ }
1806
+
1807
+ /* Main compression loop */
1808
+ do {
1809
+ size_t stillToFlush;
1810
+ /* Fill input Buffer */
1811
+ size_t const inSize = FIO_SyncCompressIO_fillBuffer(syncIO, ZSTD_CStreamInSize());
1812
+ ZSTD_inBuffer inBuff = setInBuffer( syncIO->srcBuffer, syncIO->srcBufferLoaded, 0 );
1813
+ DISPLAYLEVEL(6, "fread %u bytes from source \n", (unsigned)inSize);
1814
+ *readsize += inSize;
1815
+
1816
+ if ((syncIO->srcBufferLoaded == 0) || (*readsize == fileSize))
1817
+ directive = ZSTD_e_end;
1818
+
1819
+ stillToFlush = 1;
1820
+ while ((inBuff.pos != inBuff.size) /* input buffer must be entirely ingested */
1821
+ || (directive == ZSTD_e_end && stillToFlush != 0) ) {
1822
+
1823
+ size_t const oldIPos = inBuff.pos;
1824
+ ZSTD_outBuffer outBuff = setOutBuffer( syncIO->outBuffer, syncIO->outCapacity, 0 );
1825
+ size_t const toFlushNow = ZSTD_toFlushNow(ress->cctx);
1826
+ CHECK_V(stillToFlush, ZSTD_compressStream2(ress->cctx, &outBuff, &inBuff, directive));
1827
+ FIO_SyncCompressIO_consumeBytes(syncIO, inBuff.pos - oldIPos);
1828
+
1829
+ /* count stats */
1830
+ inputPresented++;
1831
+ if (oldIPos == inBuff.pos) inputBlocked++; /* input buffer is full and can't take any more : input speed is faster than consumption rate */
1832
+ if (!toFlushNow) flushWaiting = 1;
1833
+
1834
+ /* Write compressed stream */
1835
+ DISPLAYLEVEL(6, "ZSTD_compress_generic(end:%u) => input pos(%u)<=(%u)size ; output generated %u bytes \n",
1836
+ (unsigned)directive, (unsigned)inBuff.pos, (unsigned)inBuff.size, (unsigned)outBuff.pos);
1837
+ if (outBuff.pos) {
1838
+ FIO_SyncCompressIO_commitOut(syncIO, syncIO->outBuffer, outBuff.pos);
1839
+ compressedfilesize += outBuff.pos;
1840
+ }
1841
+
1842
+ /* adaptive mode : statistics measurement and speed correction */
1843
+ if (prefs->adaptiveMode && UTIL_clockSpanMicro(lastAdaptTime) > adaptEveryMicro) {
1844
+ ZSTD_frameProgression const zfp = ZSTD_getFrameProgression(ress->cctx);
1845
+
1846
+ lastAdaptTime = UTIL_getTime();
1847
+
1848
+ /* check output speed */
1849
+ if (zfp.currentJobID > 1) { /* only possible if nbWorkers >= 1 */
1850
+
1851
+ unsigned long long newlyProduced = zfp.produced - previous_zfp_update.produced;
1852
+ unsigned long long newlyFlushed = zfp.flushed - previous_zfp_update.flushed;
1853
+ assert(zfp.produced >= previous_zfp_update.produced);
1854
+ assert(prefs->nbWorkers >= 1);
1855
+
1856
+ /* test if compression is blocked
1857
+ * either because output is slow and all buffers are full
1858
+ * or because input is slow and no job can start while waiting for at least one buffer to be filled.
1859
+ * note : exclude starting part, since currentJobID > 1 */
1860
+ if ( (zfp.consumed == previous_zfp_update.consumed) /* no data compressed : no data available, or no more buffer to compress to, OR compression is really slow (compression of a single block is slower than update rate)*/
1861
+ && (zfp.nbActiveWorkers == 0) /* confirmed : no compression ongoing */
1862
+ ) {
1863
+ DISPLAYLEVEL(6, "all buffers full : compression stopped => slow down \n")
1864
+ speedChange = slower;
1865
+ }
1866
+
1867
+ previous_zfp_update = zfp;
1868
+
1869
+ if ( (newlyProduced > (newlyFlushed * 9 / 8)) /* compression produces more data than output can flush (though production can be spiky, due to work unit : (N==4)*block sizes) */
1870
+ && (flushWaiting == 0) /* flush speed was never slowed by lack of production, so it's operating at max capacity */
1871
+ ) {
1872
+ DISPLAYLEVEL(6, "compression faster than flush (%llu > %llu), and flushed was never slowed down by lack of production => slow down \n", newlyProduced, newlyFlushed);
1873
+ speedChange = slower;
1874
+ }
1875
+ flushWaiting = 0;
1876
+ }
1877
+
1878
+ /* course correct only if there is at least one new job completed */
1879
+ if (zfp.currentJobID > lastJobID) {
1880
+ DISPLAYLEVEL(6, "compression level adaptation check \n")
1881
+
1882
+ /* check input speed */
1883
+ if (zfp.currentJobID > (unsigned)(prefs->nbWorkers+1)) { /* warm up period, to fill all workers */
1884
+ if (inputBlocked <= 0) {
1885
+ DISPLAYLEVEL(6, "input is never blocked => input is slower than ingestion \n");
1886
+ speedChange = slower;
1887
+ } else if (speedChange == noChange) {
1888
+ unsigned long long newlyIngested = zfp.ingested - previous_zfp_correction.ingested;
1889
+ unsigned long long newlyConsumed = zfp.consumed - previous_zfp_correction.consumed;
1890
+ unsigned long long newlyProduced = zfp.produced - previous_zfp_correction.produced;
1891
+ unsigned long long newlyFlushed = zfp.flushed - previous_zfp_correction.flushed;
1892
+ previous_zfp_correction = zfp;
1893
+ assert(inputPresented > 0);
1894
+ DISPLAYLEVEL(6, "input blocked %u/%u(%.2f) - ingested:%u vs %u:consumed - flushed:%u vs %u:produced \n",
1895
+ inputBlocked, inputPresented, (double)inputBlocked/inputPresented*100,
1896
+ (unsigned)newlyIngested, (unsigned)newlyConsumed,
1897
+ (unsigned)newlyFlushed, (unsigned)newlyProduced);
1898
+ if ( (inputBlocked > inputPresented / 8) /* input is waiting often, because input buffers is full : compression or output too slow */
1899
+ && (newlyFlushed * 33 / 32 > newlyProduced) /* flush everything that is produced */
1900
+ && (newlyIngested * 33 / 32 > newlyConsumed) /* input speed as fast or faster than compression speed */
1901
+ ) {
1902
+ DISPLAYLEVEL(6, "recommend faster as in(%llu) >= (%llu)comp(%llu) <= out(%llu) \n",
1903
+ newlyIngested, newlyConsumed, newlyProduced, newlyFlushed);
1904
+ speedChange = faster;
1905
+ }
1906
+ }
1907
+ inputBlocked = 0;
1908
+ inputPresented = 0;
1909
+ }
1910
+
1911
+ if (speedChange == slower) {
1912
+ DISPLAYLEVEL(6, "slower speed , higher compression \n")
1913
+ compressionLevel ++;
1914
+ if (compressionLevel > ZSTD_maxCLevel()) compressionLevel = ZSTD_maxCLevel();
1915
+ if (compressionLevel > prefs->maxAdaptLevel) compressionLevel = prefs->maxAdaptLevel;
1916
+ compressionLevel += (compressionLevel == 0); /* skip 0 */
1917
+ ZSTD_CCtx_setParameter(ress->cctx, ZSTD_c_compressionLevel, compressionLevel);
1918
+ }
1919
+ if (speedChange == faster) {
1920
+ DISPLAYLEVEL(6, "faster speed , lighter compression \n")
1921
+ compressionLevel --;
1922
+ if (compressionLevel < prefs->minAdaptLevel) compressionLevel = prefs->minAdaptLevel;
1923
+ compressionLevel -= (compressionLevel == 0); /* skip 0 */
1924
+ ZSTD_CCtx_setParameter(ress->cctx, ZSTD_c_compressionLevel, compressionLevel);
1925
+ }
1926
+ speedChange = noChange;
1927
+
1928
+ lastJobID = zfp.currentJobID;
1929
+ } /* if (zfp.currentJobID > lastJobID) */
1930
+ } /* if (prefs->adaptiveMode && UTIL_clockSpanMicro(lastAdaptTime) > adaptEveryMicro) */
1931
+
1932
+ /* display notification */
1933
+ if (SHOULD_DISPLAY_PROGRESS() && READY_FOR_UPDATE()) {
1934
+ ZSTD_frameProgression const zfp = ZSTD_getFrameProgression(ress->cctx);
1935
+ double const cShare = (double)zfp.produced / (double)(zfp.consumed + !zfp.consumed/*avoid div0*/) * 100;
1936
+ UTIL_HumanReadableSize_t const buffered_hrs = UTIL_makeHumanReadableSize(zfp.ingested - zfp.consumed);
1937
+ UTIL_HumanReadableSize_t const consumed_hrs = UTIL_makeHumanReadableSize(zfp.consumed);
1938
+ UTIL_HumanReadableSize_t const produced_hrs = UTIL_makeHumanReadableSize(zfp.produced);
1939
+
1940
+ DELAY_NEXT_UPDATE();
1941
+
1942
+ /* display progress notifications */
1943
+ DISPLAY_PROGRESS("\r%79s\r", ""); /* Clear out the current displayed line */
1944
+ if (g_display_prefs.displayLevel >= 3) {
1945
+ /* Verbose progress update */
1946
+ DISPLAY_PROGRESS(
1947
+ "(L%i) Buffered:%5.*f%s - Consumed:%5.*f%s - Compressed:%5.*f%s => %.2f%% ",
1948
+ compressionLevel,
1949
+ buffered_hrs.precision, buffered_hrs.value, buffered_hrs.suffix,
1950
+ consumed_hrs.precision, consumed_hrs.value, consumed_hrs.suffix,
1951
+ produced_hrs.precision, produced_hrs.value, produced_hrs.suffix,
1952
+ cShare );
1953
+ } else {
1954
+ /* Require level 2 or forcibly displayed progress counter for summarized updates */
1955
+ if (fCtx->nbFilesTotal > 1) {
1956
+ size_t srcFileNameSize = strlen(srcFileName);
1957
+ /* Ensure that the string we print is roughly the same size each time */
1958
+ if (srcFileNameSize > 18) {
1959
+ const char* truncatedSrcFileName = srcFileName + srcFileNameSize - 15;
1960
+ DISPLAY_PROGRESS("Compress: %u/%u files. Current: ...%s ",
1961
+ fCtx->currFileIdx+1, fCtx->nbFilesTotal, truncatedSrcFileName);
1962
+ } else {
1963
+ DISPLAY_PROGRESS("Compress: %u/%u files. Current: %*s ",
1964
+ fCtx->currFileIdx+1, fCtx->nbFilesTotal, (int)(18-srcFileNameSize), srcFileName);
1965
+ }
1966
+ }
1967
+ DISPLAY_PROGRESS("Read:%6.*f%4s ", consumed_hrs.precision, consumed_hrs.value, consumed_hrs.suffix);
1968
+ if (fileSize != UTIL_FILESIZE_UNKNOWN)
1969
+ DISPLAY_PROGRESS("/%6.*f%4s", file_hrs.precision, file_hrs.value, file_hrs.suffix);
1970
+ DISPLAY_PROGRESS(" ==> %2.f%%", cShare);
1971
+ }
1972
+ } /* if (SHOULD_DISPLAY_PROGRESS() && READY_FOR_UPDATE()) */
1973
+ } /* while ((inBuff.pos != inBuff.size) */
1974
+ } while (directive != ZSTD_e_end);
1975
+
1976
+ if (fileSize != UTIL_FILESIZE_UNKNOWN && *readsize != fileSize) {
1977
+ EXM_THROW(27, "Read error : Incomplete read : %llu / %llu B",
1978
+ (unsigned long long)*readsize, (unsigned long long)fileSize);
1979
+ }
1980
+
1981
+ FIO_SyncCompressIO_finish(syncIO);
1982
+
1983
+ return compressedfilesize;
1984
+ }
1985
+
1986
+ /*! FIO_compressFilename_internal() :
1987
+ * same as FIO_compressFilename_extRess(), with `ress.desFile` already opened.
1988
+ * @return : 0 : compression completed correctly,
1989
+ * 1 : missing or pb opening srcFileName
1990
+ */
1991
+ static int
1992
+ FIO_compressFilename_internal(FIO_ctx_t* const fCtx,
1993
+ FIO_prefs_t* const prefs,
1994
+ cRess_t* ress,
1995
+ const char* dstFileName, const char* srcFileName,
1996
+ int compressionLevel)
1997
+ {
1998
+ UTIL_time_t const timeStart = UTIL_getTime();
1999
+ clock_t const cpuStart = clock();
2000
+ U64 readsize = 0;
2001
+ U64 compressedfilesize = 0;
2002
+ U64 const fileSize = UTIL_getFileSize(srcFileName);
2003
+ DISPLAYLEVEL(5, "%s: %llu bytes \n", srcFileName, (unsigned long long)fileSize);
2004
+
2005
+ /* compression format selection */
2006
+ switch (prefs->compressionType) {
2007
+ default:
2008
+ case FIO_zstdCompression:
2009
+ compressedfilesize = FIO_compressZstdFrame(fCtx, prefs, ress, srcFileName, fileSize, compressionLevel, &readsize);
2010
+ break;
2011
+
2012
+ case FIO_gzipCompression:
2013
+ #ifdef ZSTD_GZCOMPRESS
2014
+ compressedfilesize = FIO_compressGzFrame(ress, srcFileName, fileSize, compressionLevel, &readsize);
2015
+ #else
2016
+ (void)compressionLevel;
2017
+ EXM_THROW(20, "zstd: %s: file cannot be compressed as gzip (zstd compiled without ZSTD_GZCOMPRESS) -- ignored \n",
2018
+ srcFileName);
2019
+ #endif
2020
+ break;
2021
+
2022
+ case FIO_xzCompression:
2023
+ case FIO_lzmaCompression:
2024
+ #ifdef ZSTD_LZMACOMPRESS
2025
+ compressedfilesize = FIO_compressLzmaFrame(ress, srcFileName, fileSize, compressionLevel, &readsize, prefs->compressionType==FIO_lzmaCompression);
2026
+ #else
2027
+ (void)compressionLevel;
2028
+ EXM_THROW(20, "zstd: %s: file cannot be compressed as xz/lzma (zstd compiled without ZSTD_LZMACOMPRESS) -- ignored \n",
2029
+ srcFileName);
2030
+ #endif
2031
+ break;
2032
+
2033
+ case FIO_lz4Compression:
2034
+ #ifdef ZSTD_LZ4COMPRESS
2035
+ compressedfilesize = FIO_compressLz4Frame(ress, srcFileName, fileSize, compressionLevel, prefs->checksumFlag, &readsize);
2036
+ #else
2037
+ (void)compressionLevel;
2038
+ EXM_THROW(20, "zstd: %s: file cannot be compressed as lz4 (zstd compiled without ZSTD_LZ4COMPRESS) -- ignored \n",
2039
+ srcFileName);
2040
+ #endif
2041
+ break;
2042
+ }
2043
+
2044
+ /* Status */
2045
+ fCtx->totalBytesInput += (size_t)readsize;
2046
+ fCtx->totalBytesOutput += (size_t)compressedfilesize;
2047
+ DISPLAY_PROGRESS("\r%79s\r", "");
2048
+ if (FIO_shouldDisplayFileSummary(fCtx)) {
2049
+ UTIL_HumanReadableSize_t hr_isize = UTIL_makeHumanReadableSize((U64) readsize);
2050
+ UTIL_HumanReadableSize_t hr_osize = UTIL_makeHumanReadableSize((U64) compressedfilesize);
2051
+ if (readsize == 0) {
2052
+ DISPLAY_SUMMARY("%-20s : (%6.*f%s => %6.*f%s, %s) \n",
2053
+ srcFileName,
2054
+ hr_isize.precision, hr_isize.value, hr_isize.suffix,
2055
+ hr_osize.precision, hr_osize.value, hr_osize.suffix,
2056
+ dstFileName);
2057
+ } else {
2058
+ DISPLAY_SUMMARY("%-20s :%6.2f%% (%6.*f%s => %6.*f%s, %s) \n",
2059
+ srcFileName,
2060
+ (double)compressedfilesize / (double)readsize * 100,
2061
+ hr_isize.precision, hr_isize.value, hr_isize.suffix,
2062
+ hr_osize.precision, hr_osize.value, hr_osize.suffix,
2063
+ dstFileName);
2064
+ }
2065
+ }
2066
+
2067
+ /* Elapsed Time and CPU Load */
2068
+ { clock_t const cpuEnd = clock();
2069
+ double const cpuLoad_s = (double)(cpuEnd - cpuStart) / CLOCKS_PER_SEC;
2070
+ U64 const timeLength_ns = UTIL_clockSpanNano(timeStart);
2071
+ double const timeLength_s = (double)timeLength_ns / 1000000000;
2072
+ double const cpuLoad_pct = (cpuLoad_s / timeLength_s) * 100;
2073
+ DISPLAYLEVEL(4, "%-20s : Completed in %.2f sec (cpu load : %.0f%%)\n",
2074
+ srcFileName, timeLength_s, cpuLoad_pct);
2075
+ }
2076
+ return 0;
2077
+ }
2078
+
2079
+
2080
+ /*! FIO_compressFilename_dstFile() :
2081
+ * open dstFileName, or pass-through if ress.file != NULL,
2082
+ * then start compression with FIO_compressFilename_internal().
2083
+ * Manages source removal (--rm) and file permissions transfer.
2084
+ * note : ress.srcFile must be != NULL,
2085
+ * so reach this function through FIO_compressFilename_srcFile().
2086
+ * @return : 0 : compression completed correctly,
2087
+ * 1 : pb
2088
+ */
2089
+ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
2090
+ FIO_prefs_t* const prefs,
2091
+ cRess_t* ress,
2092
+ const char* dstFileName,
2093
+ const char* srcFileName,
2094
+ const stat_t* srcFileStat,
2095
+ int compressionLevel)
2096
+ {
2097
+ int closeDstFile = 0;
2098
+ int result;
2099
+ int transferStat = 0;
2100
+ int dstFd = -1;
2101
+
2102
+ if (ress->io.dstFile == NULL) {
2103
+ int dstFileInitialPermissions = DEFAULT_FILE_PERMISSIONS;
2104
+ if ( strcmp (srcFileName, stdinmark)
2105
+ && strcmp (dstFileName, stdoutmark)
2106
+ && UTIL_isRegularFileStat(srcFileStat) ) {
2107
+ transferStat = 1;
2108
+ dstFileInitialPermissions = TEMPORARY_FILE_PERMISSIONS;
2109
+ }
2110
+
2111
+ closeDstFile = 1;
2112
+ DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s \n", dstFileName);
2113
+ {
2114
+ FILE *dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFileInitialPermissions);
2115
+ if (dstFile==NULL) return 1; /* could not open dstFileName */
2116
+ dstFd = fileno(dstFile);
2117
+ FIO_SyncCompressIO_setDst(&ress->io, dstFile);
2118
+ }
2119
+ /* Must only be added after FIO_openDstFile() succeeds. */
2120
+ addHandler(dstFileName);
2121
+ }
2122
+
2123
+ result = FIO_compressFilename_internal(fCtx, prefs, ress, dstFileName, srcFileName, compressionLevel);
2124
+
2125
+ if (closeDstFile) {
2126
+ clearHandler();
2127
+
2128
+ if (transferStat) {
2129
+ UTIL_setFDStat(dstFd, dstFileName, srcFileStat);
2130
+ }
2131
+
2132
+ DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: closing dst: %s \n", dstFileName);
2133
+ if (FIO_SyncCompressIO_closeDst(&ress->io)) { /* error closing file */
2134
+ DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno));
2135
+ result=1;
2136
+ }
2137
+
2138
+ if (transferStat) {
2139
+ UTIL_utime(dstFileName, srcFileStat);
2140
+ }
2141
+
2142
+ if ( (result != 0)
2143
+ && strcmp(dstFileName, stdoutmark) ) {
2144
+ FIO_removeFile(dstFileName);
2145
+ }
2146
+ }
2147
+
2148
+ return result;
2149
+ }
2150
+
2151
+ /* List used to compare file extensions (used with --exclude-compressed flag)
2152
+ * Different from the suffixList and should only apply to ZSTD compress operationResult
2153
+ */
2154
+ static const char *compressedFileExtensions[] = {
2155
+ ZSTD_EXTENSION,
2156
+ TZSTD_EXTENSION,
2157
+ GZ_EXTENSION,
2158
+ TGZ_EXTENSION,
2159
+ LZMA_EXTENSION,
2160
+ XZ_EXTENSION,
2161
+ TXZ_EXTENSION,
2162
+ LZ4_EXTENSION,
2163
+ TLZ4_EXTENSION,
2164
+ ".7z",
2165
+ ".aa3",
2166
+ ".aac",
2167
+ ".aar",
2168
+ ".ace",
2169
+ ".alac",
2170
+ ".ape",
2171
+ ".apk",
2172
+ ".apng",
2173
+ ".arc",
2174
+ ".archive",
2175
+ ".arj",
2176
+ ".ark",
2177
+ ".asf",
2178
+ ".avi",
2179
+ ".avif",
2180
+ ".ba",
2181
+ ".br",
2182
+ ".bz2",
2183
+ ".cab",
2184
+ ".cdx",
2185
+ ".chm",
2186
+ ".cr2",
2187
+ ".divx",
2188
+ ".dmg",
2189
+ ".dng",
2190
+ ".docm",
2191
+ ".docx",
2192
+ ".dotm",
2193
+ ".dotx",
2194
+ ".dsft",
2195
+ ".ear",
2196
+ ".eftx",
2197
+ ".emz",
2198
+ ".eot",
2199
+ ".epub",
2200
+ ".f4v",
2201
+ ".flac",
2202
+ ".flv",
2203
+ ".gho",
2204
+ ".gif",
2205
+ ".gifv",
2206
+ ".gnp",
2207
+ ".iso",
2208
+ ".jar",
2209
+ ".jpeg",
2210
+ ".jpg",
2211
+ ".jxl",
2212
+ ".lz",
2213
+ ".lzh",
2214
+ ".m4a",
2215
+ ".m4v",
2216
+ ".mkv",
2217
+ ".mov",
2218
+ ".mp2",
2219
+ ".mp3",
2220
+ ".mp4",
2221
+ ".mpa",
2222
+ ".mpc",
2223
+ ".mpe",
2224
+ ".mpeg",
2225
+ ".mpg",
2226
+ ".mpl",
2227
+ ".mpv",
2228
+ ".msi",
2229
+ ".odp",
2230
+ ".ods",
2231
+ ".odt",
2232
+ ".ogg",
2233
+ ".ogv",
2234
+ ".otp",
2235
+ ".ots",
2236
+ ".ott",
2237
+ ".pea",
2238
+ ".png",
2239
+ ".pptx",
2240
+ ".qt",
2241
+ ".rar",
2242
+ ".s7z",
2243
+ ".sfx",
2244
+ ".sit",
2245
+ ".sitx",
2246
+ ".sqx",
2247
+ ".svgz",
2248
+ ".swf",
2249
+ ".tbz2",
2250
+ ".tib",
2251
+ ".tlz",
2252
+ ".vob",
2253
+ ".war",
2254
+ ".webm",
2255
+ ".webp",
2256
+ ".wma",
2257
+ ".wmv",
2258
+ ".woff",
2259
+ ".woff2",
2260
+ ".wvl",
2261
+ ".xlsx",
2262
+ ".xpi",
2263
+ ".xps",
2264
+ ".zip",
2265
+ ".zipx",
2266
+ ".zoo",
2267
+ ".zpaq",
2268
+ NULL
2269
+ };
2270
+
2271
+ /*! FIO_compressFilename_srcFile() :
2272
+ * @return : 0 : compression completed correctly,
2273
+ * 1 : missing or pb opening srcFileName
2274
+ */
2275
+ static int
2276
+ FIO_compressFilename_srcFile(FIO_ctx_t* const fCtx,
2277
+ FIO_prefs_t* const prefs,
2278
+ cRess_t* ress,
2279
+ const char* dstFileName,
2280
+ const char* srcFileName,
2281
+ int compressionLevel)
2282
+ {
2283
+ int result;
2284
+ FILE* srcFile;
2285
+ stat_t srcFileStat;
2286
+ U64 fileSize = UTIL_FILESIZE_UNKNOWN;
2287
+ DISPLAYLEVEL(6, "FIO_compressFilename_srcFile: %s \n", srcFileName);
2288
+
2289
+ if (strcmp(srcFileName, stdinmark)) {
2290
+ if (UTIL_stat(srcFileName, &srcFileStat)) {
2291
+ /* failure to stat at all is handled during opening */
2292
+
2293
+ /* ensure src is not a directory */
2294
+ if (UTIL_isDirectoryStat(&srcFileStat)) {
2295
+ DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
2296
+ return 1;
2297
+ }
2298
+
2299
+ /* ensure src is not the same as dict (if present) */
2300
+ if (ress->dictFileName != NULL && UTIL_isSameFileStat(srcFileName, ress->dictFileName, &srcFileStat, &ress->dictFileStat)) {
2301
+ DISPLAYLEVEL(1, "zstd: cannot use %s as an input file and dictionary \n", srcFileName);
2302
+ return 1;
2303
+ }
2304
+ }
2305
+ }
2306
+
2307
+ /* Check if "srcFile" is compressed. Only done if --exclude-compressed flag is used
2308
+ * YES => ZSTD will skip compression of the file and will return 0.
2309
+ * NO => ZSTD will resume with compress operation.
2310
+ */
2311
+ if (prefs->excludeCompressedFiles == 1 && UTIL_isCompressedFile(srcFileName, compressedFileExtensions)) {
2312
+ DISPLAYLEVEL(4, "File is already compressed : %s \n", srcFileName);
2313
+ return 0;
2314
+ }
2315
+
2316
+ srcFile = FIO_openSrcFile(prefs, srcFileName, &srcFileStat);
2317
+ if (srcFile == NULL) return 1; /* srcFile could not be opened */
2318
+
2319
+ if (strcmp(srcFileName, stdinmark)) /* Stdin doesn't have stats */
2320
+ fileSize = UTIL_getFileSizeStat(&srcFileStat);
2321
+ (void)fileSize;
2322
+
2323
+ FIO_SyncCompressIO_setSrc(&ress->io, srcFile);
2324
+ result = FIO_compressFilename_dstFile(
2325
+ fCtx, prefs, ress,
2326
+ dstFileName, srcFileName,
2327
+ &srcFileStat, compressionLevel);
2328
+ FIO_SyncCompressIO_clearSrc(&ress->io);
2329
+
2330
+ if (srcFile != NULL && fclose(srcFile)) {
2331
+ DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno));
2332
+ return 1;
2333
+ }
2334
+
2335
+ if ( prefs->removeSrcFile /* --rm */
2336
+ && result == 0 /* success */
2337
+ && strcmp(srcFileName, stdinmark) /* exception : don't erase stdin */
2338
+ ) {
2339
+ /* We must clear the handler, since after this point calling it would
2340
+ * delete both the source and destination files.
2341
+ */
2342
+ clearHandler();
2343
+ if (FIO_removeFile(srcFileName))
2344
+ EXM_THROW(1, "zstd: %s: %s", srcFileName, strerror(errno));
2345
+ }
2346
+ return result;
2347
+ }
2348
+
2349
+ static const char*
2350
+ checked_index(const char* options[], size_t length, size_t index) {
2351
+ assert(index < length);
2352
+ /* Necessary to avoid warnings since -O3 will omit the above `assert` */
2353
+ (void) length;
2354
+ return options[index];
2355
+ }
2356
+
2357
+ #define INDEX(options, index) checked_index((options), sizeof(options) / sizeof(char*), (size_t)(index))
2358
+
2359
+ void FIO_displayCompressionParameters(const FIO_prefs_t* prefs)
2360
+ {
2361
+ static const char* formatOptions[5] = {ZSTD_EXTENSION, GZ_EXTENSION, XZ_EXTENSION,
2362
+ LZMA_EXTENSION, LZ4_EXTENSION};
2363
+ static const char* sparseOptions[3] = {" --no-sparse", "", " --sparse"};
2364
+ static const char* checkSumOptions[3] = {" --no-check", "", " --check"};
2365
+ static const char* rowMatchFinderOptions[3] = {"", " --no-row-match-finder", " --row-match-finder"};
2366
+ static const char* compressLiteralsOptions[3] = {"", " --compress-literals", " --no-compress-literals"};
2367
+
2368
+ assert(g_display_prefs.displayLevel >= 4);
2369
+
2370
+ DISPLAY("--format=%s", formatOptions[prefs->compressionType]);
2371
+ DISPLAY("%s", INDEX(sparseOptions, prefs->sparseFileSupport));
2372
+ DISPLAY("%s", prefs->dictIDFlag ? "" : " --no-dictID");
2373
+ DISPLAY("%s", INDEX(checkSumOptions, prefs->checksumFlag));
2374
+ DISPLAY(" --jobsize=%d", prefs->jobSize);
2375
+ if (prefs->adaptiveMode)
2376
+ DISPLAY(" --adapt=min=%d,max=%d", prefs->minAdaptLevel, prefs->maxAdaptLevel);
2377
+ DISPLAY("%s", INDEX(rowMatchFinderOptions, prefs->useRowMatchFinder));
2378
+ DISPLAY("%s", prefs->rsyncable ? " --rsyncable" : "");
2379
+ if (prefs->streamSrcSize)
2380
+ DISPLAY(" --stream-size=%u", (unsigned) prefs->streamSrcSize);
2381
+ if (prefs->srcSizeHint)
2382
+ DISPLAY(" --size-hint=%d", prefs->srcSizeHint);
2383
+ if (prefs->targetCBlockSize)
2384
+ DISPLAY(" --target-compressed-block-size=%u", (unsigned) prefs->targetCBlockSize);
2385
+ DISPLAY("%s", INDEX(compressLiteralsOptions, prefs->literalCompressionMode));
2386
+ DISPLAY(" --memory=%u", prefs->memLimit ? prefs->memLimit : 128 MB);
2387
+ DISPLAY(" --threads=%d", prefs->nbWorkers);
2388
+ DISPLAY("%s", prefs->excludeCompressedFiles ? " --exclude-compressed" : "");
2389
+ DISPLAY(" --%scontent-size", prefs->contentSize ? "" : "no-");
2390
+ DISPLAY("\n");
2391
+ }
2392
+
2393
+ #undef INDEX
2394
+
2395
+ int FIO_compressFilename(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs, const char* dstFileName,
2396
+ const char* srcFileName, const char* dictFileName,
2397
+ int compressionLevel, ZSTD_compressionParameters comprParams)
2398
+ {
2399
+ cRess_t ress = FIO_createCResources(prefs, dictFileName, UTIL_getFileSize(srcFileName), compressionLevel, comprParams);
2400
+ int const result = FIO_compressFilename_srcFile(fCtx, prefs, &ress, dstFileName, srcFileName, compressionLevel);
2401
+
2402
+ #define DISPLAY_LEVEL_DEFAULT 2
2403
+
2404
+ FIO_freeCResources(&ress);
2405
+ return result;
2406
+ }
2407
+
2408
+ /* FIO_determineCompressedName() :
2409
+ * create a destination filename for compressed srcFileName.
2410
+ * @return a pointer to it.
2411
+ * This function never returns an error (it may abort() in case of pb)
2412
+ */
2413
+ static const char*
2414
+ FIO_determineCompressedName(const char* srcFileName, const char* outDirName, const char* suffix)
2415
+ {
2416
+ static size_t dfnbCapacity = 0;
2417
+ static char* dstFileNameBuffer = NULL; /* using static allocation : this function cannot be multi-threaded */
2418
+ char* outDirFilename = NULL;
2419
+ size_t sfnSize = strlen(srcFileName);
2420
+ size_t const srcSuffixLen = strlen(suffix);
2421
+
2422
+ if(!strcmp(srcFileName, stdinmark)) {
2423
+ return stdoutmark;
2424
+ }
2425
+
2426
+ if (outDirName) {
2427
+ outDirFilename = FIO_createFilename_fromOutDir(srcFileName, outDirName, srcSuffixLen);
2428
+ sfnSize = strlen(outDirFilename);
2429
+ assert(outDirFilename != NULL);
2430
+ }
2431
+
2432
+ if (dfnbCapacity <= sfnSize+srcSuffixLen+1) {
2433
+ /* resize buffer for dstName */
2434
+ free(dstFileNameBuffer);
2435
+ dfnbCapacity = sfnSize + srcSuffixLen + 30;
2436
+ dstFileNameBuffer = (char*)malloc(dfnbCapacity);
2437
+ if (!dstFileNameBuffer) {
2438
+ EXM_THROW(30, "zstd: %s", strerror(errno));
2439
+ }
2440
+ }
2441
+ assert(dstFileNameBuffer != NULL);
2442
+
2443
+ if (outDirFilename) {
2444
+ memcpy(dstFileNameBuffer, outDirFilename, sfnSize);
2445
+ free(outDirFilename);
2446
+ } else {
2447
+ memcpy(dstFileNameBuffer, srcFileName, sfnSize);
2448
+ }
2449
+ memcpy(dstFileNameBuffer+sfnSize, suffix, srcSuffixLen+1 /* Include terminating null */);
2450
+ return dstFileNameBuffer;
2451
+ }
2452
+
2453
+ static unsigned long long FIO_getLargestFileSize(const char** inFileNames, unsigned nbFiles)
2454
+ {
2455
+ size_t i;
2456
+ unsigned long long fileSize, maxFileSize = 0;
2457
+ for (i = 0; i < nbFiles; i++) {
2458
+ fileSize = UTIL_getFileSize(inFileNames[i]);
2459
+ maxFileSize = fileSize > maxFileSize ? fileSize : maxFileSize;
2460
+ }
2461
+ return maxFileSize;
2462
+ }
2463
+
2464
+ /* FIO_compressMultipleFilenames() :
2465
+ * compress nbFiles files
2466
+ * into either one destination (outFileName),
2467
+ * or into one file each (outFileName == NULL, but suffix != NULL),
2468
+ * or into a destination folder (specified with -O)
2469
+ */
2470
+ int FIO_compressMultipleFilenames(FIO_ctx_t* const fCtx,
2471
+ FIO_prefs_t* const prefs,
2472
+ const char** inFileNamesTable,
2473
+ const char* outMirroredRootDirName,
2474
+ const char* outDirName,
2475
+ const char* outFileName, const char* suffix,
2476
+ const char* dictFileName, int compressionLevel,
2477
+ ZSTD_compressionParameters comprParams)
2478
+ {
2479
+ int status;
2480
+ int error = 0;
2481
+ cRess_t ress = FIO_createCResources(prefs, dictFileName,
2482
+ FIO_getLargestFileSize(inFileNamesTable, (unsigned)fCtx->nbFilesTotal),
2483
+ compressionLevel, comprParams);
2484
+
2485
+ /* init */
2486
+ assert(outFileName != NULL || suffix != NULL);
2487
+ if (outFileName != NULL) { /* output into a single destination (stdout typically) */
2488
+ FILE *dstFile;
2489
+ if (FIO_multiFilesConcatWarning(fCtx, prefs, outFileName, 1 /* displayLevelCutoff */)) {
2490
+ FIO_freeCResources(&ress);
2491
+ return 1;
2492
+ }
2493
+ dstFile = FIO_openDstFile(fCtx, prefs, NULL, outFileName, DEFAULT_FILE_PERMISSIONS);
2494
+ if (dstFile == NULL) { /* could not open outFileName */
2495
+ error = 1;
2496
+ } else {
2497
+ FIO_SyncCompressIO_setDst(&ress.io, dstFile);
2498
+ for (; fCtx->currFileIdx < fCtx->nbFilesTotal; ++fCtx->currFileIdx) {
2499
+ status = FIO_compressFilename_srcFile(fCtx, prefs, &ress, outFileName, inFileNamesTable[fCtx->currFileIdx], compressionLevel);
2500
+ if (!status) fCtx->nbFilesProcessed++;
2501
+ error |= status;
2502
+ }
2503
+ if (FIO_SyncCompressIO_closeDst(&ress.io))
2504
+ EXM_THROW(29, "Write error (%s) : cannot properly close %s",
2505
+ strerror(errno), outFileName);
2506
+ }
2507
+ } else {
2508
+ if (outMirroredRootDirName)
2509
+ UTIL_mirrorSourceFilesDirectories(inFileNamesTable, (unsigned)fCtx->nbFilesTotal, outMirroredRootDirName);
2510
+
2511
+ for (; fCtx->currFileIdx < fCtx->nbFilesTotal; ++fCtx->currFileIdx) {
2512
+ const char* const srcFileName = inFileNamesTable[fCtx->currFileIdx];
2513
+ const char* dstFileName = NULL;
2514
+ if (outMirroredRootDirName) {
2515
+ char* validMirroredDirName = UTIL_createMirroredDestDirName(srcFileName, outMirroredRootDirName);
2516
+ if (validMirroredDirName) {
2517
+ dstFileName = FIO_determineCompressedName(srcFileName, validMirroredDirName, suffix);
2518
+ free(validMirroredDirName);
2519
+ } else {
2520
+ DISPLAYLEVEL(2, "zstd: --output-dir-mirror cannot compress '%s' into '%s' \n", srcFileName, outMirroredRootDirName);
2521
+ error=1;
2522
+ continue;
2523
+ }
2524
+ } else {
2525
+ dstFileName = FIO_determineCompressedName(srcFileName, outDirName, suffix); /* cannot fail */
2526
+ }
2527
+ status = FIO_compressFilename_srcFile(fCtx, prefs, &ress, dstFileName, srcFileName, compressionLevel);
2528
+ if (!status) fCtx->nbFilesProcessed++;
2529
+ error |= status;
2530
+ }
2531
+
2532
+ if (outDirName)
2533
+ FIO_checkFilenameCollisions(inFileNamesTable , (unsigned)fCtx->nbFilesTotal);
2534
+ }
2535
+
2536
+ if (FIO_shouldDisplayMultipleFileSummary(fCtx)) {
2537
+ UTIL_HumanReadableSize_t hr_isize = UTIL_makeHumanReadableSize((U64) fCtx->totalBytesInput);
2538
+ UTIL_HumanReadableSize_t hr_osize = UTIL_makeHumanReadableSize((U64) fCtx->totalBytesOutput);
2539
+
2540
+ DISPLAY_PROGRESS("\r%79s\r", "");
2541
+ if (fCtx->totalBytesInput == 0) {
2542
+ DISPLAY_SUMMARY("%3d files compressed : (%6.*f%4s => %6.*f%4s)\n",
2543
+ fCtx->nbFilesProcessed,
2544
+ hr_isize.precision, hr_isize.value, hr_isize.suffix,
2545
+ hr_osize.precision, hr_osize.value, hr_osize.suffix);
2546
+ } else {
2547
+ DISPLAY_SUMMARY("%3d files compressed : %.2f%% (%6.*f%4s => %6.*f%4s)\n",
2548
+ fCtx->nbFilesProcessed,
2549
+ (double)fCtx->totalBytesOutput/((double)fCtx->totalBytesInput)*100,
2550
+ hr_isize.precision, hr_isize.value, hr_isize.suffix,
2551
+ hr_osize.precision, hr_osize.value, hr_osize.suffix);
2552
+ }
2553
+ }
2554
+
2555
+ FIO_freeCResources(&ress);
2556
+ return error;
2557
+ }
2558
+
2559
+ #endif /* #ifndef ZSTD_NOCOMPRESS */
2560
+
2561
+
2562
+
2563
+ #ifndef ZSTD_NODECOMPRESS
2564
+
2565
+ /* **************************************************************************
2566
+ * Decompression
2567
+ ***************************************************************************/
2568
+ typedef struct {
2569
+ FIO_Dict_t dict;
2570
+ ZSTD_DStream* dctx;
2571
+ WritePoolCtx_t *writeCtx;
2572
+ ReadPoolCtx_t *readCtx;
2573
+ } dRess_t;
2574
+
2575
+ static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFileName)
2576
+ {
2577
+ int useMMap = prefs->mmapDict == ZSTD_ps_enable;
2578
+ int forceNoUseMMap = prefs->mmapDict == ZSTD_ps_disable;
2579
+ stat_t statbuf;
2580
+ dRess_t ress;
2581
+ memset(&statbuf, 0, sizeof(statbuf));
2582
+ memset(&ress, 0, sizeof(ress));
2583
+
2584
+ FIO_getDictFileStat(dictFileName, &statbuf);
2585
+
2586
+ if (prefs->patchFromMode){
2587
+ U64 const dictSize = UTIL_getFileSizeStat(&statbuf);
2588
+ useMMap |= dictSize > prefs->memLimit;
2589
+ FIO_adjustMemLimitForPatchFromMode(prefs, dictSize, 0 /* just use the dict size */);
2590
+ }
2591
+
2592
+ /* Allocation */
2593
+ ress.dctx = ZSTD_createDStream();
2594
+ if (ress.dctx==NULL)
2595
+ EXM_THROW(60, "Error: %s : can't create ZSTD_DStream", strerror(errno));
2596
+ CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, prefs->memLimit) );
2597
+ CHECK( ZSTD_DCtx_setParameter(ress.dctx, ZSTD_d_forceIgnoreChecksum, !prefs->checksumFlag));
2598
+
2599
+ /* dictionary */
2600
+ {
2601
+ FIO_dictBufferType_t dictBufferType = (useMMap && !forceNoUseMMap) ? FIO_mmapDict : FIO_mallocDict;
2602
+ FIO_initDict(&ress.dict, dictFileName, prefs, &statbuf, dictBufferType);
2603
+
2604
+ CHECK(ZSTD_DCtx_reset(ress.dctx, ZSTD_reset_session_only) );
2605
+
2606
+ if (prefs->patchFromMode){
2607
+ CHECK(ZSTD_DCtx_refPrefix(ress.dctx, ress.dict.dictBuffer, ress.dict.dictBufferSize));
2608
+ } else {
2609
+ CHECK(ZSTD_DCtx_loadDictionary_byReference(ress.dctx, ress.dict.dictBuffer, ress.dict.dictBufferSize));
2610
+ }
2611
+ }
2612
+
2613
+ ress.writeCtx = AIO_WritePool_create(prefs, ZSTD_DStreamOutSize());
2614
+ ress.readCtx = AIO_ReadPool_create(prefs, ZSTD_DStreamInSize());
2615
+ return ress;
2616
+ }
2617
+
2618
+ static void FIO_freeDResources(dRess_t ress)
2619
+ {
2620
+ FIO_freeDict(&(ress.dict));
2621
+ CHECK( ZSTD_freeDStream(ress.dctx) );
2622
+ AIO_WritePool_free(ress.writeCtx);
2623
+ AIO_ReadPool_free(ress.readCtx);
2624
+ }
2625
+
2626
+ /* FIO_passThrough() : just copy input into output, for compatibility with gzip -df mode
2627
+ * @return : 0 (no error) */
2628
+ static int FIO_passThrough(dRess_t *ress)
2629
+ {
2630
+ size_t const blockSize = MIN(MIN(64 KB, ZSTD_DStreamInSize()), ZSTD_DStreamOutSize());
2631
+ IOJob_t *writeJob = AIO_WritePool_acquireJob(ress->writeCtx);
2632
+ AIO_ReadPool_fillBuffer(ress->readCtx, blockSize);
2633
+
2634
+ while(ress->readCtx->srcBufferLoaded) {
2635
+ size_t writeSize;
2636
+ writeSize = MIN(blockSize, ress->readCtx->srcBufferLoaded);
2637
+ assert(writeSize <= writeJob->bufferSize);
2638
+ memcpy(writeJob->buffer, ress->readCtx->srcBuffer, writeSize);
2639
+ writeJob->usedBufferSize = writeSize;
2640
+ AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
2641
+ AIO_ReadPool_consumeBytes(ress->readCtx, writeSize);
2642
+ AIO_ReadPool_fillBuffer(ress->readCtx, blockSize);
2643
+ }
2644
+ assert(ress->readCtx->reachedEof);
2645
+ AIO_WritePool_releaseIoJob(writeJob);
2646
+ AIO_WritePool_sparseWriteEnd(ress->writeCtx);
2647
+ return 0;
2648
+ }
2649
+
2650
+ /* FIO_zstdErrorHelp() :
2651
+ * detailed error message when requested window size is too large */
2652
+ static void
2653
+ FIO_zstdErrorHelp(const FIO_prefs_t* const prefs,
2654
+ const dRess_t* ress,
2655
+ size_t err,
2656
+ const char* srcFileName)
2657
+ {
2658
+ ZSTD_FrameHeader header;
2659
+
2660
+ /* Help message only for one specific error */
2661
+ if (ZSTD_getErrorCode(err) != ZSTD_error_frameParameter_windowTooLarge)
2662
+ return;
2663
+
2664
+ /* Try to decode the frame header */
2665
+ err = ZSTD_getFrameHeader(&header, ress->readCtx->srcBuffer, ress->readCtx->srcBufferLoaded);
2666
+ if (err == 0) {
2667
+ unsigned long long const windowSize = header.windowSize;
2668
+ unsigned const windowLog = FIO_highbit64(windowSize) + ((windowSize & (windowSize - 1)) != 0);
2669
+ assert(prefs->memLimit > 0);
2670
+ DISPLAYLEVEL(1, "%s : Window size larger than maximum : %llu > %u \n",
2671
+ srcFileName, windowSize, prefs->memLimit);
2672
+ if (windowLog <= ZSTD_WINDOWLOG_MAX) {
2673
+ unsigned const windowMB = (unsigned)((windowSize >> 20) + ((windowSize & ((1 MB) - 1)) != 0));
2674
+ assert(windowSize < (U64)(1ULL << 52)); /* ensure now overflow for windowMB */
2675
+ DISPLAYLEVEL(1, "%s : Use --long=%u or --memory=%uMB \n",
2676
+ srcFileName, windowLog, windowMB);
2677
+ return;
2678
+ } }
2679
+ DISPLAYLEVEL(1, "%s : Window log larger than ZSTD_WINDOWLOG_MAX=%u; not supported \n",
2680
+ srcFileName, ZSTD_WINDOWLOG_MAX);
2681
+ }
2682
+
2683
+ /** FIO_decompressFrame() :
2684
+ * @return : size of decoded zstd frame, or an error code
2685
+ */
2686
+ #define FIO_ERROR_FRAME_DECODING ((unsigned long long)(-2))
2687
+ static unsigned long long
2688
+ FIO_decompressZstdFrame(FIO_ctx_t* const fCtx, dRess_t* ress,
2689
+ const FIO_prefs_t* const prefs,
2690
+ const char* srcFileName,
2691
+ U64 alreadyDecoded) /* for multi-frames streams */
2692
+ {
2693
+ U64 frameSize = 0;
2694
+ const char* srcFName20 = srcFileName;
2695
+ IOJob_t* writeJob = AIO_WritePool_acquireJob(ress->writeCtx);
2696
+ assert(writeJob);
2697
+
2698
+ /* display last 20 characters only when not --verbose */
2699
+ { size_t const srcFileLength = strlen(srcFileName);
2700
+ if ((srcFileLength>20) && (g_display_prefs.displayLevel<3))
2701
+ srcFName20 += srcFileLength-20;
2702
+ }
2703
+
2704
+ ZSTD_DCtx_reset(ress->dctx, ZSTD_reset_session_only);
2705
+
2706
+ /* Header loading : ensures ZSTD_getFrameHeader() will succeed */
2707
+ AIO_ReadPool_fillBuffer(ress->readCtx, ZSTD_FRAMEHEADERSIZE_MAX);
2708
+
2709
+ /* Main decompression Loop */
2710
+ while (1) {
2711
+ ZSTD_inBuffer inBuff = setInBuffer( ress->readCtx->srcBuffer, ress->readCtx->srcBufferLoaded, 0 );
2712
+ ZSTD_outBuffer outBuff= setOutBuffer( writeJob->buffer, writeJob->bufferSize, 0 );
2713
+ size_t const readSizeHint = ZSTD_decompressStream(ress->dctx, &outBuff, &inBuff);
2714
+ UTIL_HumanReadableSize_t const hrs = UTIL_makeHumanReadableSize(alreadyDecoded+frameSize);
2715
+ if (ZSTD_isError(readSizeHint)) {
2716
+ DISPLAYLEVEL(1, "%s : Decoding error (36) : %s \n",
2717
+ srcFileName, ZSTD_getErrorName(readSizeHint));
2718
+ FIO_zstdErrorHelp(prefs, ress, readSizeHint, srcFileName);
2719
+ AIO_WritePool_releaseIoJob(writeJob);
2720
+ return FIO_ERROR_FRAME_DECODING;
2721
+ }
2722
+
2723
+ /* Write block */
2724
+ writeJob->usedBufferSize = outBuff.pos;
2725
+ AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
2726
+ frameSize += outBuff.pos;
2727
+ if (fCtx->nbFilesTotal > 1) {
2728
+ DISPLAYUPDATE_PROGRESS(
2729
+ "\rDecompress: %2u/%2u files. Current: %s : %.*f%s... ",
2730
+ fCtx->currFileIdx+1, fCtx->nbFilesTotal, srcFName20, hrs.precision, hrs.value, hrs.suffix);
2731
+ } else {
2732
+ DISPLAYUPDATE_PROGRESS("\r%-20.20s : %.*f%s... ",
2733
+ srcFName20, hrs.precision, hrs.value, hrs.suffix);
2734
+ }
2735
+
2736
+ AIO_ReadPool_consumeBytes(ress->readCtx, inBuff.pos);
2737
+
2738
+ if (readSizeHint == 0) break; /* end of frame */
2739
+
2740
+ /* Fill input buffer */
2741
+ { size_t const toDecode = MIN(readSizeHint, ZSTD_DStreamInSize()); /* support large skippable frames */
2742
+ if (ress->readCtx->srcBufferLoaded < toDecode) {
2743
+ size_t const readSize = AIO_ReadPool_fillBuffer(ress->readCtx, toDecode);
2744
+ if (readSize==0) {
2745
+ DISPLAYLEVEL(1, "%s : Read error (39) : premature end \n",
2746
+ srcFileName);
2747
+ AIO_WritePool_releaseIoJob(writeJob);
2748
+ return FIO_ERROR_FRAME_DECODING;
2749
+ }
2750
+ } } }
2751
+
2752
+ AIO_WritePool_releaseIoJob(writeJob);
2753
+ AIO_WritePool_sparseWriteEnd(ress->writeCtx);
2754
+
2755
+ return frameSize;
2756
+ }
2757
+
2758
+
2759
+ #ifdef ZSTD_GZDECOMPRESS
2760
+ static unsigned long long
2761
+ FIO_decompressGzFrame(dRess_t* ress, const char* srcFileName)
2762
+ {
2763
+ unsigned long long outFileSize = 0;
2764
+ z_stream strm;
2765
+ int flush = Z_NO_FLUSH;
2766
+ int decodingError = 0;
2767
+ IOJob_t *writeJob = NULL;
2768
+
2769
+ strm.zalloc = Z_NULL;
2770
+ strm.zfree = Z_NULL;
2771
+ strm.opaque = Z_NULL;
2772
+ strm.next_in = 0;
2773
+ strm.avail_in = 0;
2774
+ /* see https://www.zlib.net/manual.html */
2775
+ if (inflateInit2(&strm, 15 /* maxWindowLogSize */ + 16 /* gzip only */) != Z_OK)
2776
+ return FIO_ERROR_FRAME_DECODING;
2777
+
2778
+ writeJob = AIO_WritePool_acquireJob(ress->writeCtx);
2779
+ strm.next_out = (Bytef*)writeJob->buffer;
2780
+ strm.avail_out = (uInt)writeJob->bufferSize;
2781
+ strm.avail_in = (uInt)ress->readCtx->srcBufferLoaded;
2782
+ strm.next_in = (z_const unsigned char*)ress->readCtx->srcBuffer;
2783
+
2784
+ for ( ; ; ) {
2785
+ int ret;
2786
+ if (strm.avail_in == 0) {
2787
+ AIO_ReadPool_consumeAndRefill(ress->readCtx);
2788
+ if (ress->readCtx->srcBufferLoaded == 0) flush = Z_FINISH;
2789
+ strm.next_in = (z_const unsigned char*)ress->readCtx->srcBuffer;
2790
+ strm.avail_in = (uInt)ress->readCtx->srcBufferLoaded;
2791
+ }
2792
+ ret = inflate(&strm, flush);
2793
+ if (ret == Z_BUF_ERROR) {
2794
+ DISPLAYLEVEL(1, "zstd: %s: premature gz end \n", srcFileName);
2795
+ decodingError = 1; break;
2796
+ }
2797
+ if (ret != Z_OK && ret != Z_STREAM_END) {
2798
+ DISPLAYLEVEL(1, "zstd: %s: inflate error %d \n", srcFileName, ret);
2799
+ decodingError = 1; break;
2800
+ }
2801
+ { size_t const decompBytes = writeJob->bufferSize - strm.avail_out;
2802
+ if (decompBytes) {
2803
+ writeJob->usedBufferSize = decompBytes;
2804
+ AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
2805
+ outFileSize += decompBytes;
2806
+ strm.next_out = (Bytef*)writeJob->buffer;
2807
+ strm.avail_out = (uInt)writeJob->bufferSize;
2808
+ }
2809
+ }
2810
+ if (ret == Z_STREAM_END) break;
2811
+ }
2812
+
2813
+ AIO_ReadPool_consumeBytes(ress->readCtx, ress->readCtx->srcBufferLoaded - strm.avail_in);
2814
+
2815
+ if ( (inflateEnd(&strm) != Z_OK) /* release resources ; error detected */
2816
+ && (decodingError==0) ) {
2817
+ DISPLAYLEVEL(1, "zstd: %s: inflateEnd error \n", srcFileName);
2818
+ decodingError = 1;
2819
+ }
2820
+ AIO_WritePool_releaseIoJob(writeJob);
2821
+ AIO_WritePool_sparseWriteEnd(ress->writeCtx);
2822
+ return decodingError ? FIO_ERROR_FRAME_DECODING : outFileSize;
2823
+ }
2824
+ #endif
2825
+
2826
+ #ifdef ZSTD_LZMADECOMPRESS
2827
+ static unsigned long long
2828
+ FIO_decompressLzmaFrame(dRess_t* ress,
2829
+ const char* srcFileName, int plain_lzma)
2830
+ {
2831
+ unsigned long long outFileSize = 0;
2832
+ lzma_stream strm = LZMA_STREAM_INIT;
2833
+ lzma_action action = LZMA_RUN;
2834
+ lzma_ret initRet;
2835
+ int decodingError = 0;
2836
+ IOJob_t *writeJob = NULL;
2837
+
2838
+ strm.next_in = 0;
2839
+ strm.avail_in = 0;
2840
+ if (plain_lzma) {
2841
+ initRet = lzma_alone_decoder(&strm, UINT64_MAX); /* LZMA */
2842
+ } else {
2843
+ initRet = lzma_stream_decoder(&strm, UINT64_MAX, 0); /* XZ */
2844
+ }
2845
+
2846
+ if (initRet != LZMA_OK) {
2847
+ DISPLAYLEVEL(1, "zstd: %s: %s error %d \n",
2848
+ plain_lzma ? "lzma_alone_decoder" : "lzma_stream_decoder",
2849
+ srcFileName, initRet);
2850
+ return FIO_ERROR_FRAME_DECODING;
2851
+ }
2852
+
2853
+ writeJob = AIO_WritePool_acquireJob(ress->writeCtx);
2854
+ strm.next_out = (BYTE*)writeJob->buffer;
2855
+ strm.avail_out = writeJob->bufferSize;
2856
+ strm.next_in = (BYTE const*)ress->readCtx->srcBuffer;
2857
+ strm.avail_in = ress->readCtx->srcBufferLoaded;
2858
+
2859
+ for ( ; ; ) {
2860
+ lzma_ret ret;
2861
+ if (strm.avail_in == 0) {
2862
+ AIO_ReadPool_consumeAndRefill(ress->readCtx);
2863
+ if (ress->readCtx->srcBufferLoaded == 0) action = LZMA_FINISH;
2864
+ strm.next_in = (BYTE const*)ress->readCtx->srcBuffer;
2865
+ strm.avail_in = ress->readCtx->srcBufferLoaded;
2866
+ }
2867
+ ret = lzma_code(&strm, action);
2868
+
2869
+ if (ret == LZMA_BUF_ERROR) {
2870
+ DISPLAYLEVEL(1, "zstd: %s: premature lzma end \n", srcFileName);
2871
+ decodingError = 1; break;
2872
+ }
2873
+ if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
2874
+ DISPLAYLEVEL(1, "zstd: %s: lzma_code decoding error %d \n",
2875
+ srcFileName, ret);
2876
+ decodingError = 1; break;
2877
+ }
2878
+ { size_t const decompBytes = writeJob->bufferSize - strm.avail_out;
2879
+ if (decompBytes) {
2880
+ writeJob->usedBufferSize = decompBytes;
2881
+ AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
2882
+ outFileSize += decompBytes;
2883
+ strm.next_out = (BYTE*)writeJob->buffer;
2884
+ strm.avail_out = writeJob->bufferSize;
2885
+ } }
2886
+ if (ret == LZMA_STREAM_END) break;
2887
+ }
2888
+
2889
+ AIO_ReadPool_consumeBytes(ress->readCtx, ress->readCtx->srcBufferLoaded - strm.avail_in);
2890
+ lzma_end(&strm);
2891
+ AIO_WritePool_releaseIoJob(writeJob);
2892
+ AIO_WritePool_sparseWriteEnd(ress->writeCtx);
2893
+ return decodingError ? FIO_ERROR_FRAME_DECODING : outFileSize;
2894
+ }
2895
+ #endif
2896
+
2897
+ #ifdef ZSTD_LZ4DECOMPRESS
2898
+ static unsigned long long
2899
+ FIO_decompressLz4Frame(dRess_t* ress, const char* srcFileName)
2900
+ {
2901
+ unsigned long long filesize = 0;
2902
+ LZ4F_errorCode_t nextToLoad = 4;
2903
+ LZ4F_decompressionContext_t dCtx;
2904
+ LZ4F_errorCode_t const errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
2905
+ int decodingError = 0;
2906
+ IOJob_t *writeJob = NULL;
2907
+
2908
+ if (LZ4F_isError(errorCode)) {
2909
+ DISPLAYLEVEL(1, "zstd: failed to create lz4 decompression context \n");
2910
+ return FIO_ERROR_FRAME_DECODING;
2911
+ }
2912
+
2913
+ writeJob = AIO_WritePool_acquireJob(ress->writeCtx);
2914
+
2915
+ /* Main Loop */
2916
+ for (;nextToLoad;) {
2917
+ size_t pos = 0;
2918
+ size_t decodedBytes = writeJob->bufferSize;
2919
+ int fullBufferDecoded = 0;
2920
+
2921
+ /* Read input */
2922
+ AIO_ReadPool_fillBuffer(ress->readCtx, nextToLoad);
2923
+ if(!ress->readCtx->srcBufferLoaded) break; /* reached end of file */
2924
+
2925
+ while ((pos < ress->readCtx->srcBufferLoaded) || fullBufferDecoded) { /* still to read, or still to flush */
2926
+ /* Decode Input (at least partially) */
2927
+ size_t remaining = ress->readCtx->srcBufferLoaded - pos;
2928
+ decodedBytes = writeJob->bufferSize;
2929
+ nextToLoad = LZ4F_decompress(dCtx, writeJob->buffer, &decodedBytes, (char*)(ress->readCtx->srcBuffer)+pos,
2930
+ &remaining, NULL);
2931
+ if (LZ4F_isError(nextToLoad)) {
2932
+ DISPLAYLEVEL(1, "zstd: %s: lz4 decompression error : %s \n",
2933
+ srcFileName, LZ4F_getErrorName(nextToLoad));
2934
+ decodingError = 1; nextToLoad = 0; break;
2935
+ }
2936
+ pos += remaining;
2937
+ assert(pos <= ress->readCtx->srcBufferLoaded);
2938
+ fullBufferDecoded = decodedBytes == writeJob->bufferSize;
2939
+
2940
+ /* Write Block */
2941
+ if (decodedBytes) {
2942
+ UTIL_HumanReadableSize_t hrs;
2943
+ writeJob->usedBufferSize = decodedBytes;
2944
+ AIO_WritePool_enqueueAndReacquireWriteJob(&writeJob);
2945
+ filesize += decodedBytes;
2946
+ hrs = UTIL_makeHumanReadableSize(filesize);
2947
+ DISPLAYUPDATE_PROGRESS("\rDecompressed : %.*f%s ", hrs.precision, hrs.value, hrs.suffix);
2948
+ }
2949
+
2950
+ if (!nextToLoad) break;
2951
+ }
2952
+ AIO_ReadPool_consumeBytes(ress->readCtx, pos);
2953
+ }
2954
+ if (nextToLoad!=0) {
2955
+ DISPLAYLEVEL(1, "zstd: %s: unfinished lz4 stream \n", srcFileName);
2956
+ decodingError=1;
2957
+ }
2958
+
2959
+ LZ4F_freeDecompressionContext(dCtx);
2960
+ AIO_WritePool_releaseIoJob(writeJob);
2961
+ AIO_WritePool_sparseWriteEnd(ress->writeCtx);
2962
+
2963
+ return decodingError ? FIO_ERROR_FRAME_DECODING : filesize;
2964
+ }
2965
+ #endif
2966
+
2967
+
2968
+
2969
+ /** FIO_decompressFrames() :
2970
+ * Find and decode frames inside srcFile
2971
+ * srcFile presumed opened and valid
2972
+ * @return : 0 : OK
2973
+ * 1 : error
2974
+ */
2975
+ static int FIO_decompressFrames(FIO_ctx_t* const fCtx,
2976
+ dRess_t ress, const FIO_prefs_t* const prefs,
2977
+ const char* dstFileName, const char* srcFileName)
2978
+ {
2979
+ unsigned readSomething = 0;
2980
+ unsigned long long filesize = 0;
2981
+ int passThrough = prefs->passThrough;
2982
+
2983
+ if (passThrough == -1) {
2984
+ /* If pass-through mode is not explicitly enabled or disabled,
2985
+ * default to the legacy behavior of enabling it if we are writing
2986
+ * to stdout with the overwrite flag enabled.
2987
+ */
2988
+ passThrough = prefs->overwrite && !strcmp(dstFileName, stdoutmark);
2989
+ }
2990
+ assert(passThrough == 0 || passThrough == 1);
2991
+
2992
+ /* for each frame */
2993
+ for ( ; ; ) {
2994
+ /* check magic number -> version */
2995
+ size_t const toRead = 4;
2996
+ const BYTE* buf;
2997
+ AIO_ReadPool_fillBuffer(ress.readCtx, toRead);
2998
+ buf = (const BYTE*)ress.readCtx->srcBuffer;
2999
+ if (ress.readCtx->srcBufferLoaded==0) {
3000
+ if (readSomething==0) { /* srcFile is empty (which is invalid) */
3001
+ DISPLAYLEVEL(1, "zstd: %s: unexpected end of file \n", srcFileName);
3002
+ return 1;
3003
+ } /* else, just reached frame boundary */
3004
+ break; /* no more input */
3005
+ }
3006
+ readSomething = 1; /* there is at least 1 byte in srcFile */
3007
+ if (ress.readCtx->srcBufferLoaded < toRead) { /* not enough input to check magic number */
3008
+ if (passThrough) {
3009
+ return FIO_passThrough(&ress);
3010
+ }
3011
+ DISPLAYLEVEL(1, "zstd: %s: unknown header \n", srcFileName);
3012
+ return 1;
3013
+ }
3014
+ if (ZSTD_isFrame(buf, ress.readCtx->srcBufferLoaded)) {
3015
+ unsigned long long const frameSize = FIO_decompressZstdFrame(fCtx, &ress, prefs, srcFileName, filesize);
3016
+ if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;
3017
+ filesize += frameSize;
3018
+ } else if (buf[0] == 31 && buf[1] == 139) { /* gz magic number */
3019
+ #ifdef ZSTD_GZDECOMPRESS
3020
+ unsigned long long const frameSize = FIO_decompressGzFrame(&ress, srcFileName);
3021
+ if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;
3022
+ filesize += frameSize;
3023
+ #else
3024
+ DISPLAYLEVEL(1, "zstd: %s: gzip file cannot be uncompressed (zstd compiled without HAVE_ZLIB) -- ignored \n", srcFileName);
3025
+ return 1;
3026
+ #endif
3027
+ } else if ((buf[0] == 0xFD && buf[1] == 0x37) /* xz magic number */
3028
+ || (buf[0] == 0x5D && buf[1] == 0x00)) { /* lzma header (no magic number) */
3029
+ #ifdef ZSTD_LZMADECOMPRESS
3030
+ unsigned long long const frameSize = FIO_decompressLzmaFrame(&ress, srcFileName, buf[0] != 0xFD);
3031
+ if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;
3032
+ filesize += frameSize;
3033
+ #else
3034
+ DISPLAYLEVEL(1, "zstd: %s: xz/lzma file cannot be uncompressed (zstd compiled without HAVE_LZMA) -- ignored \n", srcFileName);
3035
+ return 1;
3036
+ #endif
3037
+ } else if (MEM_readLE32(buf) == LZ4_MAGICNUMBER) {
3038
+ #ifdef ZSTD_LZ4DECOMPRESS
3039
+ unsigned long long const frameSize = FIO_decompressLz4Frame(&ress, srcFileName);
3040
+ if (frameSize == FIO_ERROR_FRAME_DECODING) return 1;
3041
+ filesize += frameSize;
3042
+ #else
3043
+ DISPLAYLEVEL(1, "zstd: %s: lz4 file cannot be uncompressed (zstd compiled without HAVE_LZ4) -- ignored \n", srcFileName);
3044
+ return 1;
3045
+ #endif
3046
+ } else if (passThrough) {
3047
+ return FIO_passThrough(&ress);
3048
+ } else {
3049
+ DISPLAYLEVEL(1, "zstd: %s: unsupported format \n", srcFileName);
3050
+ return 1;
3051
+ } } /* for each frame */
3052
+
3053
+ /* Final Status */
3054
+ fCtx->totalBytesOutput += (size_t)filesize;
3055
+ DISPLAY_PROGRESS("\r%79s\r", "");
3056
+ if (FIO_shouldDisplayFileSummary(fCtx))
3057
+ DISPLAY_SUMMARY("%-20s: %llu bytes \n", srcFileName, filesize);
3058
+
3059
+ return 0;
3060
+ }
3061
+
3062
+ /** FIO_decompressDstFile() :
3063
+ open `dstFileName`, or pass-through if writeCtx's file is already != 0,
3064
+ then start decompression process (FIO_decompressFrames()).
3065
+ @return : 0 : OK
3066
+ 1 : operation aborted
3067
+ */
3068
+ static int FIO_decompressDstFile(FIO_ctx_t* const fCtx,
3069
+ FIO_prefs_t* const prefs,
3070
+ dRess_t ress,
3071
+ const char* dstFileName,
3072
+ const char* srcFileName,
3073
+ const stat_t* srcFileStat)
3074
+ {
3075
+ int result;
3076
+ int releaseDstFile = 0;
3077
+ int transferStat = 0;
3078
+ int dstFd = 0;
3079
+
3080
+ if ((AIO_WritePool_getFile(ress.writeCtx) == NULL) && (prefs->testMode == 0)) {
3081
+ FILE *dstFile;
3082
+ int dstFilePermissions = DEFAULT_FILE_PERMISSIONS;
3083
+ if ( strcmp(srcFileName, stdinmark) /* special case : don't transfer permissions from stdin */
3084
+ && strcmp(dstFileName, stdoutmark)
3085
+ && UTIL_isRegularFileStat(srcFileStat) ) {
3086
+ transferStat = 1;
3087
+ dstFilePermissions = TEMPORARY_FILE_PERMISSIONS;
3088
+ }
3089
+
3090
+ releaseDstFile = 1;
3091
+
3092
+ dstFile = FIO_openDstFile(fCtx, prefs, srcFileName, dstFileName, dstFilePermissions);
3093
+ if (dstFile==NULL) return 1;
3094
+ dstFd = fileno(dstFile);
3095
+ AIO_WritePool_setFile(ress.writeCtx, dstFile);
3096
+
3097
+ /* Must only be added after FIO_openDstFile() succeeds.
3098
+ * Otherwise we may delete the destination file if it already exists,
3099
+ * and the user presses Ctrl-C when asked if they wish to overwrite.
3100
+ */
3101
+ addHandler(dstFileName);
3102
+ }
3103
+
3104
+ result = FIO_decompressFrames(fCtx, ress, prefs, dstFileName, srcFileName);
3105
+
3106
+ if (releaseDstFile) {
3107
+ clearHandler();
3108
+
3109
+ if (transferStat) {
3110
+ UTIL_setFDStat(dstFd, dstFileName, srcFileStat);
3111
+ }
3112
+
3113
+ if (AIO_WritePool_closeFile(ress.writeCtx)) {
3114
+ DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno));
3115
+ result = 1;
3116
+ }
3117
+
3118
+ if (transferStat) {
3119
+ UTIL_utime(dstFileName, srcFileStat);
3120
+ }
3121
+
3122
+ if ( (result != 0) /* operation failure */
3123
+ && strcmp(dstFileName, stdoutmark) /* special case : don't remove() stdout */
3124
+ ) {
3125
+ FIO_removeFile(dstFileName); /* remove decompression artefact; note: don't do anything special if remove() fails */
3126
+ }
3127
+ }
3128
+
3129
+ return result;
3130
+ }
3131
+
3132
+
3133
+ /** FIO_decompressSrcFile() :
3134
+ Open `srcFileName`, transfer control to decompressDstFile()
3135
+ @return : 0 : OK
3136
+ 1 : error
3137
+ */
3138
+ static int FIO_decompressSrcFile(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs, dRess_t ress, const char* dstFileName, const char* srcFileName)
3139
+ {
3140
+ FILE* srcFile;
3141
+ stat_t srcFileStat;
3142
+ int result;
3143
+ U64 fileSize = UTIL_FILESIZE_UNKNOWN;
3144
+
3145
+ if (UTIL_isDirectory(srcFileName)) {
3146
+ DISPLAYLEVEL(1, "zstd: %s is a directory -- ignored \n", srcFileName);
3147
+ return 1;
3148
+ }
3149
+
3150
+ srcFile = FIO_openSrcFile(prefs, srcFileName, &srcFileStat);
3151
+ if (srcFile==NULL) return 1;
3152
+
3153
+ /* Don't use AsyncIO for small files */
3154
+ if (strcmp(srcFileName, stdinmark)) /* Stdin doesn't have stats */
3155
+ fileSize = UTIL_getFileSizeStat(&srcFileStat);
3156
+ if(fileSize != UTIL_FILESIZE_UNKNOWN && fileSize < ZSTD_BLOCKSIZE_MAX * 3) {
3157
+ AIO_ReadPool_setAsync(ress.readCtx, 0);
3158
+ AIO_WritePool_setAsync(ress.writeCtx, 0);
3159
+ } else {
3160
+ AIO_ReadPool_setAsync(ress.readCtx, 1);
3161
+ AIO_WritePool_setAsync(ress.writeCtx, 1);
3162
+ }
3163
+
3164
+ AIO_ReadPool_setFile(ress.readCtx, srcFile);
3165
+
3166
+ result = FIO_decompressDstFile(fCtx, prefs, ress, dstFileName, srcFileName, &srcFileStat);
3167
+
3168
+ AIO_ReadPool_setFile(ress.readCtx, NULL);
3169
+
3170
+ /* Close file */
3171
+ if (fclose(srcFile)) {
3172
+ DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno)); /* error should not happen */
3173
+ return 1;
3174
+ }
3175
+ if ( prefs->removeSrcFile /* --rm */
3176
+ && (result==0) /* decompression successful */
3177
+ && strcmp(srcFileName, stdinmark) ) /* not stdin */ {
3178
+ /* We must clear the handler, since after this point calling it would
3179
+ * delete both the source and destination files.
3180
+ */
3181
+ clearHandler();
3182
+ if (FIO_removeFile(srcFileName)) {
3183
+ /* failed to remove src file */
3184
+ DISPLAYLEVEL(1, "zstd: %s: %s \n", srcFileName, strerror(errno));
3185
+ return 1;
3186
+ } }
3187
+ return result;
3188
+ }
3189
+
3190
+
3191
+
3192
+ int FIO_decompressFilename(FIO_ctx_t* const fCtx, FIO_prefs_t* const prefs,
3193
+ const char* dstFileName, const char* srcFileName,
3194
+ const char* dictFileName)
3195
+ {
3196
+ dRess_t const ress = FIO_createDResources(prefs, dictFileName);
3197
+
3198
+ int const decodingError = FIO_decompressSrcFile(fCtx, prefs, ress, dstFileName, srcFileName);
3199
+
3200
+
3201
+
3202
+ FIO_freeDResources(ress);
3203
+ return decodingError;
3204
+ }
3205
+
3206
+ static const char *suffixList[] = {
3207
+ ZSTD_EXTENSION,
3208
+ TZSTD_EXTENSION,
3209
+ #ifndef ZSTD_NODECOMPRESS
3210
+ ZSTD_ALT_EXTENSION,
3211
+ #endif
3212
+ #ifdef ZSTD_GZDECOMPRESS
3213
+ GZ_EXTENSION,
3214
+ TGZ_EXTENSION,
3215
+ #endif
3216
+ #ifdef ZSTD_LZMADECOMPRESS
3217
+ LZMA_EXTENSION,
3218
+ XZ_EXTENSION,
3219
+ TXZ_EXTENSION,
3220
+ #endif
3221
+ #ifdef ZSTD_LZ4DECOMPRESS
3222
+ LZ4_EXTENSION,
3223
+ TLZ4_EXTENSION,
3224
+ #endif
3225
+ NULL
3226
+ };
3227
+
3228
+ static const char *suffixListStr =
3229
+ ZSTD_EXTENSION "/" TZSTD_EXTENSION
3230
+ #ifdef ZSTD_GZDECOMPRESS
3231
+ "/" GZ_EXTENSION "/" TGZ_EXTENSION
3232
+ #endif
3233
+ #ifdef ZSTD_LZMADECOMPRESS
3234
+ "/" LZMA_EXTENSION "/" XZ_EXTENSION "/" TXZ_EXTENSION
3235
+ #endif
3236
+ #ifdef ZSTD_LZ4DECOMPRESS
3237
+ "/" LZ4_EXTENSION "/" TLZ4_EXTENSION
3238
+ #endif
3239
+ ;
3240
+
3241
+ /* FIO_determineDstName() :
3242
+ * create a destination filename from a srcFileName.
3243
+ * @return a pointer to it.
3244
+ * @return == NULL if there is an error */
3245
+ static const char*
3246
+ FIO_determineDstName(const char* srcFileName, const char* outDirName)
3247
+ {
3248
+ static size_t dfnbCapacity = 0;
3249
+ static char* dstFileNameBuffer = NULL; /* using static allocation : this function cannot be multi-threaded */
3250
+ size_t dstFileNameEndPos;
3251
+ char* outDirFilename = NULL;
3252
+ const char* dstSuffix = "";
3253
+ size_t dstSuffixLen = 0;
3254
+
3255
+ size_t sfnSize = strlen(srcFileName);
3256
+
3257
+ size_t srcSuffixLen;
3258
+ const char* const srcSuffix = strrchr(srcFileName, '.');
3259
+
3260
+ if(!strcmp(srcFileName, stdinmark)) {
3261
+ return stdoutmark;
3262
+ }
3263
+
3264
+ if (srcSuffix == NULL) {
3265
+ DISPLAYLEVEL(1,
3266
+ "zstd: %s: unknown suffix (%s expected). "
3267
+ "Can't derive the output file name. "
3268
+ "Specify it with -o dstFileName. Ignoring.\n",
3269
+ srcFileName, suffixListStr);
3270
+ return NULL;
3271
+ }
3272
+ srcSuffixLen = strlen(srcSuffix);
3273
+
3274
+ {
3275
+ const char** matchedSuffixPtr;
3276
+ for (matchedSuffixPtr = suffixList; *matchedSuffixPtr != NULL; matchedSuffixPtr++) {
3277
+ if (!strcmp(*matchedSuffixPtr, srcSuffix)) {
3278
+ break;
3279
+ }
3280
+ }
3281
+
3282
+ /* check suffix is authorized */
3283
+ if (sfnSize <= srcSuffixLen || *matchedSuffixPtr == NULL) {
3284
+ DISPLAYLEVEL(1,
3285
+ "zstd: %s: unknown suffix (%s expected). "
3286
+ "Can't derive the output file name. "
3287
+ "Specify it with -o dstFileName. Ignoring.\n",
3288
+ srcFileName, suffixListStr);
3289
+ return NULL;
3290
+ }
3291
+
3292
+ if ((*matchedSuffixPtr)[1] == 't') {
3293
+ dstSuffix = ".tar";
3294
+ dstSuffixLen = strlen(dstSuffix);
3295
+ }
3296
+ }
3297
+
3298
+ if (outDirName) {
3299
+ outDirFilename = FIO_createFilename_fromOutDir(srcFileName, outDirName, 0);
3300
+ sfnSize = strlen(outDirFilename);
3301
+ assert(outDirFilename != NULL);
3302
+ }
3303
+
3304
+ if (dfnbCapacity+srcSuffixLen <= sfnSize+1+dstSuffixLen) {
3305
+ /* allocate enough space to write dstFilename into it */
3306
+ free(dstFileNameBuffer);
3307
+ dfnbCapacity = sfnSize + 20;
3308
+ dstFileNameBuffer = (char*)malloc(dfnbCapacity);
3309
+ if (dstFileNameBuffer==NULL)
3310
+ EXM_THROW(74, "%s : not enough memory for dstFileName",
3311
+ strerror(errno));
3312
+ }
3313
+
3314
+ /* return dst name == src name truncated from suffix */
3315
+ assert(dstFileNameBuffer != NULL);
3316
+ dstFileNameEndPos = sfnSize - srcSuffixLen;
3317
+ if (outDirFilename) {
3318
+ memcpy(dstFileNameBuffer, outDirFilename, dstFileNameEndPos);
3319
+ free(outDirFilename);
3320
+ } else {
3321
+ memcpy(dstFileNameBuffer, srcFileName, dstFileNameEndPos);
3322
+ }
3323
+
3324
+ /* The short tar extensions tzst, tgz, txz and tlz4 files should have "tar"
3325
+ * extension on decompression. Also writes terminating null. */
3326
+ strcpy(dstFileNameBuffer + dstFileNameEndPos, dstSuffix);
3327
+ return dstFileNameBuffer;
3328
+
3329
+ /* note : dstFileNameBuffer memory is not going to be free */
3330
+ }
3331
+
3332
+ int
3333
+ FIO_decompressMultipleFilenames(FIO_ctx_t* const fCtx,
3334
+ FIO_prefs_t* const prefs,
3335
+ const char** srcNamesTable,
3336
+ const char* outMirroredRootDirName,
3337
+ const char* outDirName, const char* outFileName,
3338
+ const char* dictFileName)
3339
+ {
3340
+ int status;
3341
+ int error = 0;
3342
+ dRess_t ress = FIO_createDResources(prefs, dictFileName);
3343
+
3344
+ if (outFileName) {
3345
+ if (FIO_multiFilesConcatWarning(fCtx, prefs, outFileName, 1 /* displayLevelCutoff */)) {
3346
+ FIO_freeDResources(ress);
3347
+ return 1;
3348
+ }
3349
+ if (!prefs->testMode) {
3350
+ FILE* dstFile = FIO_openDstFile(fCtx, prefs, NULL, outFileName, DEFAULT_FILE_PERMISSIONS);
3351
+ if (dstFile == 0) EXM_THROW(19, "cannot open %s", outFileName);
3352
+ AIO_WritePool_setFile(ress.writeCtx, dstFile);
3353
+ }
3354
+ for (; fCtx->currFileIdx < fCtx->nbFilesTotal; fCtx->currFileIdx++) {
3355
+ status = FIO_decompressSrcFile(fCtx, prefs, ress, outFileName, srcNamesTable[fCtx->currFileIdx]);
3356
+ if (!status) fCtx->nbFilesProcessed++;
3357
+ error |= status;
3358
+ }
3359
+ if ((!prefs->testMode) && (AIO_WritePool_closeFile(ress.writeCtx)))
3360
+ EXM_THROW(72, "Write error : %s : cannot properly close output file",
3361
+ strerror(errno));
3362
+ } else {
3363
+ if (outMirroredRootDirName)
3364
+ UTIL_mirrorSourceFilesDirectories(srcNamesTable, (unsigned)fCtx->nbFilesTotal, outMirroredRootDirName);
3365
+
3366
+ for (; fCtx->currFileIdx < fCtx->nbFilesTotal; fCtx->currFileIdx++) { /* create dstFileName */
3367
+ const char* const srcFileName = srcNamesTable[fCtx->currFileIdx];
3368
+ const char* dstFileName = NULL;
3369
+ if (outMirroredRootDirName) {
3370
+ char* validMirroredDirName = UTIL_createMirroredDestDirName(srcFileName, outMirroredRootDirName);
3371
+ if (validMirroredDirName) {
3372
+ dstFileName = FIO_determineDstName(srcFileName, validMirroredDirName);
3373
+ free(validMirroredDirName);
3374
+ } else {
3375
+ DISPLAYLEVEL(2, "zstd: --output-dir-mirror cannot decompress '%s' into '%s'\n", srcFileName, outMirroredRootDirName);
3376
+ }
3377
+ } else {
3378
+ dstFileName = FIO_determineDstName(srcFileName, outDirName);
3379
+ }
3380
+ if (dstFileName == NULL) { error=1; continue; }
3381
+ status = FIO_decompressSrcFile(fCtx, prefs, ress, dstFileName, srcFileName);
3382
+ if (!status) fCtx->nbFilesProcessed++;
3383
+ error |= status;
3384
+ }
3385
+ if (outDirName)
3386
+ FIO_checkFilenameCollisions(srcNamesTable , (unsigned)fCtx->nbFilesTotal);
3387
+ }
3388
+
3389
+ if (FIO_shouldDisplayMultipleFileSummary(fCtx)) {
3390
+ DISPLAY_PROGRESS("\r%79s\r", "");
3391
+ DISPLAY_SUMMARY("%d files decompressed : %6llu bytes total \n",
3392
+ fCtx->nbFilesProcessed, (unsigned long long)fCtx->totalBytesOutput);
3393
+ }
3394
+
3395
+ FIO_freeDResources(ress);
3396
+ return error;
3397
+ }
3398
+
3399
+ /* **************************************************************************
3400
+ * .zst file info (--list command)
3401
+ ***************************************************************************/
3402
+
3403
+ typedef struct {
3404
+ U64 decompressedSize;
3405
+ U64 compressedSize;
3406
+ U64 windowSize;
3407
+ int numActualFrames;
3408
+ int numSkippableFrames;
3409
+ int decompUnavailable;
3410
+ int usesCheck;
3411
+ BYTE checksum[4];
3412
+ U32 nbFiles;
3413
+ unsigned dictID;
3414
+ } fileInfo_t;
3415
+
3416
+ typedef enum {
3417
+ info_success=0,
3418
+ info_frame_error=1,
3419
+ info_not_zstd=2,
3420
+ info_file_error=3,
3421
+ info_truncated_input=4
3422
+ } InfoError;
3423
+
3424
+ #define ERROR_IF(c,n,...) { \
3425
+ if (c) { \
3426
+ DISPLAYLEVEL(1, __VA_ARGS__); \
3427
+ DISPLAYLEVEL(1, " \n"); \
3428
+ return n; \
3429
+ } \
3430
+ }
3431
+
3432
+ static InfoError
3433
+ FIO_analyzeFrames(fileInfo_t* info, FILE* const srcFile)
3434
+ {
3435
+ /* begin analyzing frame */
3436
+ for ( ; ; ) {
3437
+ BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
3438
+ size_t const numBytesRead = fread(headerBuffer, 1, sizeof(headerBuffer), srcFile);
3439
+ if (numBytesRead < ZSTD_FRAMEHEADERSIZE_MIN(ZSTD_f_zstd1)) {
3440
+ if ( feof(srcFile)
3441
+ && (numBytesRead == 0)
3442
+ && (info->compressedSize > 0)
3443
+ && (info->compressedSize != UTIL_FILESIZE_UNKNOWN) ) {
3444
+ unsigned long long file_position = (unsigned long long) LONG_TELL(srcFile);
3445
+ unsigned long long file_size = (unsigned long long) info->compressedSize;
3446
+ ERROR_IF(file_position != file_size, info_truncated_input,
3447
+ "Error: seeked to position %llu, which is beyond file size of %llu\n",
3448
+ file_position,
3449
+ file_size);
3450
+ break; /* correct end of file => success */
3451
+ }
3452
+ ERROR_IF(feof(srcFile), info_not_zstd, "Error: reached end of file with incomplete frame");
3453
+ ERROR_IF(1, info_frame_error, "Error: did not reach end of file but ran out of frames");
3454
+ }
3455
+ { U32 const magicNumber = MEM_readLE32(headerBuffer);
3456
+ /* Zstandard frame */
3457
+ if (magicNumber == ZSTD_MAGICNUMBER) {
3458
+ ZSTD_FrameHeader header;
3459
+ U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead);
3460
+ if ( frameContentSize == ZSTD_CONTENTSIZE_ERROR
3461
+ || frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN ) {
3462
+ info->decompUnavailable = 1;
3463
+ } else {
3464
+ info->decompressedSize += frameContentSize;
3465
+ }
3466
+ ERROR_IF(ZSTD_getFrameHeader(&header, headerBuffer, numBytesRead) != 0,
3467
+ info_frame_error, "Error: could not decode frame header");
3468
+ if (info->dictID != 0 && info->dictID != header.dictID) {
3469
+ DISPLAY("WARNING: File contains multiple frames with different dictionary IDs. Showing dictID 0 instead");
3470
+ info->dictID = 0;
3471
+ } else {
3472
+ info->dictID = header.dictID;
3473
+ }
3474
+ info->windowSize = header.windowSize;
3475
+ /* move to the end of the frame header */
3476
+ { size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead);
3477
+ ERROR_IF(ZSTD_isError(headerSize), info_frame_error, "Error: could not determine frame header size");
3478
+ ERROR_IF(fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR) != 0,
3479
+ info_frame_error, "Error: could not move to end of frame header");
3480
+ }
3481
+
3482
+ /* skip all blocks in the frame */
3483
+ { int lastBlock = 0;
3484
+ do {
3485
+ BYTE blockHeaderBuffer[3];
3486
+ ERROR_IF(fread(blockHeaderBuffer, 1, 3, srcFile) != 3,
3487
+ info_frame_error, "Error while reading block header");
3488
+ { U32 const blockHeader = MEM_readLE24(blockHeaderBuffer);
3489
+ U32 const blockTypeID = (blockHeader >> 1) & 3;
3490
+ U32 const isRLE = (blockTypeID == 1);
3491
+ U32 const isWrongBlock = (blockTypeID == 3);
3492
+ long const blockSize = isRLE ? 1 : (long)(blockHeader >> 3);
3493
+ ERROR_IF(isWrongBlock, info_frame_error, "Error: unsupported block type");
3494
+ lastBlock = blockHeader & 1;
3495
+ ERROR_IF(fseek(srcFile, blockSize, SEEK_CUR) != 0,
3496
+ info_frame_error, "Error: could not skip to end of block");
3497
+ }
3498
+ } while (lastBlock != 1);
3499
+ }
3500
+
3501
+ /* check if checksum is used */
3502
+ { BYTE const frameHeaderDescriptor = headerBuffer[4];
3503
+ int const contentChecksumFlag = (frameHeaderDescriptor & (1 << 2)) >> 2;
3504
+ if (contentChecksumFlag) {
3505
+ info->usesCheck = 1;
3506
+ ERROR_IF(fread(info->checksum, 1, 4, srcFile) != 4,
3507
+ info_frame_error, "Error: could not read checksum");
3508
+ } }
3509
+ info->numActualFrames++;
3510
+ }
3511
+ /* Skippable frame */
3512
+ else if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
3513
+ U32 const frameSize = MEM_readLE32(headerBuffer + 4);
3514
+ long const seek = (long)(8 + frameSize - numBytesRead);
3515
+ ERROR_IF(LONG_SEEK(srcFile, seek, SEEK_CUR) != 0,
3516
+ info_frame_error, "Error: could not find end of skippable frame");
3517
+ info->numSkippableFrames++;
3518
+ }
3519
+ /* unknown content */
3520
+ else {
3521
+ return info_not_zstd;
3522
+ }
3523
+ } /* magic number analysis */
3524
+ } /* end analyzing frames */
3525
+ return info_success;
3526
+ }
3527
+
3528
+
3529
+ static InfoError
3530
+ getFileInfo_fileConfirmed(fileInfo_t* info, const char* inFileName)
3531
+ {
3532
+ InfoError status;
3533
+ stat_t srcFileStat;
3534
+ FILE* const srcFile = FIO_openSrcFile(NULL, inFileName, &srcFileStat);
3535
+ ERROR_IF(srcFile == NULL, info_file_error, "Error: could not open source file %s", inFileName);
3536
+
3537
+ info->compressedSize = UTIL_getFileSizeStat(&srcFileStat);
3538
+ status = FIO_analyzeFrames(info, srcFile);
3539
+
3540
+ fclose(srcFile);
3541
+ info->nbFiles = 1;
3542
+ return status;
3543
+ }
3544
+
3545
+
3546
+ /** getFileInfo() :
3547
+ * Reads information from file, stores in *info
3548
+ * @return : InfoError status
3549
+ */
3550
+ static InfoError
3551
+ getFileInfo(fileInfo_t* info, const char* srcFileName)
3552
+ {
3553
+ ERROR_IF(!UTIL_isRegularFile(srcFileName),
3554
+ info_file_error, "Error : %s is not a file", srcFileName);
3555
+ return getFileInfo_fileConfirmed(info, srcFileName);
3556
+ }
3557
+
3558
+
3559
+ static void
3560
+ displayInfo(const char* inFileName, const fileInfo_t* info, int displayLevel)
3561
+ {
3562
+ UTIL_HumanReadableSize_t const window_hrs = UTIL_makeHumanReadableSize(info->windowSize);
3563
+ UTIL_HumanReadableSize_t const compressed_hrs = UTIL_makeHumanReadableSize(info->compressedSize);
3564
+ UTIL_HumanReadableSize_t const decompressed_hrs = UTIL_makeHumanReadableSize(info->decompressedSize);
3565
+ double const ratio = (info->compressedSize == 0) ? 0 : ((double)info->decompressedSize)/(double)info->compressedSize;
3566
+ const char* const checkString = (info->usesCheck ? "XXH64" : "None");
3567
+ if (displayLevel <= 2) {
3568
+ if (!info->decompUnavailable) {
3569
+ DISPLAYOUT("%6d %5d %6.*f%4s %8.*f%4s %5.3f %5s %s\n",
3570
+ info->numSkippableFrames + info->numActualFrames,
3571
+ info->numSkippableFrames,
3572
+ compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
3573
+ decompressed_hrs.precision, decompressed_hrs.value, decompressed_hrs.suffix,
3574
+ ratio, checkString, inFileName);
3575
+ } else {
3576
+ DISPLAYOUT("%6d %5d %6.*f%4s %5s %s\n",
3577
+ info->numSkippableFrames + info->numActualFrames,
3578
+ info->numSkippableFrames,
3579
+ compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
3580
+ checkString, inFileName);
3581
+ }
3582
+ } else {
3583
+ DISPLAYOUT("%s \n", inFileName);
3584
+ DISPLAYOUT("# Zstandard Frames: %d\n", info->numActualFrames);
3585
+ if (info->numSkippableFrames)
3586
+ DISPLAYOUT("# Skippable Frames: %d\n", info->numSkippableFrames);
3587
+ DISPLAYOUT("DictID: %u\n", info->dictID);
3588
+ DISPLAYOUT("Window Size: %.*f%s (%llu B)\n",
3589
+ window_hrs.precision, window_hrs.value, window_hrs.suffix,
3590
+ (unsigned long long)info->windowSize);
3591
+ DISPLAYOUT("Compressed Size: %.*f%s (%llu B)\n",
3592
+ compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
3593
+ (unsigned long long)info->compressedSize);
3594
+ if (!info->decompUnavailable) {
3595
+ DISPLAYOUT("Decompressed Size: %.*f%s (%llu B)\n",
3596
+ decompressed_hrs.precision, decompressed_hrs.value, decompressed_hrs.suffix,
3597
+ (unsigned long long)info->decompressedSize);
3598
+ DISPLAYOUT("Ratio: %.4f\n", ratio);
3599
+ }
3600
+
3601
+ if (info->usesCheck && info->numActualFrames == 1) {
3602
+ DISPLAYOUT("Check: %s %02x%02x%02x%02x\n", checkString,
3603
+ info->checksum[3], info->checksum[2],
3604
+ info->checksum[1], info->checksum[0]
3605
+ );
3606
+ } else {
3607
+ DISPLAYOUT("Check: %s\n", checkString);
3608
+ }
3609
+
3610
+ DISPLAYOUT("\n");
3611
+ }
3612
+ }
3613
+
3614
+ static fileInfo_t FIO_addFInfo(fileInfo_t fi1, fileInfo_t fi2)
3615
+ {
3616
+ fileInfo_t total;
3617
+ memset(&total, 0, sizeof(total));
3618
+ total.numActualFrames = fi1.numActualFrames + fi2.numActualFrames;
3619
+ total.numSkippableFrames = fi1.numSkippableFrames + fi2.numSkippableFrames;
3620
+ total.compressedSize = fi1.compressedSize + fi2.compressedSize;
3621
+ total.decompressedSize = fi1.decompressedSize + fi2.decompressedSize;
3622
+ total.decompUnavailable = fi1.decompUnavailable | fi2.decompUnavailable;
3623
+ total.usesCheck = fi1.usesCheck & fi2.usesCheck;
3624
+ total.nbFiles = fi1.nbFiles + fi2.nbFiles;
3625
+ return total;
3626
+ }
3627
+
3628
+ static int
3629
+ FIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel)
3630
+ {
3631
+ fileInfo_t info;
3632
+ memset(&info, 0, sizeof(info));
3633
+ { InfoError const error = getFileInfo(&info, inFileName);
3634
+ switch (error) {
3635
+ case info_frame_error:
3636
+ /* display error, but provide output */
3637
+ DISPLAYLEVEL(1, "Error while parsing \"%s\" \n", inFileName);
3638
+ break;
3639
+ case info_not_zstd:
3640
+ DISPLAYOUT("File \"%s\" not compressed by zstd \n", inFileName);
3641
+ if (displayLevel > 2) DISPLAYOUT("\n");
3642
+ return 1;
3643
+ case info_file_error:
3644
+ /* error occurred while opening the file */
3645
+ if (displayLevel > 2) DISPLAYOUT("\n");
3646
+ return 1;
3647
+ case info_truncated_input:
3648
+ DISPLAYOUT("File \"%s\" is truncated \n", inFileName);
3649
+ if (displayLevel > 2) DISPLAYOUT("\n");
3650
+ return 1;
3651
+ case info_success:
3652
+ default:
3653
+ break;
3654
+ }
3655
+
3656
+ displayInfo(inFileName, &info, displayLevel);
3657
+ *total = FIO_addFInfo(*total, info);
3658
+ assert(error == info_success || error == info_frame_error);
3659
+ return (int)error;
3660
+ }
3661
+ }
3662
+
3663
+ int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel)
3664
+ {
3665
+ /* ensure no specified input is stdin (needs fseek() capability) */
3666
+ { unsigned u;
3667
+ for (u=0; u<numFiles;u++) {
3668
+ ERROR_IF(!strcmp (filenameTable[u], stdinmark),
3669
+ 1, "zstd: --list does not support reading from standard input");
3670
+ } }
3671
+
3672
+ if (numFiles == 0) {
3673
+ if (!UTIL_isConsole(stdin)) {
3674
+ DISPLAYLEVEL(1, "zstd: --list does not support reading from standard input \n");
3675
+ }
3676
+ DISPLAYLEVEL(1, "No files given \n");
3677
+ return 1;
3678
+ }
3679
+
3680
+ if (displayLevel <= 2) {
3681
+ DISPLAYOUT("Frames Skips Compressed Uncompressed Ratio Check Filename\n");
3682
+ }
3683
+ { int error = 0;
3684
+ fileInfo_t total;
3685
+ memset(&total, 0, sizeof(total));
3686
+ total.usesCheck = 1;
3687
+ /* --list each file, and check for any error */
3688
+ { unsigned u;
3689
+ for (u=0; u<numFiles;u++) {
3690
+ error |= FIO_listFile(&total, filenameTable[u], displayLevel);
3691
+ } }
3692
+ if (numFiles > 1 && displayLevel <= 2) { /* display total */
3693
+ UTIL_HumanReadableSize_t const compressed_hrs = UTIL_makeHumanReadableSize(total.compressedSize);
3694
+ UTIL_HumanReadableSize_t const decompressed_hrs = UTIL_makeHumanReadableSize(total.decompressedSize);
3695
+ double const ratio = (total.compressedSize == 0) ? 0 : ((double)total.decompressedSize)/(double)total.compressedSize;
3696
+ const char* const checkString = (total.usesCheck ? "XXH64" : "");
3697
+ DISPLAYOUT("----------------------------------------------------------------- \n");
3698
+ if (total.decompUnavailable) {
3699
+ DISPLAYOUT("%6d %5d %6.*f%4s %5s %u files\n",
3700
+ total.numSkippableFrames + total.numActualFrames,
3701
+ total.numSkippableFrames,
3702
+ compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
3703
+ checkString, (unsigned)total.nbFiles);
3704
+ } else {
3705
+ DISPLAYOUT("%6d %5d %6.*f%4s %8.*f%4s %5.3f %5s %u files\n",
3706
+ total.numSkippableFrames + total.numActualFrames,
3707
+ total.numSkippableFrames,
3708
+ compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
3709
+ decompressed_hrs.precision, decompressed_hrs.value, decompressed_hrs.suffix,
3710
+ ratio, checkString, (unsigned)total.nbFiles);
3711
+ } }
3712
+ return error;
3713
+ }
3714
+ }
3715
+
3716
+
3717
+ #endif /* #ifndef ZSTD_NODECOMPRESS */