mz_strm_zlib.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /* mz_strm_zlib.c -- Stream for zlib inflate/deflate
  2. Version 2.9.2, February 12, 2020
  3. part of the MiniZip project
  4. Copyright (C) 2010-2020 Nathan Moinvaziri
  5. https://github.com/nmoinvaz/minizip
  6. This program is distributed under the terms of the same license as zlib.
  7. See the accompanying LICENSE file for the full text of the license.
  8. */
  9. #include "mz.h"
  10. #include "mz_strm.h"
  11. #include "mz_strm_zlib.h"
  12. #include "zlib.h"
  13. #if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
  14. # include "zlib-ng.h"
  15. #endif
  16. /***************************************************************************/
  17. #if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
  18. # define ZLIB_PREFIX(x) zng_ ## x
  19. typedef zng_stream zlib_stream;
  20. #else
  21. # define ZLIB_PREFIX(x) x
  22. typedef z_stream zlib_stream;
  23. #endif
  24. #if !defined(DEF_MEM_LEVEL)
  25. # if MAX_MEM_LEVEL >= 8
  26. # define DEF_MEM_LEVEL 8
  27. # else
  28. # define DEF_MEM_LEVEL MAX_MEM_LEVEL
  29. # endif
  30. #endif
  31. /***************************************************************************/
  32. static mz_stream_vtbl mz_stream_zlib_vtbl = {
  33. mz_stream_zlib_open,
  34. mz_stream_zlib_is_open,
  35. mz_stream_zlib_read,
  36. mz_stream_zlib_write,
  37. mz_stream_zlib_tell,
  38. mz_stream_zlib_seek,
  39. mz_stream_zlib_close,
  40. mz_stream_zlib_error,
  41. mz_stream_zlib_create,
  42. mz_stream_zlib_delete,
  43. mz_stream_zlib_get_prop_int64,
  44. mz_stream_zlib_set_prop_int64
  45. };
  46. /***************************************************************************/
  47. typedef struct mz_stream_zlib_s {
  48. mz_stream stream;
  49. zlib_stream zstream;
  50. uint8_t buffer[INT16_MAX];
  51. int32_t buffer_len;
  52. int64_t total_in;
  53. int64_t total_out;
  54. int64_t max_total_in;
  55. int8_t initialized;
  56. int16_t level;
  57. int32_t window_bits;
  58. int32_t mode;
  59. int32_t error;
  60. } mz_stream_zlib;
  61. /***************************************************************************/
  62. int32_t mz_stream_zlib_open(void *stream, const char *path, int32_t mode)
  63. {
  64. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  65. MZ_UNUSED(path);
  66. zlib->zstream.data_type = Z_BINARY;
  67. zlib->zstream.zalloc = Z_NULL;
  68. zlib->zstream.zfree = Z_NULL;
  69. zlib->zstream.opaque = Z_NULL;
  70. zlib->zstream.total_in = 0;
  71. zlib->zstream.total_out = 0;
  72. zlib->total_in = 0;
  73. zlib->total_out = 0;
  74. if (mode & MZ_OPEN_MODE_WRITE)
  75. {
  76. #ifdef MZ_ZIP_NO_COMPRESSION
  77. return MZ_SUPPORT_ERROR;
  78. #else
  79. zlib->zstream.next_out = zlib->buffer;
  80. zlib->zstream.avail_out = sizeof(zlib->buffer);
  81. zlib->error = ZLIB_PREFIX(deflateInit2)(&zlib->zstream, (int8_t)zlib->level, Z_DEFLATED,
  82. zlib->window_bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
  83. #endif
  84. }
  85. else if (mode & MZ_OPEN_MODE_READ)
  86. {
  87. #ifdef MZ_ZIP_NO_DECOMPRESSION
  88. return MZ_SUPPORT_ERROR;
  89. #else
  90. zlib->zstream.next_in = zlib->buffer;
  91. zlib->zstream.avail_in = 0;
  92. zlib->error = ZLIB_PREFIX(inflateInit2)(&zlib->zstream, zlib->window_bits);
  93. #endif
  94. }
  95. if (zlib->error != Z_OK)
  96. return MZ_OPEN_ERROR;
  97. zlib->initialized = 1;
  98. zlib->mode = mode;
  99. return MZ_OK;
  100. }
  101. int32_t mz_stream_zlib_is_open(void *stream)
  102. {
  103. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  104. if (zlib->initialized != 1)
  105. return MZ_OPEN_ERROR;
  106. return MZ_OK;
  107. }
  108. int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size)
  109. {
  110. #ifdef MZ_ZIP_NO_DECOMPRESSION
  111. MZ_UNUSED(stream);
  112. MZ_UNUSED(buf);
  113. MZ_UNUSED(size);
  114. return MZ_SUPPORT_ERROR;
  115. #else
  116. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  117. uint64_t total_in_before = 0;
  118. uint64_t total_in_after = 0;
  119. uint64_t total_out_before = 0;
  120. uint64_t total_out_after = 0;
  121. uint32_t total_in = 0;
  122. uint32_t total_out = 0;
  123. uint32_t in_bytes = 0;
  124. uint32_t out_bytes = 0;
  125. int32_t bytes_to_read = sizeof(zlib->buffer);
  126. int32_t read = 0;
  127. int32_t err = Z_OK;
  128. zlib->zstream.next_out = (Bytef*)buf;
  129. zlib->zstream.avail_out = (uInt)size;
  130. do
  131. {
  132. if (zlib->zstream.avail_in == 0)
  133. {
  134. if (zlib->max_total_in > 0)
  135. {
  136. if ((int64_t)bytes_to_read > (zlib->max_total_in - zlib->total_in))
  137. bytes_to_read = (int32_t)(zlib->max_total_in - zlib->total_in);
  138. }
  139. read = mz_stream_read(zlib->stream.base, zlib->buffer, bytes_to_read);
  140. if (read < 0)
  141. return read;
  142. zlib->zstream.next_in = zlib->buffer;
  143. zlib->zstream.avail_in = read;
  144. }
  145. total_in_before = zlib->zstream.avail_in;
  146. total_out_before = zlib->zstream.total_out;
  147. err = ZLIB_PREFIX(inflate)(&zlib->zstream, Z_SYNC_FLUSH);
  148. if ((err >= Z_OK) && (zlib->zstream.msg != NULL))
  149. {
  150. zlib->error = Z_DATA_ERROR;
  151. break;
  152. }
  153. total_in_after = zlib->zstream.avail_in;
  154. total_out_after = zlib->zstream.total_out;
  155. in_bytes = (uint32_t)(total_in_before - total_in_after);
  156. out_bytes = (uint32_t)(total_out_after - total_out_before);
  157. total_in += in_bytes;
  158. total_out += out_bytes;
  159. zlib->total_in += in_bytes;
  160. zlib->total_out += out_bytes;
  161. if (err == Z_STREAM_END)
  162. break;
  163. if (err != Z_OK)
  164. {
  165. zlib->error = err;
  166. break;
  167. }
  168. }
  169. while (zlib->zstream.avail_out > 0);
  170. if (zlib->error != 0)
  171. {
  172. /* Zlib errors are compatible with MZ */
  173. return zlib->error;
  174. }
  175. return total_out;
  176. #endif
  177. }
  178. #ifndef MZ_ZIP_NO_COMPRESSION
  179. static int32_t mz_stream_zlib_flush(void *stream)
  180. {
  181. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  182. if (mz_stream_write(zlib->stream.base, zlib->buffer, zlib->buffer_len) != zlib->buffer_len)
  183. return MZ_WRITE_ERROR;
  184. return MZ_OK;
  185. }
  186. static int32_t mz_stream_zlib_deflate(void *stream, int flush)
  187. {
  188. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  189. uint64_t total_out_before = 0;
  190. uint64_t total_out_after = 0;
  191. int32_t out_bytes = 0;
  192. int32_t err = Z_OK;
  193. do
  194. {
  195. if (zlib->zstream.avail_out == 0)
  196. {
  197. err = mz_stream_zlib_flush(zlib);
  198. if (err != MZ_OK)
  199. return err;
  200. zlib->zstream.avail_out = sizeof(zlib->buffer);
  201. zlib->zstream.next_out = zlib->buffer;
  202. zlib->buffer_len = 0;
  203. }
  204. total_out_before = zlib->zstream.total_out;
  205. err = ZLIB_PREFIX(deflate)(&zlib->zstream, flush);
  206. total_out_after = zlib->zstream.total_out;
  207. out_bytes = (uint32_t)(total_out_after - total_out_before);
  208. zlib->buffer_len += out_bytes;
  209. zlib->total_out += out_bytes;
  210. if (err == Z_STREAM_END)
  211. break;
  212. if (err != Z_OK)
  213. {
  214. zlib->error = err;
  215. return MZ_DATA_ERROR;
  216. }
  217. }
  218. while ((zlib->zstream.avail_in > 0) || (flush == Z_FINISH && err == Z_OK));
  219. return MZ_OK;
  220. }
  221. #endif
  222. int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size)
  223. {
  224. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  225. int32_t err = size;
  226. #ifdef MZ_ZIP_NO_COMPRESSION
  227. MZ_UNUSED(zlib);
  228. MZ_UNUSED(buf);
  229. err = MZ_SUPPORT_ERROR;
  230. #else
  231. zlib->zstream.next_in = (Bytef*)(intptr_t)buf;
  232. zlib->zstream.avail_in = (uInt)size;
  233. mz_stream_zlib_deflate(stream, Z_NO_FLUSH);
  234. zlib->total_in += size;
  235. #endif
  236. return err;
  237. }
  238. int64_t mz_stream_zlib_tell(void *stream)
  239. {
  240. MZ_UNUSED(stream);
  241. return MZ_TELL_ERROR;
  242. }
  243. int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin)
  244. {
  245. MZ_UNUSED(stream);
  246. MZ_UNUSED(offset);
  247. MZ_UNUSED(origin);
  248. return MZ_SEEK_ERROR;
  249. }
  250. int32_t mz_stream_zlib_close(void *stream)
  251. {
  252. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  253. if (zlib->mode & MZ_OPEN_MODE_WRITE)
  254. {
  255. #ifdef MZ_ZIP_NO_COMPRESSION
  256. return MZ_SUPPORT_ERROR;
  257. #else
  258. mz_stream_zlib_deflate(stream, Z_FINISH);
  259. mz_stream_zlib_flush(stream);
  260. ZLIB_PREFIX(deflateEnd)(&zlib->zstream);
  261. #endif
  262. }
  263. else if (zlib->mode & MZ_OPEN_MODE_READ)
  264. {
  265. #ifdef MZ_ZIP_NO_DECOMPRESSION
  266. return MZ_SUPPORT_ERROR;
  267. #else
  268. ZLIB_PREFIX(inflateEnd)(&zlib->zstream);
  269. #endif
  270. }
  271. zlib->initialized = 0;
  272. if (zlib->error != Z_OK)
  273. return MZ_CLOSE_ERROR;
  274. return MZ_OK;
  275. }
  276. int32_t mz_stream_zlib_error(void *stream)
  277. {
  278. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  279. return zlib->error;
  280. }
  281. int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value)
  282. {
  283. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  284. switch (prop)
  285. {
  286. case MZ_STREAM_PROP_TOTAL_IN:
  287. *value = zlib->total_in;
  288. break;
  289. case MZ_STREAM_PROP_TOTAL_IN_MAX:
  290. *value = zlib->max_total_in;
  291. break;
  292. case MZ_STREAM_PROP_TOTAL_OUT:
  293. *value = zlib->total_out;
  294. break;
  295. case MZ_STREAM_PROP_HEADER_SIZE:
  296. *value = 0;
  297. break;
  298. case MZ_STREAM_PROP_COMPRESS_WINDOW:
  299. *value = zlib->window_bits;
  300. break;
  301. default:
  302. return MZ_EXIST_ERROR;
  303. }
  304. return MZ_OK;
  305. }
  306. int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value)
  307. {
  308. mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
  309. switch (prop)
  310. {
  311. case MZ_STREAM_PROP_COMPRESS_LEVEL:
  312. zlib->level = (int16_t)value;
  313. break;
  314. case MZ_STREAM_PROP_TOTAL_IN_MAX:
  315. zlib->max_total_in = value;
  316. break;
  317. case MZ_STREAM_PROP_COMPRESS_WINDOW:
  318. zlib->window_bits = (int32_t)value;
  319. break;
  320. default:
  321. return MZ_EXIST_ERROR;
  322. }
  323. return MZ_OK;
  324. }
  325. void *mz_stream_zlib_create(void **stream)
  326. {
  327. mz_stream_zlib *zlib = NULL;
  328. zlib = (mz_stream_zlib *)MZ_ALLOC(sizeof(mz_stream_zlib));
  329. if (zlib != NULL)
  330. {
  331. memset(zlib, 0, sizeof(mz_stream_zlib));
  332. zlib->stream.vtbl = &mz_stream_zlib_vtbl;
  333. zlib->level = Z_DEFAULT_COMPRESSION;
  334. zlib->window_bits = -MAX_WBITS;
  335. }
  336. if (stream != NULL)
  337. *stream = zlib;
  338. return zlib;
  339. }
  340. void mz_stream_zlib_delete(void **stream)
  341. {
  342. mz_stream_zlib *zlib = NULL;
  343. if (stream == NULL)
  344. return;
  345. zlib = (mz_stream_zlib *)*stream;
  346. if (zlib != NULL)
  347. MZ_FREE(zlib);
  348. *stream = NULL;
  349. }
  350. void *mz_stream_zlib_get_interface(void)
  351. {
  352. return (void *)&mz_stream_zlib_vtbl;
  353. }