Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
miniz.c
Go to the documentation of this file.
1#define MINGW_HAS_SECURE_API 1
2#include "miniz.h"
3/**************************************************************************
4 *
5 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 **************************************************************************/
28
29
30
31typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
32typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
33typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39/* ------------------- zlib-style API's */
40
41mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
42{
43 mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
44 size_t block_len = buf_len % 5552;
45 if (!ptr)
46 return MZ_ADLER32_INIT;
47 while (buf_len)
48 {
49 for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
50 {
51 s1 += ptr[0], s2 += s1;
52 s1 += ptr[1], s2 += s1;
53 s1 += ptr[2], s2 += s1;
54 s1 += ptr[3], s2 += s1;
55 s1 += ptr[4], s2 += s1;
56 s1 += ptr[5], s2 += s1;
57 s1 += ptr[6], s2 += s1;
58 s1 += ptr[7], s2 += s1;
59 }
60 for (; i < block_len; ++i)
61 s1 += *ptr++, s2 += s1;
62 s1 %= 65521U, s2 %= 65521U;
63 buf_len -= block_len;
64 block_len = 5552;
65 }
66 return (s2 << 16) + s1;
67}
68
69/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */
70#if 0
71 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
72 {
73 static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
74 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
75 mz_uint32 crcu32 = (mz_uint32)crc;
76 if (!ptr)
77 return MZ_CRC32_INIT;
78 crcu32 = ~crcu32;
79 while (buf_len--)
80 {
81 mz_uint8 b = *ptr++;
82 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
83 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
84 }
85 return ~crcu32;
86 }
87#elif defined(USE_EXTERNAL_MZCRC)
88/* If USE_EXTERNAL_CRC is defined, an external module will export the
89 * mz_crc32() symbol for us to use, e.g. an SSE-accelerated version.
90 * Depending on the impl, it may be necessary to ~ the input/output crc values.
91 */
92mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len);
93#else
94/* Faster, but larger CPU cache footprint.
95 */
96mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
97{
98 static const mz_uint32 s_crc_table[256] =
99 {
100 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
101 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
102 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
103 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
104 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
105 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
106 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
107 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
108 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
109 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
110 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
111 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
112 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
113 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
114 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
115 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
116 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
117 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
118 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
119 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
120 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
121 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
122 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
123 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
124 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
125 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
126 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
127 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
128 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
129 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
130 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
131 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
132 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
133 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
134 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
135 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
136 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
137 };
138
139 mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
140 const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
141
142 while (buf_len >= 4)
143 {
144 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
145 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
146 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
147 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
148 pByte_buf += 4;
149 buf_len -= 4;
150 }
151
152 while (buf_len)
153 {
154 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
155 ++pByte_buf;
156 --buf_len;
157 }
158
159 return ~crc32;
160}
161#endif
162
163void mz_free(void *p)
164{
165 MZ_FREE(p);
166}
167
168MINIZ_EXPORT void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
169{
170 (void)opaque, (void)items, (void)size;
171 return MZ_MALLOC(items * size);
172}
173MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address)
174{
175 (void)opaque, (void)address;
176 MZ_FREE(address);
177}
178MINIZ_EXPORT void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
179{
180 (void)opaque, (void)address, (void)items, (void)size;
181 return MZ_REALLOC(address, items * size);
182}
183
184const char *mz_version(void)
185{
186 return MZ_VERSION;
187}
188
189#ifndef MINIZ_NO_ZLIB_APIS
190
191#ifndef MINIZ_NO_DEFLATE_APIS
192
193int mz_deflateInit(mz_streamp pStream, int level)
194{
196}
197
198int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
199{
200 tdefl_compressor *pComp;
201 mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
202
203 if (!pStream)
204 return MZ_STREAM_ERROR;
205 if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
206 return MZ_PARAM_ERROR;
207
208 pStream->data_type = 0;
209 pStream->adler = MZ_ADLER32_INIT;
210 pStream->msg = NULL;
211 pStream->reserved = 0;
212 pStream->total_in = 0;
213 pStream->total_out = 0;
214 if (!pStream->zalloc)
215 pStream->zalloc = miniz_def_alloc_func;
216 if (!pStream->zfree)
217 pStream->zfree = miniz_def_free_func;
218
219 pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
220 if (!pComp)
221 return MZ_MEM_ERROR;
222
223 pStream->state = (struct mz_internal_state *)pComp;
224
225 if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
226 {
227 mz_deflateEnd(pStream);
228 return MZ_PARAM_ERROR;
229 }
230
231 return MZ_OK;
232}
233
235{
236 if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
237 return MZ_STREAM_ERROR;
238 pStream->total_in = pStream->total_out = 0;
239 tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
240 return MZ_OK;
241}
242
243int mz_deflate(mz_streamp pStream, int flush)
244{
245 size_t in_bytes, out_bytes;
246 mz_ulong orig_total_in, orig_total_out;
247 int mz_status = MZ_OK;
248
249 if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
250 return MZ_STREAM_ERROR;
251 if (!pStream->avail_out)
252 return MZ_BUF_ERROR;
253
254 if (flush == MZ_PARTIAL_FLUSH)
255 flush = MZ_SYNC_FLUSH;
256
257 if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
258 return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
259
260 orig_total_in = pStream->total_in;
261 orig_total_out = pStream->total_out;
262 for (;;)
263 {
264 tdefl_status defl_status;
265 in_bytes = pStream->avail_in;
266 out_bytes = pStream->avail_out;
267
268 defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
269 pStream->next_in += (mz_uint)in_bytes;
270 pStream->avail_in -= (mz_uint)in_bytes;
271 pStream->total_in += (mz_uint)in_bytes;
272 pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
273
274 pStream->next_out += (mz_uint)out_bytes;
275 pStream->avail_out -= (mz_uint)out_bytes;
276 pStream->total_out += (mz_uint)out_bytes;
277
278 if (defl_status < 0)
279 {
280 mz_status = MZ_STREAM_ERROR;
281 break;
282 }
283 else if (defl_status == TDEFL_STATUS_DONE)
284 {
285 mz_status = MZ_STREAM_END;
286 break;
287 }
288 else if (!pStream->avail_out)
289 break;
290 else if ((!pStream->avail_in) && (flush != MZ_FINISH))
291 {
292 if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
293 break;
294 return MZ_BUF_ERROR; /* Can't make forward progress without some input.
295 */
296 }
297 }
298 return mz_status;
299}
300
302{
303 if (!pStream)
304 return MZ_STREAM_ERROR;
305 if (pStream->state)
306 {
307 pStream->zfree(pStream->opaque, pStream->state);
308 pStream->state = NULL;
309 }
310 return MZ_OK;
311}
312
314{
315 (void)pStream;
316 /* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */
317 return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
318}
319
320int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
321{
322 int status;
324 memset(&stream, 0, sizeof(stream));
325
326 /* In case mz_ulong is 64-bits (argh I hate longs). */
327 if ((mz_uint64)(source_len | *pDest_len) > 0xFFFFFFFFU)
328 return MZ_PARAM_ERROR;
329
330 stream.next_in = pSource;
331 stream.avail_in = (mz_uint32)source_len;
332 stream.next_out = pDest;
333 stream.avail_out = (mz_uint32)*pDest_len;
334
335 status = mz_deflateInit(&stream, level);
336 if (status != MZ_OK)
337 return status;
338
339 status = mz_deflate(&stream, MZ_FINISH);
340 if (status != MZ_STREAM_END)
341 {
343 return (status == MZ_OK) ? MZ_BUF_ERROR : status;
344 }
345
346 *pDest_len = stream.total_out;
347 return mz_deflateEnd(&stream);
348}
349
350int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
351{
352 return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
353}
354
356{
357 return mz_deflateBound(NULL, source_len);
358}
359
360#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/
361
362#ifndef MINIZ_NO_INFLATE_APIS
363
372
373int mz_inflateInit2(mz_streamp pStream, int window_bits)
374{
375 inflate_state *pDecomp;
376 if (!pStream)
377 return MZ_STREAM_ERROR;
378 if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
379 return MZ_PARAM_ERROR;
380
381 pStream->data_type = 0;
382 pStream->adler = 0;
383 pStream->msg = NULL;
384 pStream->total_in = 0;
385 pStream->total_out = 0;
386 pStream->reserved = 0;
387 if (!pStream->zalloc)
388 pStream->zalloc = miniz_def_alloc_func;
389 if (!pStream->zfree)
390 pStream->zfree = miniz_def_free_func;
391
392 pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
393 if (!pDecomp)
394 return MZ_MEM_ERROR;
395
396 pStream->state = (struct mz_internal_state *)pDecomp;
397
398 tinfl_init(&pDecomp->m_decomp);
399 pDecomp->m_dict_ofs = 0;
400 pDecomp->m_dict_avail = 0;
402 pDecomp->m_first_call = 1;
403 pDecomp->m_has_flushed = 0;
404 pDecomp->m_window_bits = window_bits;
405
406 return MZ_OK;
407}
408
410{
412}
413
415{
416 inflate_state *pDecomp;
417 if (!pStream)
418 return MZ_STREAM_ERROR;
419
420 pStream->data_type = 0;
421 pStream->adler = 0;
422 pStream->msg = NULL;
423 pStream->total_in = 0;
424 pStream->total_out = 0;
425 pStream->reserved = 0;
426
427 pDecomp = (inflate_state *)pStream->state;
428
429 tinfl_init(&pDecomp->m_decomp);
430 pDecomp->m_dict_ofs = 0;
431 pDecomp->m_dict_avail = 0;
433 pDecomp->m_first_call = 1;
434 pDecomp->m_has_flushed = 0;
435 /* pDecomp->m_window_bits = window_bits */;
436
437 return MZ_OK;
438}
439
440int mz_inflate(mz_streamp pStream, int flush)
441{
442 inflate_state *pState;
443 mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
444 size_t in_bytes, out_bytes, orig_avail_in;
445 tinfl_status status;
446
447 if ((!pStream) || (!pStream->state))
448 return MZ_STREAM_ERROR;
449 if (flush == MZ_PARTIAL_FLUSH)
450 flush = MZ_SYNC_FLUSH;
451 if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
452 return MZ_STREAM_ERROR;
453
454 pState = (inflate_state *)pStream->state;
455 if (pState->m_window_bits > 0)
456 decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
457 orig_avail_in = pStream->avail_in;
458
459 first_call = pState->m_first_call;
460 pState->m_first_call = 0;
461 if (pState->m_last_status < 0)
462 return MZ_DATA_ERROR;
463
464 if (pState->m_has_flushed && (flush != MZ_FINISH))
465 return MZ_STREAM_ERROR;
466 pState->m_has_flushed |= (flush == MZ_FINISH);
467
468 if ((flush == MZ_FINISH) && (first_call))
469 {
470 /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
472 in_bytes = pStream->avail_in;
473 out_bytes = pStream->avail_out;
474 status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
475 pState->m_last_status = status;
476 pStream->next_in += (mz_uint)in_bytes;
477 pStream->avail_in -= (mz_uint)in_bytes;
478 pStream->total_in += (mz_uint)in_bytes;
479 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
480 pStream->next_out += (mz_uint)out_bytes;
481 pStream->avail_out -= (mz_uint)out_bytes;
482 pStream->total_out += (mz_uint)out_bytes;
483
484 if (status < 0)
485 return MZ_DATA_ERROR;
486 else if (status != TINFL_STATUS_DONE)
487 {
489 return MZ_BUF_ERROR;
490 }
491 return MZ_STREAM_END;
492 }
493 /* flush != MZ_FINISH then we must assume there's more input. */
494 if (flush != MZ_FINISH)
495 decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
496
497 if (pState->m_dict_avail)
498 {
499 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
500 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
501 pStream->next_out += n;
502 pStream->avail_out -= n;
503 pStream->total_out += n;
504 pState->m_dict_avail -= n;
505 pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
506 return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
507 }
508
509 for (;;)
510 {
511 in_bytes = pStream->avail_in;
512 out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
513
514 status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
515 pState->m_last_status = status;
516
517 pStream->next_in += (mz_uint)in_bytes;
518 pStream->avail_in -= (mz_uint)in_bytes;
519 pStream->total_in += (mz_uint)in_bytes;
520 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
521
522 pState->m_dict_avail = (mz_uint)out_bytes;
523
524 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
525 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
526 pStream->next_out += n;
527 pStream->avail_out -= n;
528 pStream->total_out += n;
529 pState->m_dict_avail -= n;
530 pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
531
532 if (status < 0)
533 return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
534 else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
535 return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
536 else if (flush == MZ_FINISH)
537 {
538 /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
539 if (status == TINFL_STATUS_DONE)
540 return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
541 /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */
542 else if (!pStream->avail_out)
543 return MZ_BUF_ERROR;
544 }
545 else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
546 break;
547 }
548
549 return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
550}
551
553{
554 if (!pStream)
555 return MZ_STREAM_ERROR;
556 if (pStream->state)
557 {
558 pStream->zfree(pStream->opaque, pStream->state);
559 pStream->state = NULL;
560 }
561 return MZ_OK;
562}
563int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len)
564{
566 int status;
567 memset(&stream, 0, sizeof(stream));
568
569 /* In case mz_ulong is 64-bits (argh I hate longs). */
570 if ((mz_uint64)(*pSource_len | *pDest_len) > 0xFFFFFFFFU)
571 return MZ_PARAM_ERROR;
572
573 stream.next_in = pSource;
574 stream.avail_in = (mz_uint32)*pSource_len;
575 stream.next_out = pDest;
576 stream.avail_out = (mz_uint32)*pDest_len;
577
578 status = mz_inflateInit(&stream);
579 if (status != MZ_OK)
580 return status;
581
582 status = mz_inflate(&stream, MZ_FINISH);
583 *pSource_len = *pSource_len - stream.avail_in;
584 if (status != MZ_STREAM_END)
585 {
587 return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
588 }
589 *pDest_len = stream.total_out;
590
591 return mz_inflateEnd(&stream);
592}
593
594int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
595{
596 return mz_uncompress2(pDest, pDest_len, pSource, &source_len);
597}
598
599#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/
600
601const char *mz_error(int err)
602{
603 static struct
604 {
605 int m_err;
606 const char *m_pDesc;
607 } s_error_descs[] =
608 {
609 { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
610 };
611 mz_uint i;
612 for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
613 if (s_error_descs[i].m_err == err)
614 return s_error_descs[i].m_pDesc;
615 return NULL;
616}
617
618#endif /*MINIZ_NO_ZLIB_APIS */
619
620#ifdef __cplusplus
621}
622#endif
623
624/*
625 This is free and unencumbered software released into the public domain.
626
627 Anyone is free to copy, modify, publish, use, compile, sell, or
628 distribute this software, either in source code form or as a compiled
629 binary, for any purpose, commercial or non-commercial, and by any
630 means.
631
632 In jurisdictions that recognize copyright laws, the author or authors
633 of this software dedicate any and all copyright interest in the
634 software to the public domain. We make this dedication for the benefit
635 of the public at large and to the detriment of our heirs and
636 successors. We intend this dedication to be an overt act of
637 relinquishment in perpetuity of all present and future rights to this
638 software under copyright law.
639
640 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
641 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
642 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
643 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
644 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
645 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
646 OTHER DEALINGS IN THE SOFTWARE.
647
648 For more information, please refer to <http://unlicense.org/>
649*/
650/**************************************************************************
651 *
652 * Copyright 2013-2014 RAD Game Tools and Valve Software
653 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
654 * All Rights Reserved.
655 *
656 * Permission is hereby granted, free of charge, to any person obtaining a copy
657 * of this software and associated documentation files (the "Software"), to deal
658 * in the Software without restriction, including without limitation the rights
659 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
660 * copies of the Software, and to permit persons to whom the Software is
661 * furnished to do so, subject to the following conditions:
662 *
663 * The above copyright notice and this permission notice shall be included in
664 * all copies or substantial portions of the Software.
665 *
666 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
667 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
668 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
669 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
670 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
671 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
672 * THE SOFTWARE.
673 *
674 **************************************************************************/
675
676
677
678#ifndef MINIZ_NO_DEFLATE_APIS
679
680#ifdef __cplusplus
681extern "C" {
682#endif
683
684/* ------------------- Low-level Compression (independent from all decompression API's) */
685
686/* Purposely making these tables static for faster init and thread safety. */
687static const mz_uint16 s_tdefl_len_sym[256] =
688 {
689 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,
690 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,
691 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
692 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
693 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
694 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
695 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
696 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285
697 };
698
699static const mz_uint8 s_tdefl_len_extra[256] =
700 {
701 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
702 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
703 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
704 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0
705 };
706
708 {
709 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
710 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,
711 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
712 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
713 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
714 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
715 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
716 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
717 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
718 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
719 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
720 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17
721 };
722
724 {
725 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
726 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
727 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
728 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
729 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
730 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
731 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
732 7, 7, 7, 7, 7, 7, 7, 7
733 };
734
736 {
737 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
738 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
739 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
740 };
741
743 {
744 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
745 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
746 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13
747 };
748
749/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */
750typedef struct
751{
752 mz_uint16 m_key, m_sym_index;
755{
756 mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
757 tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
758 MZ_CLEAR_ARR(hist);
759 for (i = 0; i < num_syms; i++)
760 {
761 mz_uint freq = pSyms0[i].m_key;
762 hist[freq & 0xFF]++;
763 hist[256 + ((freq >> 8) & 0xFF)]++;
764 }
765 while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
766 total_passes--;
767 for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
768 {
769 const mz_uint32 *pHist = &hist[pass << 8];
770 mz_uint offsets[256], cur_ofs = 0;
771 for (i = 0; i < 256; i++)
772 {
773 offsets[i] = cur_ofs;
774 cur_ofs += pHist[i];
775 }
776 for (i = 0; i < num_syms; i++)
777 pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
778 {
779 tdefl_sym_freq *t = pCur_syms;
780 pCur_syms = pNew_syms;
781 pNew_syms = t;
782 }
783 }
784 return pCur_syms;
785}
786
787/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */
789{
790 int root, leaf, next, avbl, used, dpth;
791 if (n == 0)
792 return;
793 else if (n == 1)
794 {
795 A[0].m_key = 1;
796 return;
797 }
798 A[0].m_key += A[1].m_key;
799 root = 0;
800 leaf = 2;
801 for (next = 1; next < n - 1; next++)
802 {
803 if (leaf >= n || A[root].m_key < A[leaf].m_key)
804 {
805 A[next].m_key = A[root].m_key;
806 A[root++].m_key = (mz_uint16)next;
807 }
808 else
809 A[next].m_key = A[leaf++].m_key;
810 if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
811 {
812 A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
813 A[root++].m_key = (mz_uint16)next;
814 }
815 else
816 A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
817 }
818 A[n - 2].m_key = 0;
819 for (next = n - 3; next >= 0; next--)
820 A[next].m_key = A[A[next].m_key].m_key + 1;
821 avbl = 1;
822 used = dpth = 0;
823 root = n - 2;
824 next = n - 1;
825 while (avbl > 0)
826 {
827 while (root >= 0 && (int)A[root].m_key == dpth)
828 {
829 used++;
830 root--;
831 }
832 while (avbl > used)
833 {
834 A[next--].m_key = (mz_uint16)(dpth);
835 avbl--;
836 }
837 avbl = 2 * used;
838 dpth++;
839 used = 0;
840 }
841}
842
843/* Limits canonical Huffman code table's max code size. */
844enum
845{
848static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
849{
850 int i;
851 mz_uint32 total = 0;
852 if (code_list_len <= 1)
853 return;
854 for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
855 pNum_codes[max_code_size] += pNum_codes[i];
856 for (i = max_code_size; i > 0; i--)
857 total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
858 while (total != (1UL << max_code_size))
859 {
860 pNum_codes[max_code_size]--;
861 for (i = max_code_size - 1; i > 0; i--)
862 if (pNum_codes[i])
863 {
864 pNum_codes[i]--;
865 pNum_codes[i + 1] += 2;
866 break;
867 }
868 total--;
869 }
870}
871
872static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
873{
874 int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
876 MZ_CLEAR_ARR(num_codes);
877 if (static_table)
878 {
879 for (i = 0; i < table_len; i++)
880 num_codes[d->m_huff_code_sizes[table_num][i]]++;
881 }
882 else
883 {
885 int num_used_syms = 0;
886 const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
887 for (i = 0; i < table_len; i++)
888 if (pSym_count[i])
889 {
890 syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
891 syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
892 }
893
894 pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
895 tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
896
897 for (i = 0; i < num_used_syms; i++)
898 num_codes[pSyms[i].m_key]++;
899
900 tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
901
902 MZ_CLEAR_ARR(d->m_huff_code_sizes[table_num]);
903 MZ_CLEAR_ARR(d->m_huff_codes[table_num]);
904 for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
905 for (l = num_codes[i]; l > 0; l--)
906 d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
907 }
908
909 next_code[1] = 0;
910 for (j = 0, i = 2; i <= code_size_limit; i++)
911 next_code[i] = j = ((j + num_codes[i - 1]) << 1);
912
913 for (i = 0; i < table_len; i++)
914 {
915 mz_uint rev_code = 0, code, code_size;
916 if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
917 continue;
918 code = next_code[code_size]++;
919 for (l = code_size; l > 0; l--, code >>= 1)
920 rev_code = (rev_code << 1) | (code & 1);
921 d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
922 }
923}
924
925#define TDEFL_PUT_BITS(b, l) \
926 do \
927 { \
928 mz_uint bits = b; \
929 mz_uint len = l; \
930 MZ_ASSERT(bits <= ((1U << len) - 1U)); \
931 d->m_bit_buffer |= (bits << d->m_bits_in); \
932 d->m_bits_in += len; \
933 while (d->m_bits_in >= 8) \
934 { \
935 if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
936 *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
937 d->m_bit_buffer >>= 8; \
938 d->m_bits_in -= 8; \
939 } \
940 } \
941 MZ_MACRO_END
942
943#define TDEFL_RLE_PREV_CODE_SIZE() \
944 { \
945 if (rle_repeat_count) \
946 { \
947 if (rle_repeat_count < 3) \
948 { \
949 d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
950 while (rle_repeat_count--) \
951 packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
952 } \
953 else \
954 { \
955 d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \
956 packed_code_sizes[num_packed_code_sizes++] = 16; \
957 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
958 } \
959 rle_repeat_count = 0; \
960 } \
961 }
962
963#define TDEFL_RLE_ZERO_CODE_SIZE() \
964 { \
965 if (rle_z_count) \
966 { \
967 if (rle_z_count < 3) \
968 { \
969 d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \
970 while (rle_z_count--) \
971 packed_code_sizes[num_packed_code_sizes++] = 0; \
972 } \
973 else if (rle_z_count <= 10) \
974 { \
975 d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \
976 packed_code_sizes[num_packed_code_sizes++] = 17; \
977 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
978 } \
979 else \
980 { \
981 d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \
982 packed_code_sizes[num_packed_code_sizes++] = 18; \
983 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
984 } \
985 rle_z_count = 0; \
986 } \
987 }
988
989static const mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
990
992{
993 int num_lit_codes, num_dist_codes, num_bit_lengths;
994 mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
995 mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
996
997 d->m_huff_count[0][256] = 1;
998
1001
1002 for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
1003 if (d->m_huff_code_sizes[0][num_lit_codes - 1])
1004 break;
1005 for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
1006 if (d->m_huff_code_sizes[1][num_dist_codes - 1])
1007 break;
1008
1009 memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
1010 memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
1011 total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
1012 num_packed_code_sizes = 0;
1013 rle_z_count = 0;
1014 rle_repeat_count = 0;
1015
1016 memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
1017 for (i = 0; i < total_code_sizes_to_pack; i++)
1018 {
1019 mz_uint8 code_size = code_sizes_to_pack[i];
1020 if (!code_size)
1021 {
1023 if (++rle_z_count == 138)
1024 {
1026 }
1027 }
1028 else
1029 {
1031 if (code_size != prev_code_size)
1032 {
1034 d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
1035 packed_code_sizes[num_packed_code_sizes++] = code_size;
1036 }
1037 else if (++rle_repeat_count == 6)
1038 {
1040 }
1041 }
1042 prev_code_size = code_size;
1043 }
1044 if (rle_repeat_count)
1045 {
1047 }
1048 else
1049 {
1051 }
1052
1054
1055 TDEFL_PUT_BITS(2, 2);
1056
1057 TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1058 TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1059
1060 for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
1061 if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
1062 break;
1063 num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
1064 TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1065 for (i = 0; (int)i < num_bit_lengths; i++)
1067
1068 for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
1069 {
1070 mz_uint code = packed_code_sizes[packed_code_sizes_index++];
1072 TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1073 if (code >= 16)
1074 TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1075 }
1076}
1077
1079{
1080 mz_uint i;
1081 mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1082
1083 for (i = 0; i <= 143; ++i)
1084 *p++ = 8;
1085 for (; i <= 255; ++i)
1086 *p++ = 9;
1087 for (; i <= 279; ++i)
1088 *p++ = 7;
1089 for (; i <= 287; ++i)
1090 *p++ = 8;
1091
1092 memset(d->m_huff_code_sizes[1], 5, 32);
1093
1094 tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1096
1097 TDEFL_PUT_BITS(1, 2);
1098}
1099
1100static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1101
1102#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
1104{
1105 mz_uint flags;
1106 mz_uint8 *pLZ_codes;
1107 mz_uint8 *pOutput_buf = d->m_pOutput_buf;
1108 mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
1109 mz_uint64 bit_buffer = d->m_bit_buffer;
1110 mz_uint bits_in = d->m_bits_in;
1111
1112#define TDEFL_PUT_BITS_FAST(b, l) \
1113 { \
1114 bit_buffer |= (((mz_uint64)(b)) << bits_in); \
1115 bits_in += (l); \
1116 }
1117
1118 flags = 1;
1119 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
1120 {
1121 if (flags == 1)
1122 flags = *pLZ_codes++ | 0x100;
1123
1124 if (flags & 1)
1125 {
1126 mz_uint s0, s1, n0, n1, sym, num_extra_bits;
1127 mz_uint match_len = pLZ_codes[0];
1128 mz_uint match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1129 pLZ_codes += 3;
1130
1131 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1132 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1133 TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1134
1135 /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
1136 s0 = s_tdefl_small_dist_sym[match_dist & 511];
1137 n0 = s_tdefl_small_dist_extra[match_dist & 511];
1138 s1 = s_tdefl_large_dist_sym[match_dist >> 8];
1139 n1 = s_tdefl_large_dist_extra[match_dist >> 8];
1140 sym = (match_dist < 512) ? s0 : s1;
1141 num_extra_bits = (match_dist < 512) ? n0 : n1;
1142
1143 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1144 TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1145 TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1146 }
1147 else
1148 {
1149 mz_uint lit = *pLZ_codes++;
1150 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1151 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1152
1153 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1154 {
1155 flags >>= 1;
1156 lit = *pLZ_codes++;
1157 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1158 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1159
1160 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1161 {
1162 flags >>= 1;
1163 lit = *pLZ_codes++;
1164 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1165 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1166 }
1167 }
1168 }
1169
1170 if (pOutput_buf >= d->m_pOutput_buf_end)
1171 return MZ_FALSE;
1172
1173 memcpy(pOutput_buf, &bit_buffer, sizeof(mz_uint64));
1174 pOutput_buf += (bits_in >> 3);
1175 bit_buffer >>= (bits_in & ~7);
1176 bits_in &= 7;
1177 }
1178
1179#undef TDEFL_PUT_BITS_FAST
1180
1181 d->m_pOutput_buf = pOutput_buf;
1182 d->m_bits_in = 0;
1183 d->m_bit_buffer = 0;
1184
1185 while (bits_in)
1186 {
1187 mz_uint32 n = MZ_MIN(bits_in, 16);
1188 TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
1189 bit_buffer >>= n;
1190 bits_in -= n;
1191 }
1192
1193 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1194
1195 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1196}
1197#else
1199{
1200 mz_uint flags;
1201 mz_uint8 *pLZ_codes;
1202
1203 flags = 1;
1204 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1205 {
1206 if (flags == 1)
1207 flags = *pLZ_codes++ | 0x100;
1208 if (flags & 1)
1209 {
1210 mz_uint sym, num_extra_bits;
1211 mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1212 pLZ_codes += 3;
1213
1214 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1215 TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1216 TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1217
1218 if (match_dist < 512)
1219 {
1220 sym = s_tdefl_small_dist_sym[match_dist];
1221 num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1222 }
1223 else
1224 {
1225 sym = s_tdefl_large_dist_sym[match_dist >> 8];
1226 num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1227 }
1228 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1229 TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1230 TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1231 }
1232 else
1233 {
1234 mz_uint lit = *pLZ_codes++;
1235 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1236 TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1237 }
1238 }
1239
1240 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1241
1242 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1243}
1244#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */
1245
1247{
1248 if (static_block)
1250 else
1252 return tdefl_compress_lz_codes(d);
1253}
1254
1256
1257static int tdefl_flush_block(tdefl_compressor *d, int flush)
1258{
1259 mz_uint saved_bit_buf, saved_bits_in;
1260 mz_uint8 *pSaved_output_buf;
1261 mz_bool comp_block_succeeded = MZ_FALSE;
1262 int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
1263 mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
1264
1265 d->m_pOutput_buf = pOutput_buf_start;
1267
1269 d->m_output_flush_ofs = 0;
1271
1273 d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1274
1275 if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1276 {
1277 const mz_uint8 cmf = 0x78;
1278 mz_uint8 flg, flevel = 3;
1279 mz_uint header, i, mz_un = sizeof(s_tdefl_num_probes) / sizeof(mz_uint);
1280
1281 /* Determine compression level by reversing the process in tdefl_create_comp_flags_from_zip_params() */
1282 for (i = 0; i < mz_un; i++)
1283 if (s_tdefl_num_probes[i] == (d->m_flags & 0xFFF)) break;
1284
1285 if (i < 2)
1286 flevel = 0;
1287 else if (i < 6)
1288 flevel = 1;
1289 else if (i == 6)
1290 flevel = 2;
1291
1292 header = cmf << 8 | (flevel << 6);
1293 header += 31 - (header % 31);
1294 flg = header & 0xFF;
1295
1296 TDEFL_PUT_BITS(cmf, 8);
1297 TDEFL_PUT_BITS(flg, 8);
1298 }
1299
1300 TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1301
1302 pSaved_output_buf = d->m_pOutput_buf;
1303 saved_bit_buf = d->m_bit_buffer;
1304 saved_bits_in = d->m_bits_in;
1305
1306 if (!use_raw_block)
1307 comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
1308
1309 /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */
1310 if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
1312 {
1313 mz_uint i;
1314 d->m_pOutput_buf = pSaved_output_buf;
1315 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1316 TDEFL_PUT_BITS(0, 2);
1317 if (d->m_bits_in)
1318 {
1319 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1320 }
1321 for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1322 {
1323 TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1324 }
1325 for (i = 0; i < d->m_total_lz_bytes; ++i)
1326 {
1328 }
1329 }
1330 /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */
1331 else if (!comp_block_succeeded)
1332 {
1333 d->m_pOutput_buf = pSaved_output_buf;
1334 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1336 }
1337
1338 if (flush)
1339 {
1340 if (flush == TDEFL_FINISH)
1341 {
1342 if (d->m_bits_in)
1343 {
1344 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1345 }
1347 {
1348 mz_uint i, a = d->m_adler32;
1349 for (i = 0; i < 4; i++)
1350 {
1351 TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
1352 a <<= 8;
1353 }
1354 }
1355 }
1356 else
1357 {
1358 mz_uint i, z = 0;
1359 TDEFL_PUT_BITS(0, 3);
1360 if (d->m_bits_in)
1361 {
1362 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1363 }
1364 for (i = 2; i; --i, z ^= 0xFFFF)
1365 {
1366 TDEFL_PUT_BITS(z & 0xFFFF, 16);
1367 }
1368 }
1369 }
1370
1372
1373 memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1374 memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1375
1376 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1377 d->m_pLZ_flags = d->m_lz_code_buf;
1378 d->m_num_flags_left = 8;
1380 d->m_total_lz_bytes = 0;
1381 d->m_block_index++;
1382
1383 if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1384 {
1385 if (d->m_pPut_buf_func)
1386 {
1387 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1388 if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
1390 }
1391 else if (pOutput_buf_start == d->m_output_buf)
1392 {
1393 int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1394 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1395 d->m_out_buf_ofs += bytes_to_copy;
1396 if ((n -= bytes_to_copy) != 0)
1397 {
1398 d->m_output_flush_ofs = bytes_to_copy;
1400 }
1401 }
1402 else
1403 {
1404 d->m_out_buf_ofs += n;
1405 }
1406 }
1407
1408 return d->m_output_flush_remaining;
1409}
1410
1411#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1412#ifdef MINIZ_UNALIGNED_USE_MEMCPY
1413static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p)
1414{
1415 mz_uint16 ret;
1416 memcpy(&ret, p, sizeof(mz_uint16));
1417 return ret;
1418}
1419static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p)
1420{
1421 mz_uint16 ret;
1422 memcpy(&ret, p, sizeof(mz_uint16));
1423 return ret;
1424}
1425#else
1426#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
1427#define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
1428#endif
1429static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1430{
1431 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1432 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1433 const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
1434 mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s);
1435 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1436 if (max_match_len <= match_len)
1437 return;
1438 for (;;)
1439 {
1440 for (;;)
1441 {
1442 if (--num_probes_left == 0)
1443 return;
1444#define TDEFL_PROBE \
1445 next_probe_pos = d->m_next[probe_pos]; \
1446 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1447 return; \
1448 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1449 if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
1450 break;
1454 }
1455 if (!dist)
1456 break;
1457 q = (const mz_uint16 *)(d->m_dict + probe_pos);
1458 if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)
1459 continue;
1460 p = s;
1461 probe_len = 32;
1462 do
1463 {
1464 } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1465 (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1466 if (!probe_len)
1467 {
1468 *pMatch_dist = dist;
1469 *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
1470 break;
1471 }
1472 else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len)
1473 {
1474 *pMatch_dist = dist;
1475 if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)
1476 break;
1477 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
1478 }
1479 }
1480}
1481#else
1482static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1483{
1484 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1485 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1486 const mz_uint8 *s = d->m_dict + pos, *p, *q;
1487 mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1488 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1489 if (max_match_len <= match_len)
1490 return;
1491 for (;;)
1492 {
1493 for (;;)
1494 {
1495 if (--num_probes_left == 0)
1496 return;
1497#define TDEFL_PROBE \
1498 next_probe_pos = d->m_next[probe_pos]; \
1499 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1500 return; \
1501 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1502 if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
1503 break;
1507 }
1508 if (!dist)
1509 break;
1510 p = s;
1511 q = d->m_dict + probe_pos;
1512 for (probe_len = 0; probe_len < max_match_len; probe_len++)
1513 if (*p++ != *q++)
1514 break;
1515 if (probe_len > match_len)
1516 {
1517 *pMatch_dist = dist;
1518 if ((*pMatch_len = match_len = probe_len) == max_match_len)
1519 return;
1520 c0 = d->m_dict[pos + match_len];
1521 c1 = d->m_dict[pos + match_len - 1];
1522 }
1523 }
1524}
1525#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
1526
1527#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1528#ifdef MINIZ_UNALIGNED_USE_MEMCPY
1529static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p)
1530{
1531 mz_uint32 ret;
1532 memcpy(&ret, p, sizeof(mz_uint32));
1533 return ret;
1534}
1535#else
1536#define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p)
1537#endif
1538static mz_bool tdefl_compress_fast(tdefl_compressor *d)
1539{
1540 /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */
1541 mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
1542 mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
1543 mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1544
1545 while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
1546 {
1547 const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
1548 mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1549 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
1550 d->m_src_buf_left -= num_bytes_to_process;
1551 lookahead_size += num_bytes_to_process;
1552
1553 while (num_bytes_to_process)
1554 {
1555 mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
1556 memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
1557 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1558 memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
1559 d->m_pSrc += n;
1560 dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
1561 num_bytes_to_process -= n;
1562 }
1563
1564 dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
1565 if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
1566 break;
1567
1568 while (lookahead_size >= 4)
1569 {
1570 mz_uint cur_match_dist, cur_match_len = 1;
1571 mz_uint8 *pCur_dict = d->m_dict + cur_pos;
1572 mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF;
1573 mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
1574 mz_uint probe_pos = d->m_hash[hash];
1575 d->m_hash[hash] = (mz_uint16)lookahead_pos;
1576
1577 if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((TDEFL_READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
1578 {
1579 const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
1580 const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
1581 mz_uint32 probe_len = 32;
1582 do
1583 {
1584 } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1585 (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1586 cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
1587 if (!probe_len)
1588 cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
1589
1590 if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))
1591 {
1592 cur_match_len = 1;
1593 *pLZ_code_buf++ = (mz_uint8)first_trigram;
1594 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1595 d->m_huff_count[0][(mz_uint8)first_trigram]++;
1596 }
1597 else
1598 {
1599 mz_uint32 s0, s1;
1600 cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
1601
1602 MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
1603
1604 cur_match_dist--;
1605
1606 pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
1607#ifdef MINIZ_UNALIGNED_USE_MEMCPY
1608 memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist));
1609#else
1610 *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
1611#endif
1612 pLZ_code_buf += 3;
1613 *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
1614
1615 s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
1616 s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
1617 d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
1618
1619 d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
1620 }
1621 }
1622 else
1623 {
1624 *pLZ_code_buf++ = (mz_uint8)first_trigram;
1625 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1626 d->m_huff_count[0][(mz_uint8)first_trigram]++;
1627 }
1628
1629 if (--num_flags_left == 0)
1630 {
1631 num_flags_left = 8;
1632 pLZ_flags = pLZ_code_buf++;
1633 }
1634
1635 total_lz_bytes += cur_match_len;
1636 lookahead_pos += cur_match_len;
1637 dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
1638 cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
1639 MZ_ASSERT(lookahead_size >= cur_match_len);
1640 lookahead_size -= cur_match_len;
1641
1642 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1643 {
1644 int n;
1645 d->m_lookahead_pos = lookahead_pos;
1646 d->m_lookahead_size = lookahead_size;
1647 d->m_dict_size = dict_size;
1648 d->m_total_lz_bytes = total_lz_bytes;
1649 d->m_pLZ_code_buf = pLZ_code_buf;
1650 d->m_pLZ_flags = pLZ_flags;
1651 d->m_num_flags_left = num_flags_left;
1652 if ((n = tdefl_flush_block(d, 0)) != 0)
1653 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1654 total_lz_bytes = d->m_total_lz_bytes;
1655 pLZ_code_buf = d->m_pLZ_code_buf;
1656 pLZ_flags = d->m_pLZ_flags;
1657 num_flags_left = d->m_num_flags_left;
1658 }
1659 }
1660
1661 while (lookahead_size)
1662 {
1663 mz_uint8 lit = d->m_dict[cur_pos];
1664
1665 total_lz_bytes++;
1666 *pLZ_code_buf++ = lit;
1667 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1668 if (--num_flags_left == 0)
1669 {
1670 num_flags_left = 8;
1671 pLZ_flags = pLZ_code_buf++;
1672 }
1673
1674 d->m_huff_count[0][lit]++;
1675
1676 lookahead_pos++;
1677 dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
1678 cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1679 lookahead_size--;
1680
1681 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1682 {
1683 int n;
1684 d->m_lookahead_pos = lookahead_pos;
1685 d->m_lookahead_size = lookahead_size;
1686 d->m_dict_size = dict_size;
1687 d->m_total_lz_bytes = total_lz_bytes;
1688 d->m_pLZ_code_buf = pLZ_code_buf;
1689 d->m_pLZ_flags = pLZ_flags;
1690 d->m_num_flags_left = num_flags_left;
1691 if ((n = tdefl_flush_block(d, 0)) != 0)
1692 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1693 total_lz_bytes = d->m_total_lz_bytes;
1694 pLZ_code_buf = d->m_pLZ_code_buf;
1695 pLZ_flags = d->m_pLZ_flags;
1696 num_flags_left = d->m_num_flags_left;
1697 }
1698 }
1699 }
1700
1701 d->m_lookahead_pos = lookahead_pos;
1702 d->m_lookahead_size = lookahead_size;
1703 d->m_dict_size = dict_size;
1704 d->m_total_lz_bytes = total_lz_bytes;
1705 d->m_pLZ_code_buf = pLZ_code_buf;
1706 d->m_pLZ_flags = pLZ_flags;
1707 d->m_num_flags_left = num_flags_left;
1708 return MZ_TRUE;
1709}
1710#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1711
1713{
1714 d->m_total_lz_bytes++;
1715 *d->m_pLZ_code_buf++ = lit;
1716 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
1717 if (--d->m_num_flags_left == 0)
1718 {
1719 d->m_num_flags_left = 8;
1720 d->m_pLZ_flags = d->m_pLZ_code_buf++;
1721 }
1722 d->m_huff_count[0][lit]++;
1723}
1724
1726{
1727 mz_uint32 s0, s1;
1728
1729 MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1730
1731 d->m_total_lz_bytes += match_len;
1732
1733 d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1734
1735 match_dist -= 1;
1736 d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1737 d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
1738 d->m_pLZ_code_buf += 3;
1739
1740 *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
1741 if (--d->m_num_flags_left == 0)
1742 {
1743 d->m_num_flags_left = 8;
1744 d->m_pLZ_flags = d->m_pLZ_code_buf++;
1745 }
1746
1747 s0 = s_tdefl_small_dist_sym[match_dist & 511];
1748 s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1749 d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1750 d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1751}
1752
1754{
1755 const mz_uint8 *pSrc = d->m_pSrc;
1756 size_t src_buf_left = d->m_src_buf_left;
1757 tdefl_flush flush = d->m_flush;
1758
1759 while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1760 {
1761 mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
1762 /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */
1763 if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1764 {
1766 mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
1767 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1768 const mz_uint8 *pSrc_end = pSrc ? pSrc + num_bytes_to_process : NULL;
1769 src_buf_left -= num_bytes_to_process;
1770 d->m_lookahead_size += num_bytes_to_process;
1771 while (pSrc != pSrc_end)
1772 {
1773 mz_uint8 c = *pSrc++;
1774 d->m_dict[dst_pos] = c;
1775 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1776 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1777 hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1778 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1779 d->m_hash[hash] = (mz_uint16)(ins_pos);
1780 dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1781 ins_pos++;
1782 }
1783 }
1784 else
1785 {
1786 while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1787 {
1788 mz_uint8 c = *pSrc++;
1790 src_buf_left--;
1791 d->m_dict[dst_pos] = c;
1792 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1793 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1795 {
1796 mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1797 mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1798 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1799 d->m_hash[hash] = (mz_uint16)(ins_pos);
1800 }
1801 }
1802 }
1804 if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1805 break;
1806
1807 /* Simple lazy/greedy parsing state machine. */
1808 len_to_move = 1;
1809 cur_match_dist = 0;
1810 cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
1813 {
1814 if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1815 {
1816 mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1817 cur_match_len = 0;
1818 while (cur_match_len < d->m_lookahead_size)
1819 {
1820 if (d->m_dict[cur_pos + cur_match_len] != c)
1821 break;
1822 cur_match_len++;
1823 }
1824 if (cur_match_len < TDEFL_MIN_MATCH_LEN)
1825 cur_match_len = 0;
1826 else
1827 cur_match_dist = 1;
1828 }
1829 }
1830 else
1831 {
1832 tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1833 }
1834 if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
1835 {
1836 cur_match_dist = cur_match_len = 0;
1837 }
1838 if (d->m_saved_match_len)
1839 {
1840 if (cur_match_len > d->m_saved_match_len)
1841 {
1843 if (cur_match_len >= 128)
1844 {
1845 tdefl_record_match(d, cur_match_len, cur_match_dist);
1846 d->m_saved_match_len = 0;
1847 len_to_move = cur_match_len;
1848 }
1849 else
1850 {
1851 d->m_saved_lit = d->m_dict[cur_pos];
1852 d->m_saved_match_dist = cur_match_dist;
1853 d->m_saved_match_len = cur_match_len;
1854 }
1855 }
1856 else
1857 {
1859 len_to_move = d->m_saved_match_len - 1;
1860 d->m_saved_match_len = 0;
1861 }
1862 }
1863 else if (!cur_match_dist)
1864 tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
1865 else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1866 {
1867 tdefl_record_match(d, cur_match_len, cur_match_dist);
1868 len_to_move = cur_match_len;
1869 }
1870 else
1871 {
1872 d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
1873 d->m_saved_match_dist = cur_match_dist;
1874 d->m_saved_match_len = cur_match_len;
1875 }
1876 /* Move the lookahead forward by len_to_move bytes. */
1877 d->m_lookahead_pos += len_to_move;
1878 MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1879 d->m_lookahead_size -= len_to_move;
1880 d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
1881 /* Check if it's time to flush the current LZ codes to the internal output buffer. */
1883 ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))))
1884 {
1885 int n;
1886 d->m_pSrc = pSrc;
1887 d->m_src_buf_left = src_buf_left;
1888 if ((n = tdefl_flush_block(d, 0)) != 0)
1889 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1890 }
1891 }
1892
1893 d->m_pSrc = pSrc;
1894 d->m_src_buf_left = src_buf_left;
1895 return MZ_TRUE;
1896}
1897
1899{
1900 if (d->m_pIn_buf_size)
1901 {
1902 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1903 }
1904
1905 if (d->m_pOut_buf_size)
1906 {
1908 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1909 d->m_output_flush_ofs += (mz_uint)n;
1911 d->m_out_buf_ofs += n;
1912
1914 }
1915
1917}
1918
1919tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
1920{
1921 if (!d)
1922 {
1923 if (pIn_buf_size)
1924 *pIn_buf_size = 0;
1925 if (pOut_buf_size)
1926 *pOut_buf_size = 0;
1928 }
1929
1930 d->m_pIn_buf = pIn_buf;
1931 d->m_pIn_buf_size = pIn_buf_size;
1932 d->m_pOut_buf = pOut_buf;
1933 d->m_pOut_buf_size = pOut_buf_size;
1934 d->m_pSrc = (const mz_uint8 *)(pIn_buf);
1935 d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1936 d->m_out_buf_ofs = 0;
1937 d->m_flush = flush;
1938
1939 if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1940 (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
1941 {
1942 if (pIn_buf_size)
1943 *pIn_buf_size = 0;
1944 if (pOut_buf_size)
1945 *pOut_buf_size = 0;
1947 }
1948 d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1949
1950 if ((d->m_output_flush_remaining) || (d->m_finished))
1952
1953#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1954 if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
1955 ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
1957 {
1958 if (!tdefl_compress_fast(d))
1959 return d->m_prev_return_status;
1960 }
1961 else
1962#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1963 {
1964 if (!tdefl_compress_normal(d))
1965 return d->m_prev_return_status;
1966 }
1967
1968 if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1969 d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
1970
1971 if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1972 {
1973 if (tdefl_flush_block(d, flush) < 0)
1974 return d->m_prev_return_status;
1975 d->m_finished = (flush == TDEFL_FINISH);
1976 if (flush == TDEFL_FULL_FLUSH)
1977 {
1978 MZ_CLEAR_ARR(d->m_hash);
1979 MZ_CLEAR_ARR(d->m_next);
1980 d->m_dict_size = 0;
1981 }
1982 }
1983
1985}
1986
1987tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
1988{
1990 return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1991}
1992
1993tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1994{
1995 d->m_pPut_buf_func = pPut_buf_func;
1996 d->m_pPut_buf_user = pPut_buf_user;
1997 d->m_flags = (mz_uint)(flags);
1998 d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
1999 d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
2000 d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
2002 MZ_CLEAR_ARR(d->m_hash);
2005 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
2006 d->m_pLZ_flags = d->m_lz_code_buf;
2007 *d->m_pLZ_flags = 0;
2008 d->m_num_flags_left = 8;
2013 d->m_adler32 = 1;
2014 d->m_pIn_buf = NULL;
2015 d->m_pOut_buf = NULL;
2016 d->m_pIn_buf_size = NULL;
2017 d->m_pOut_buf_size = NULL;
2019 d->m_pSrc = NULL;
2020 d->m_src_buf_left = 0;
2021 d->m_out_buf_ofs = 0;
2023 MZ_CLEAR_ARR(d->m_dict);
2024 memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
2025 memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
2026 return TDEFL_STATUS_OKAY;
2027}
2028
2033
2038
2039mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2040{
2041 tdefl_compressor *pComp;
2042 mz_bool succeeded;
2043 if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
2044 return MZ_FALSE;
2045 pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2046 if (!pComp)
2047 return MZ_FALSE;
2048 succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
2049 succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
2050 MZ_FREE(pComp);
2051 return succeeded;
2052}
2053
2060
2061static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
2062{
2064 size_t new_size = p->m_size + len;
2065 if (new_size > p->m_capacity)
2066 {
2067 size_t new_capacity = p->m_capacity;
2068 mz_uint8 *pNew_buf;
2069 if (!p->m_expandable)
2070 return MZ_FALSE;
2071 do
2072 {
2073 new_capacity = MZ_MAX(128U, new_capacity << 1U);
2074 } while (new_size > new_capacity);
2075 pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
2076 if (!pNew_buf)
2077 return MZ_FALSE;
2078 p->m_pBuf = pNew_buf;
2079 p->m_capacity = new_capacity;
2080 }
2081 memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
2082 p->m_size = new_size;
2083 return MZ_TRUE;
2084}
2085
2086void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2087{
2088 tdefl_output_buffer out_buf;
2089 MZ_CLEAR_OBJ(out_buf);
2090 if (!pOut_len)
2091 return MZ_FALSE;
2092 else
2093 *pOut_len = 0;
2094 out_buf.m_expandable = MZ_TRUE;
2095 if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2096 return NULL;
2097 *pOut_len = out_buf.m_size;
2098 return out_buf.m_pBuf;
2099}
2100
2101size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2102{
2103 tdefl_output_buffer out_buf;
2104 MZ_CLEAR_OBJ(out_buf);
2105 if (!pOut_buf)
2106 return 0;
2107 out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
2108 out_buf.m_capacity = out_buf_len;
2109 if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2110 return 0;
2111 return out_buf.m_size;
2112}
2113
2114static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2115
2116/* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */
2117mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
2118{
2119 mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2120 if (window_bits > 0)
2121 comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2122
2123 if (!level)
2124 comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2125 else if (strategy == MZ_FILTERED)
2126 comp_flags |= TDEFL_FILTER_MATCHES;
2127 else if (strategy == MZ_HUFFMAN_ONLY)
2128 comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2129 else if (strategy == MZ_FIXED)
2130 comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2131 else if (strategy == MZ_RLE)
2132 comp_flags |= TDEFL_RLE_MATCHES;
2133
2134 return comp_flags;
2135}
2136
2137#ifdef _MSC_VER
2138#pragma warning(push)
2139#pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */
2140#endif
2141
2142/* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
2143 http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
2144 This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */
2145void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
2146{
2147 /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */
2148 static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2150 tdefl_output_buffer out_buf;
2151 int i, bpl = w * num_chans, y, z;
2152 mz_uint32 c;
2153 *pLen_out = 0;
2154 if (!pComp)
2155 return NULL;
2156 MZ_CLEAR_OBJ(out_buf);
2157 out_buf.m_expandable = MZ_TRUE;
2158 out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
2159 if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
2160 {
2161 MZ_FREE(pComp);
2162 return NULL;
2163 }
2164 /* write dummy header */
2165 for (z = 41; z; --z)
2166 tdefl_output_buffer_putter(&z, 1, &out_buf);
2167 /* compress image data */
2168 tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2169 for (y = 0; y < h; ++y)
2170 {
2172 tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
2173 }
2175 {
2176 MZ_FREE(pComp);
2177 MZ_FREE(out_buf.m_pBuf);
2178 return NULL;
2179 }
2180 /* write real header */
2181 *pLen_out = out_buf.m_size - 41;
2182 {
2183 static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
2184 mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
2185 0x0a, 0x1a, 0x0a, 0x00, 0x00,
2186 0x00, 0x0d, 0x49, 0x48, 0x44,
2187 0x52, 0x00, 0x00, 0x00, 0x00,
2188 0x00, 0x00, 0x00, 0x00, 0x08,
2189 0x00, 0x00, 0x00, 0x00, 0x00,
2190 0x00, 0x00, 0x00, 0x00, 0x00,
2191 0x00, 0x00, 0x49, 0x44, 0x41,
2192 0x54 };
2193 pnghdr[18] = (mz_uint8)(w >> 8);
2194 pnghdr[19] = (mz_uint8)w;
2195 pnghdr[22] = (mz_uint8)(h >> 8);
2196 pnghdr[23] = (mz_uint8)h;
2197 pnghdr[25] = chans[num_chans];
2198 pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
2199 pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
2200 pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
2201 pnghdr[36] = (mz_uint8)*pLen_out;
2202 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
2203 for (i = 0; i < 4; ++i, c <<= 8)
2204 ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
2205 memcpy(out_buf.m_pBuf, pnghdr, 41);
2206 }
2207 /* write footer (IDAT CRC-32, followed by IEND chunk) */
2208 if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf))
2209 {
2210 *pLen_out = 0;
2211 MZ_FREE(pComp);
2212 MZ_FREE(out_buf.m_pBuf);
2213 return NULL;
2214 }
2215 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
2216 for (i = 0; i < 4; ++i, c <<= 8)
2217 (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
2218 /* compute final size of file, grab compressed data buffer and return */
2219 *pLen_out += 57;
2220 MZ_FREE(pComp);
2221 return out_buf.m_pBuf;
2222}
2223void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
2224{
2225 /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */
2226 return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2227}
2228
2229#ifndef MINIZ_NO_MALLOC
2230/* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */
2231/* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
2232/* structure size and allocation mechanism. */
2237
2239{
2240 MZ_FREE(pComp);
2241}
2242#endif
2243
2244#ifdef _MSC_VER
2245#pragma warning(pop)
2246#endif
2247
2248#ifdef __cplusplus
2249}
2250#endif
2251
2252#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/
2253 /**************************************************************************
2254 *
2255 * Copyright 2013-2014 RAD Game Tools and Valve Software
2256 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2257 * All Rights Reserved.
2258 *
2259 * Permission is hereby granted, free of charge, to any person obtaining a copy
2260 * of this software and associated documentation files (the "Software"), to deal
2261 * in the Software without restriction, including without limitation the rights
2262 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2263 * copies of the Software, and to permit persons to whom the Software is
2264 * furnished to do so, subject to the following conditions:
2265 *
2266 * The above copyright notice and this permission notice shall be included in
2267 * all copies or substantial portions of the Software.
2268 *
2269 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2270 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2271 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2272 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2273 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2274 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2275 * THE SOFTWARE.
2276 *
2277 **************************************************************************/
2278
2279
2280
2281#ifndef MINIZ_NO_INFLATE_APIS
2282
2283#ifdef __cplusplus
2284extern "C" {
2285#endif
2286
2287/* ------------------- Low-level Decompression (completely independent from all compression API's) */
2288
2289#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2290#define TINFL_MEMSET(p, c, l) memset(p, c, l)
2291
2292#define TINFL_CR_BEGIN \
2293 switch (r->m_state) \
2294 { \
2295 case 0:
2296#define TINFL_CR_RETURN(state_index, result) \
2297 do \
2298 { \
2299 status = result; \
2300 r->m_state = state_index; \
2301 goto common_exit; \
2302 case state_index:; \
2303 } \
2304 MZ_MACRO_END
2305#define TINFL_CR_RETURN_FOREVER(state_index, result) \
2306 do \
2307 { \
2308 for (;;) \
2309 { \
2310 TINFL_CR_RETURN(state_index, result); \
2311 } \
2312 } \
2313 MZ_MACRO_END
2314#define TINFL_CR_FINISH }
2315
2316#define TINFL_GET_BYTE(state_index, c) \
2317 do \
2318 { \
2319 while (pIn_buf_cur >= pIn_buf_end) \
2320 { \
2321 TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
2322 } \
2323 c = *pIn_buf_cur++; \
2324 } \
2325 MZ_MACRO_END
2326
2327#define TINFL_NEED_BITS(state_index, n) \
2328 do \
2329 { \
2330 mz_uint c; \
2331 TINFL_GET_BYTE(state_index, c); \
2332 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2333 num_bits += 8; \
2334 } while (num_bits < (mz_uint)(n))
2335#define TINFL_SKIP_BITS(state_index, n) \
2336 do \
2337 { \
2338 if (num_bits < (mz_uint)(n)) \
2339 { \
2340 TINFL_NEED_BITS(state_index, n); \
2341 } \
2342 bit_buf >>= (n); \
2343 num_bits -= (n); \
2344 } \
2345 MZ_MACRO_END
2346#define TINFL_GET_BITS(state_index, b, n) \
2347 do \
2348 { \
2349 if (num_bits < (mz_uint)(n)) \
2350 { \
2351 TINFL_NEED_BITS(state_index, n); \
2352 } \
2353 b = bit_buf & ((1 << (n)) - 1); \
2354 bit_buf >>= (n); \
2355 num_bits -= (n); \
2356 } \
2357 MZ_MACRO_END
2358
2359/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
2360/* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */
2361/* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */
2362/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
2363#define TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree) \
2364 do \
2365 { \
2366 temp = pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
2367 if (temp >= 0) \
2368 { \
2369 code_len = temp >> 9; \
2370 if ((code_len) && (num_bits >= code_len)) \
2371 break; \
2372 } \
2373 else if (num_bits > TINFL_FAST_LOOKUP_BITS) \
2374 { \
2375 code_len = TINFL_FAST_LOOKUP_BITS; \
2376 do \
2377 { \
2378 temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \
2379 } while ((temp < 0) && (num_bits >= (code_len + 1))); \
2380 if (temp >= 0) \
2381 break; \
2382 } \
2383 TINFL_GET_BYTE(state_index, c); \
2384 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2385 num_bits += 8; \
2386 } while (num_bits < 15);
2387
2388/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */
2389/* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */
2390/* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */
2391/* The slow path is only executed at the very end of the input buffer. */
2392/* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */
2393/* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
2394#define TINFL_HUFF_DECODE(state_index, sym, pLookUp, pTree) \
2395 do \
2396 { \
2397 int temp; \
2398 mz_uint code_len, c; \
2399 if (num_bits < 15) \
2400 { \
2401 if ((pIn_buf_end - pIn_buf_cur) < 2) \
2402 { \
2403 TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree); \
2404 } \
2405 else \
2406 { \
2407 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
2408 pIn_buf_cur += 2; \
2409 num_bits += 16; \
2410 } \
2411 } \
2412 if ((temp = pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
2413 code_len = temp >> 9, temp &= 511; \
2414 else \
2415 { \
2416 code_len = TINFL_FAST_LOOKUP_BITS; \
2417 do \
2418 { \
2419 temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \
2420 } while (temp < 0); \
2421 } \
2422 sym = temp; \
2423 bit_buf >>= code_len; \
2424 num_bits -= code_len; \
2425 } \
2426 MZ_MACRO_END
2427
2429{
2430 if (r->m_type == 0)
2432 else if (r->m_type == 1)
2434 else
2436}
2437
2438tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
2439{
2440 static const mz_uint16 s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };
2441 static const mz_uint8 s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };
2442 static const mz_uint16 s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };
2443 static const mz_uint8 s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
2444 static const mz_uint8 s_length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
2445 static const mz_uint16 s_min_table_sizes[3] = { 257, 1, 4 };
2446
2447 mz_int16 *pTrees[3];
2448 mz_uint8 *pCode_sizes[3];
2449
2451 mz_uint32 num_bits, dist, counter, num_extra;
2452 tinfl_bit_buf_t bit_buf;
2453 const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
2454 mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next ? pOut_buf_next + *pOut_buf_size : NULL;
2455 size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
2456
2457 /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */
2458 if ((!pOut_buf_start) || (!pOut_buf_next) || (!pIn_buf_size) || (!pOut_buf_size))
2459 {
2461 }
2462 if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
2463 {
2464 *pIn_buf_size = *pOut_buf_size = 0;
2466 }
2467
2468 pTrees[0] = r->m_tree_0;
2469 pTrees[1] = r->m_tree_1;
2470 pTrees[2] = r->m_tree_2;
2471 pCode_sizes[0] = r->m_code_size_0;
2472 pCode_sizes[1] = r->m_code_size_1;
2473 pCode_sizes[2] = r->m_code_size_2;
2474
2475 num_bits = r->m_num_bits;
2476 bit_buf = r->m_bit_buf;
2477 dist = r->m_dist;
2478 counter = r->m_counter;
2479 num_extra = r->m_num_extra;
2480 dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2482
2483 bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2484 r->m_z_adler32 = r->m_check_adler32 = 1;
2485 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2486 {
2487 TINFL_GET_BYTE(1, r->m_zhdr0);
2488 TINFL_GET_BYTE(2, r->m_zhdr1);
2489 counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2490 if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2491 counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)((size_t)1 << (8U + (r->m_zhdr0 >> 4)))));
2492 if (counter)
2493 {
2495 }
2496 }
2497
2498 do
2499 {
2500 TINFL_GET_BITS(3, r->m_final, 3);
2501 r->m_type = r->m_final >> 1;
2502 if (r->m_type == 0)
2503 {
2504 TINFL_SKIP_BITS(5, num_bits & 7);
2505 for (counter = 0; counter < 4; ++counter)
2506 {
2507 if (num_bits)
2508 TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2509 else
2510 TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2511 }
2512 if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8))))
2513 {
2515 }
2516 while ((counter) && (num_bits))
2517 {
2518 TINFL_GET_BITS(51, dist, 8);
2519 while (pOut_buf_cur >= pOut_buf_end)
2520 {
2522 }
2523 *pOut_buf_cur++ = (mz_uint8)dist;
2524 counter--;
2525 }
2526 while (counter)
2527 {
2528 size_t n;
2529 while (pOut_buf_cur >= pOut_buf_end)
2530 {
2532 }
2533 while (pIn_buf_cur >= pIn_buf_end)
2534 {
2536 }
2537 n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
2538 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2539 pIn_buf_cur += n;
2540 pOut_buf_cur += n;
2541 counter -= (mz_uint)n;
2542 }
2543 }
2544 else if (r->m_type == 3)
2545 {
2547 }
2548 else
2549 {
2550 if (r->m_type == 1)
2551 {
2552 mz_uint8 *p = r->m_code_size_0;
2553 mz_uint i;
2554 r->m_table_sizes[0] = 288;
2555 r->m_table_sizes[1] = 32;
2556 TINFL_MEMSET(r->m_code_size_1, 5, 32);
2557 for (i = 0; i <= 143; ++i)
2558 *p++ = 8;
2559 for (; i <= 255; ++i)
2560 *p++ = 9;
2561 for (; i <= 279; ++i)
2562 *p++ = 7;
2563 for (; i <= 287; ++i)
2564 *p++ = 8;
2565 }
2566 else
2567 {
2568 for (counter = 0; counter < 3; counter++)
2569 {
2570 TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2571 r->m_table_sizes[counter] += s_min_table_sizes[counter];
2572 }
2574 for (counter = 0; counter < r->m_table_sizes[2]; counter++)
2575 {
2576 mz_uint s;
2577 TINFL_GET_BITS(14, s, 3);
2578 r->m_code_size_2[s_length_dezigzag[counter]] = (mz_uint8)s;
2579 }
2580 r->m_table_sizes[2] = 19;
2581 }
2582 for (; (int)r->m_type >= 0; r->m_type--)
2583 {
2584 int tree_next, tree_cur;
2585 mz_int16 *pLookUp;
2586 mz_int16 *pTree;
2587 mz_uint8 *pCode_size;
2588 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
2589 pLookUp = r->m_look_up[r->m_type];
2590 pTree = pTrees[r->m_type];
2591 pCode_size = pCode_sizes[r->m_type];
2592 MZ_CLEAR_ARR(total_syms);
2593 TINFL_MEMSET(pLookUp, 0, sizeof(r->m_look_up[0]));
2595 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2596 total_syms[pCode_size[i]]++;
2597 used_syms = 0, total = 0;
2598 next_code[0] = next_code[1] = 0;
2599 for (i = 1; i <= 15; ++i)
2600 {
2601 used_syms += total_syms[i];
2602 next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2603 }
2604 if ((65536 != total) && (used_syms > 1))
2605 {
2607 }
2608 for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
2609 {
2610 mz_uint rev_code = 0, l, cur_code, code_size = pCode_size[sym_index];
2611 if (!code_size)
2612 continue;
2613 cur_code = next_code[code_size]++;
2614 for (l = code_size; l > 0; l--, cur_code >>= 1)
2615 rev_code = (rev_code << 1) | (cur_code & 1);
2616 if (code_size <= TINFL_FAST_LOOKUP_BITS)
2617 {
2618 mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2619 while (rev_code < TINFL_FAST_LOOKUP_SIZE)
2620 {
2621 pLookUp[rev_code] = k;
2622 rev_code += (1 << code_size);
2623 }
2624 continue;
2625 }
2626 if (0 == (tree_cur = pLookUp[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
2627 {
2628 pLookUp[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
2629 tree_cur = tree_next;
2630 tree_next -= 2;
2631 }
2632 rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2633 for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
2634 {
2635 tree_cur -= ((rev_code >>= 1) & 1);
2636 if (!pTree[-tree_cur - 1])
2637 {
2638 pTree[-tree_cur - 1] = (mz_int16)tree_next;
2639 tree_cur = tree_next;
2640 tree_next -= 2;
2641 }
2642 else
2643 tree_cur = pTree[-tree_cur - 1];
2644 }
2645 tree_cur -= ((rev_code >>= 1) & 1);
2646 pTree[-tree_cur - 1] = (mz_int16)sym_index;
2647 }
2648 if (r->m_type == 2)
2649 {
2650 for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
2651 {
2652 mz_uint s;
2653 TINFL_HUFF_DECODE(16, dist, r->m_look_up[2], r->m_tree_2);
2654 if (dist < 16)
2655 {
2656 r->m_len_codes[counter++] = (mz_uint8)dist;
2657 continue;
2658 }
2659 if ((dist == 16) && (!counter))
2660 {
2662 }
2663 num_extra = "\02\03\07"[dist - 16];
2664 TINFL_GET_BITS(18, s, num_extra);
2665 s += "\03\03\013"[dist - 16];
2666 TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2667 counter += s;
2668 }
2669 if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
2670 {
2672 }
2675 }
2676 }
2677 for (;;)
2678 {
2679 mz_uint8 *pSrc;
2680 for (;;)
2681 {
2682 if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
2683 {
2684 TINFL_HUFF_DECODE(23, counter, r->m_look_up[0], r->m_tree_0);
2685 if (counter >= 256)
2686 break;
2687 while (pOut_buf_cur >= pOut_buf_end)
2688 {
2690 }
2691 *pOut_buf_cur++ = (mz_uint8)counter;
2692 }
2693 else
2694 {
2695 int sym2;
2696 mz_uint code_len;
2697#if TINFL_USE_64BIT_BITBUF
2698 if (num_bits < 30)
2699 {
2700 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2701 pIn_buf_cur += 4;
2702 num_bits += 32;
2703 }
2704#else
2705 if (num_bits < 15)
2706 {
2707 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2708 pIn_buf_cur += 2;
2709 num_bits += 16;
2710 }
2711#endif
2712 if ((sym2 = r->m_look_up[0][bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2713 code_len = sym2 >> 9;
2714 else
2715 {
2716 code_len = TINFL_FAST_LOOKUP_BITS;
2717 do
2718 {
2719 sym2 = r->m_tree_0[~sym2 + ((bit_buf >> code_len++) & 1)];
2720 } while (sym2 < 0);
2721 }
2722 counter = sym2;
2723 bit_buf >>= code_len;
2724 num_bits -= code_len;
2725 if (counter & 256)
2726 break;
2727
2728#if !TINFL_USE_64BIT_BITBUF
2729 if (num_bits < 15)
2730 {
2731 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2732 pIn_buf_cur += 2;
2733 num_bits += 16;
2734 }
2735#endif
2736 if ((sym2 = r->m_look_up[0][bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2737 code_len = sym2 >> 9;
2738 else
2739 {
2740 code_len = TINFL_FAST_LOOKUP_BITS;
2741 do
2742 {
2743 sym2 = r->m_tree_0[~sym2 + ((bit_buf >> code_len++) & 1)];
2744 } while (sym2 < 0);
2745 }
2746 bit_buf >>= code_len;
2747 num_bits -= code_len;
2748
2749 pOut_buf_cur[0] = (mz_uint8)counter;
2750 if (sym2 & 256)
2751 {
2752 pOut_buf_cur++;
2753 counter = sym2;
2754 break;
2755 }
2756 pOut_buf_cur[1] = (mz_uint8)sym2;
2757 pOut_buf_cur += 2;
2758 }
2759 }
2760 if ((counter &= 511) == 256)
2761 break;
2762
2763 num_extra = s_length_extra[counter - 257];
2764 counter = s_length_base[counter - 257];
2765 if (num_extra)
2766 {
2767 mz_uint extra_bits;
2768 TINFL_GET_BITS(25, extra_bits, num_extra);
2769 counter += extra_bits;
2770 }
2771
2772 TINFL_HUFF_DECODE(26, dist, r->m_look_up[1], r->m_tree_1);
2773 num_extra = s_dist_extra[dist];
2774 dist = s_dist_base[dist];
2775 if (num_extra)
2776 {
2777 mz_uint extra_bits;
2778 TINFL_GET_BITS(27, extra_bits, num_extra);
2779 dist += extra_bits;
2780 }
2781
2782 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2783 if ((dist == 0 || dist > dist_from_out_buf_start || dist_from_out_buf_start == 0) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2784 {
2786 }
2787
2788 pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2789
2790 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
2791 {
2792 while (counter--)
2793 {
2794 while (pOut_buf_cur >= pOut_buf_end)
2795 {
2797 }
2798 *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
2799 }
2800 continue;
2801 }
2802#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2803 else if ((counter >= 9) && (counter <= dist))
2804 {
2805 const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2806 do
2807 {
2808#ifdef MINIZ_UNALIGNED_USE_MEMCPY
2809 memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2);
2810#else
2811 ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2812 ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2813#endif
2814 pOut_buf_cur += 8;
2815 } while ((pSrc += 8) < pSrc_end);
2816 if ((counter &= 7) < 3)
2817 {
2818 if (counter)
2819 {
2820 pOut_buf_cur[0] = pSrc[0];
2821 if (counter > 1)
2822 pOut_buf_cur[1] = pSrc[1];
2823 pOut_buf_cur += counter;
2824 }
2825 continue;
2826 }
2827 }
2828#endif
2829 while(counter>2)
2830 {
2831 pOut_buf_cur[0] = pSrc[0];
2832 pOut_buf_cur[1] = pSrc[1];
2833 pOut_buf_cur[2] = pSrc[2];
2834 pOut_buf_cur += 3;
2835 pSrc += 3;
2836 counter -= 3;
2837 }
2838 if (counter > 0)
2839 {
2840 pOut_buf_cur[0] = pSrc[0];
2841 if (counter > 1)
2842 pOut_buf_cur[1] = pSrc[1];
2843 pOut_buf_cur += counter;
2844 }
2845 }
2846 }
2847 } while (!(r->m_final & 1));
2848
2849 /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
2850 /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */
2851 TINFL_SKIP_BITS(32, num_bits & 7);
2852 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2853 {
2854 --pIn_buf_cur;
2855 num_bits -= 8;
2856 }
2857 bit_buf &= ~(~(tinfl_bit_buf_t)0 << num_bits);
2858 MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */
2859
2860 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2861 {
2862 for (counter = 0; counter < 4; ++counter)
2863 {
2864 mz_uint s;
2865 if (num_bits)
2866 TINFL_GET_BITS(41, s, 8);
2867 else
2868 TINFL_GET_BYTE(42, s);
2869 r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2870 }
2871 }
2873
2875
2876common_exit:
2877 /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
2878 /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
2879 /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */
2881 {
2882 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2883 {
2884 --pIn_buf_cur;
2885 num_bits -= 8;
2886 }
2887 }
2888 r->m_num_bits = num_bits;
2889 r->m_bit_buf = bit_buf & ~(~(tinfl_bit_buf_t)0 << num_bits);
2890 r->m_dist = dist;
2891 r->m_counter = counter;
2892 r->m_num_extra = num_extra;
2893 r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2894 *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2895 *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2896 if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
2897 {
2898 const mz_uint8 *ptr = pOut_buf_next;
2899 size_t buf_len = *pOut_buf_size;
2900 mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
2901 size_t block_len = buf_len % 5552;
2902 while (buf_len)
2903 {
2904 for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
2905 {
2906 s1 += ptr[0], s2 += s1;
2907 s1 += ptr[1], s2 += s1;
2908 s1 += ptr[2], s2 += s1;
2909 s1 += ptr[3], s2 += s1;
2910 s1 += ptr[4], s2 += s1;
2911 s1 += ptr[5], s2 += s1;
2912 s1 += ptr[6], s2 += s1;
2913 s1 += ptr[7], s2 += s1;
2914 }
2915 for (; i < block_len; ++i)
2916 s1 += *ptr++, s2 += s1;
2917 s1 %= 65521U, s2 %= 65521U;
2918 buf_len -= block_len;
2919 block_len = 5552;
2920 }
2921 r->m_check_adler32 = (s2 << 16) + s1;
2922 if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
2924 }
2925 return status;
2926}
2927
2928/* Higher level helper functions. */
2929void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2930{
2931 tinfl_decompressor decomp;
2932 void *pBuf = NULL, *pNew_buf;
2933 size_t src_buf_ofs = 0, out_buf_capacity = 0;
2934 *pOut_len = 0;
2935 tinfl_init(&decomp);
2936 for (;;)
2937 {
2938 size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2939 tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size,
2941 if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
2942 {
2943 MZ_FREE(pBuf);
2944 *pOut_len = 0;
2945 return NULL;
2946 }
2947 src_buf_ofs += src_buf_size;
2948 *pOut_len += dst_buf_size;
2949 if (status == TINFL_STATUS_DONE)
2950 break;
2951 new_out_buf_capacity = out_buf_capacity * 2;
2952 if (new_out_buf_capacity < 128)
2953 new_out_buf_capacity = 128;
2954 pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2955 if (!pNew_buf)
2956 {
2957 MZ_FREE(pBuf);
2958 *pOut_len = 0;
2959 return NULL;
2960 }
2961 pBuf = pNew_buf;
2962 out_buf_capacity = new_out_buf_capacity;
2963 }
2964 return pBuf;
2965}
2966
2967size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2968{
2969 tinfl_decompressor decomp;
2970 tinfl_status status;
2971 tinfl_init(&decomp);
2972 status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2973 return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
2974}
2975
2976int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2977{
2978 int result = 0;
2979 tinfl_decompressor decomp;
2981 size_t in_buf_ofs = 0, dict_ofs = 0;
2982 if (!pDict)
2983 return TINFL_STATUS_FAILED;
2984 memset(pDict,0,TINFL_LZ_DICT_SIZE);
2985 tinfl_init(&decomp);
2986 for (;;)
2987 {
2988 size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2989 tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2991 in_buf_ofs += in_buf_size;
2992 if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2993 break;
2994 if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
2995 {
2996 result = (status == TINFL_STATUS_DONE);
2997 break;
2998 }
2999 dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
3000 }
3001 MZ_FREE(pDict);
3002 *pIn_buf_size = in_buf_ofs;
3003 return result;
3004}
3005
3006#ifndef MINIZ_NO_MALLOC
3008{
3010 if (pDecomp)
3011 tinfl_init(pDecomp);
3012 return pDecomp;
3013}
3014
3016{
3017 MZ_FREE(pDecomp);
3018}
3019#endif
3020
3021#ifdef __cplusplus
3022}
3023#endif
3024
3025#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/
3026 /**************************************************************************
3027 *
3028 * Copyright 2013-2014 RAD Game Tools and Valve Software
3029 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
3030 * Copyright 2016 Martin Raiber
3031 * All Rights Reserved.
3032 *
3033 * Permission is hereby granted, free of charge, to any person obtaining a copy
3034 * of this software and associated documentation files (the "Software"), to deal
3035 * in the Software without restriction, including without limitation the rights
3036 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3037 * copies of the Software, and to permit persons to whom the Software is
3038 * furnished to do so, subject to the following conditions:
3039 *
3040 * The above copyright notice and this permission notice shall be included in
3041 * all copies or substantial portions of the Software.
3042 *
3043 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3044 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3045 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3046 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3047 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3048 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3049 * THE SOFTWARE.
3050 *
3051 **************************************************************************/
3052
3053
3054#ifndef MINIZ_NO_ARCHIVE_APIS
3055
3056#ifdef __cplusplus
3057extern "C" {
3058#endif
3059
3060/* ------------------- .ZIP archive reading */
3061
3062#ifdef MINIZ_NO_STDIO
3063#define MZ_FILE void *
3064#else
3065#include <sys/stat.h>
3066
3067#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__)
3068
3069#define WIN32_LEAN_AND_MEAN
3070#include <windows.h>
3071
3072static WCHAR* mz_utf8z_to_widechar(const char* str)
3073{
3074 int reqChars = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
3075 WCHAR* wStr = (WCHAR*)malloc(reqChars * sizeof(WCHAR));
3076 MultiByteToWideChar(CP_UTF8, 0, str, -1, wStr, reqChars);
3077 return wStr;
3078}
3079
3080static FILE *mz_fopen(const char *pFilename, const char *pMode)
3081{
3082 WCHAR* wFilename = mz_utf8z_to_widechar(pFilename);
3083 WCHAR* wMode = mz_utf8z_to_widechar(pMode);
3084 FILE* pFile = NULL;
3085 errno_t err = _wfopen_s(&pFile, wFilename, wMode);
3086 free(wFilename);
3087 free(wMode);
3088 return err ? NULL : pFile;
3089}
3090
3091static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
3092{
3093 WCHAR* wPath = mz_utf8z_to_widechar(pPath);
3094 WCHAR* wMode = mz_utf8z_to_widechar(pMode);
3095 FILE* pFile = NULL;
3096 errno_t err = _wfreopen_s(&pFile, wPath, wMode, pStream);
3097 free(wPath);
3098 free(wMode);
3099 return err ? NULL : pFile;
3100}
3101
3102#if defined(__MINGW32__)
3103static int mz_stat(const char *path, struct _stat *buffer)
3104{
3105 WCHAR* wPath = mz_utf8z_to_widechar(path);
3106 int res = _wstat(wPath, buffer);
3107 free(wPath);
3108 return res;
3109}
3110#else
3111static int mz_stat64(const char *path, struct __stat64 *buffer)
3112{
3113 WCHAR* wPath = mz_utf8z_to_widechar(path);
3114 int res = _wstat64(wPath, buffer);
3115 free(wPath);
3116 return res;
3117}
3118#endif
3119
3120#ifndef MINIZ_NO_TIME
3121#include <sys/utime.h>
3122#endif
3123#define MZ_FOPEN mz_fopen
3124#define MZ_FCLOSE fclose
3125#define MZ_FREAD fread
3126#define MZ_FWRITE fwrite
3127#define MZ_FTELL64 _ftelli64
3128#define MZ_FSEEK64 _fseeki64
3129#if defined(__MINGW32__)
3130#define MZ_FILE_STAT_STRUCT _stat
3131#define MZ_FILE_STAT mz_stat
3132#else
3133#define MZ_FILE_STAT_STRUCT _stat64
3134#define MZ_FILE_STAT mz_stat64
3135#endif
3136#define MZ_FFLUSH fflush
3137#define MZ_FREOPEN mz_freopen
3138#define MZ_DELETE_FILE remove
3139
3140#elif defined(__WATCOMC__)
3141#ifndef MINIZ_NO_TIME
3142#include <sys/utime.h>
3143#endif
3144#define MZ_FOPEN(f, m) fopen(f, m)
3145#define MZ_FCLOSE fclose
3146#define MZ_FREAD fread
3147#define MZ_FWRITE fwrite
3148#define MZ_FTELL64 _ftelli64
3149#define MZ_FSEEK64 _fseeki64
3150#define MZ_FILE_STAT_STRUCT stat
3151#define MZ_FILE_STAT stat
3152#define MZ_FFLUSH fflush
3153#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3154#define MZ_DELETE_FILE remove
3155
3156#elif defined(__TINYC__)
3157#ifndef MINIZ_NO_TIME
3158#include <sys/utime.h>
3159#endif
3160#define MZ_FOPEN(f, m) fopen(f, m)
3161#define MZ_FCLOSE fclose
3162#define MZ_FREAD fread
3163#define MZ_FWRITE fwrite
3164#define MZ_FTELL64 ftell
3165#define MZ_FSEEK64 fseek
3166#define MZ_FILE_STAT_STRUCT stat
3167#define MZ_FILE_STAT stat
3168#define MZ_FFLUSH fflush
3169#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3170#define MZ_DELETE_FILE remove
3171
3172#elif defined(__USE_LARGEFILE64) /* gcc, clang */
3173#ifndef MINIZ_NO_TIME
3174#include <utime.h>
3175#endif
3176#define MZ_FOPEN(f, m) fopen64(f, m)
3177#define MZ_FCLOSE fclose
3178#define MZ_FREAD fread
3179#define MZ_FWRITE fwrite
3180#define MZ_FTELL64 ftello64
3181#define MZ_FSEEK64 fseeko64
3182#define MZ_FILE_STAT_STRUCT stat64
3183#define MZ_FILE_STAT stat64
3184#define MZ_FFLUSH fflush
3185#define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
3186#define MZ_DELETE_FILE remove
3187
3188#elif defined(__APPLE__) || defined(__FreeBSD__)
3189#ifndef MINIZ_NO_TIME
3190#include <utime.h>
3191#endif
3192#define MZ_FOPEN(f, m) fopen(f, m)
3193#define MZ_FCLOSE fclose
3194#define MZ_FREAD fread
3195#define MZ_FWRITE fwrite
3196#define MZ_FTELL64 ftello
3197#define MZ_FSEEK64 fseeko
3198#define MZ_FILE_STAT_STRUCT stat
3199#define MZ_FILE_STAT stat
3200#define MZ_FFLUSH fflush
3201#define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3202#define MZ_DELETE_FILE remove
3203
3204#else
3205#pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
3206#ifndef MINIZ_NO_TIME
3207#include <utime.h>
3208#endif
3209#define MZ_FOPEN(f, m) fopen(f, m)
3210#define MZ_FCLOSE fclose
3211#define MZ_FREAD fread
3212#define MZ_FWRITE fwrite
3213#ifdef __STRICT_ANSI__
3214#define MZ_FTELL64 ftell
3215#define MZ_FSEEK64 fseek
3216#else
3217#define MZ_FTELL64 ftello
3218#define MZ_FSEEK64 fseeko
3219#endif
3220#define MZ_FILE_STAT_STRUCT stat
3221#define MZ_FILE_STAT stat
3222#define MZ_FFLUSH fflush
3223#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3224#define MZ_DELETE_FILE remove
3225#endif /* #ifdef _MSC_VER */
3226#endif /* #ifdef MINIZ_NO_STDIO */
3227
3228#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
3229
3230/* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */
3231enum
3232{
3233 /* ZIP archive identifiers and record sizes */
3240
3241 /* ZIP64 archive identifier and record sizes */
3250
3251 /* Central directory header record offsets */
3269
3270 /* Local directory header offsets */
3283
3284 /* End of central directory offsets */
3293
3294 /* ZIP64 End of central directory locator offsets */
3295 MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
3299
3300 /* ZIP64 End of central directory header offsets */
3301 MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
3310 MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
3319
3320typedef struct
3321{
3322 void *m_p;
3323 size_t m_size, m_capacity;
3325} mz_zip_array;
3326
3328{
3332
3333 /* The flags passed in when the archive is initially opened. */
3335
3336 /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
3338
3339 /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */
3341
3342 /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */
3345
3346 void *m_pMem;
3349};
3350
3351#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
3352
3353#if defined(DEBUG) || defined(_DEBUG)
3354static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
3355{
3356 MZ_ASSERT(index < pArray->m_size);
3357 return index;
3358}
3359#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
3360#else
3361#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
3362#endif
3363
3364static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
3365{
3366 memset(pArray, 0, sizeof(mz_zip_array));
3367 pArray->m_element_size = element_size;
3368}
3369
3371{
3372 pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3373 memset(pArray, 0, sizeof(mz_zip_array));
3374}
3375
3376static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
3377{
3378 void *pNew_p;
3379 size_t new_capacity = min_new_capacity;
3380 MZ_ASSERT(pArray->m_element_size);
3381 if (pArray->m_capacity >= min_new_capacity)
3382 return MZ_TRUE;
3383 if (growing)
3384 {
3385 new_capacity = MZ_MAX(1, pArray->m_capacity);
3386 while (new_capacity < min_new_capacity)
3387 new_capacity *= 2;
3388 }
3389 if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3390 return MZ_FALSE;
3391 pArray->m_p = pNew_p;
3392 pArray->m_capacity = new_capacity;
3393 return MZ_TRUE;
3394}
3395
3396static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3397{
3398 if (new_capacity > pArray->m_capacity)
3399 {
3400 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3401 return MZ_FALSE;
3402 }
3403 return MZ_TRUE;
3404}
3405
3406static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3407{
3408 if (new_size > pArray->m_capacity)
3409 {
3410 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3411 return MZ_FALSE;
3412 }
3413 pArray->m_size = new_size;
3414 return MZ_TRUE;
3415}
3416
3418{
3419 return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3420}
3421
3422static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3423{
3424 size_t orig_size = pArray->m_size;
3425 if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3426 return MZ_FALSE;
3427 if (n > 0)
3428 memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3429 return MZ_TRUE;
3430}
3431
3432#ifndef MINIZ_NO_TIME
3433static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
3434{
3435 struct tm tm;
3436 memset(&tm, 0, sizeof(tm));
3437 tm.tm_isdst = -1;
3438 tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3439 tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3440 tm.tm_mday = dos_date & 31;
3441 tm.tm_hour = (dos_time >> 11) & 31;
3442 tm.tm_min = (dos_time >> 5) & 63;
3443 tm.tm_sec = (dos_time << 1) & 62;
3444 return mktime(&tm);
3445}
3446
3447#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3448static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3449{
3450#ifdef _MSC_VER
3451 struct tm tm_struct;
3452 struct tm *tm = &tm_struct;
3453 errno_t err = localtime_s(tm, &time);
3454 if (err)
3455 {
3456 *pDOS_date = 0;
3457 *pDOS_time = 0;
3458 return;
3459 }
3460#else
3461 struct tm *tm = localtime(&time);
3462#endif /* #ifdef _MSC_VER */
3463
3464 *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3465 *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3466}
3467#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
3468
3469#ifndef MINIZ_NO_STDIO
3470#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3471static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
3472{
3473 struct MZ_FILE_STAT_STRUCT file_stat;
3474
3475 /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
3476 if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3477 return MZ_FALSE;
3478
3479 *pTime = file_stat.st_mtime;
3480
3481 return MZ_TRUE;
3482}
3483#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
3484
3485static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
3486{
3487 struct utimbuf t;
3488
3489 memset(&t, 0, sizeof(t));
3490 t.actime = access_time;
3491 t.modtime = modified_time;
3492
3493 return !utime(pFilename, &t);
3494}
3495#endif /* #ifndef MINIZ_NO_STDIO */
3496#endif /* #ifndef MINIZ_NO_TIME */
3497
3499{
3500 if (pZip)
3501 pZip->m_last_error = err_num;
3502 return MZ_FALSE;
3503}
3504
3506{
3507 (void)flags;
3508 if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3510
3511 if (!pZip->m_pAlloc)
3513 if (!pZip->m_pFree)
3515 if (!pZip->m_pRealloc)
3517
3518 pZip->m_archive_size = 0;
3520 pZip->m_total_files = 0;
3522
3523 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3525
3526 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3530 pZip->m_pState->m_init_flags = flags;
3531 pZip->m_pState->m_zip64 = MZ_FALSE;
3533
3535
3536 return MZ_TRUE;
3537}
3538
3539static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
3540{
3541 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
3542 const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3544 mz_uint8 l = 0, r = 0;
3547 pE = pL + MZ_MIN(l_len, r_len);
3548 while (pL < pE)
3549 {
3550 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3551 break;
3552 pL++;
3553 pR++;
3554 }
3555 return (pL == pE) ? (l_len < r_len) : (l < r);
3556}
3557
3558#define MZ_SWAP_UINT32(a, b) \
3559 do \
3560 { \
3561 mz_uint32 t = a; \
3562 a = b; \
3563 b = t; \
3564 } \
3565 MZ_MACRO_END
3566
3567/* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */
3569{
3570 mz_zip_internal_state *pState = pZip->m_pState;
3571 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3572 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3573 mz_uint32 *pIndices;
3574 mz_uint32 start, end;
3575 const mz_uint32 size = pZip->m_total_files;
3576
3577 if (size <= 1U)
3578 return;
3579
3581
3582 start = (size - 2U) >> 1U;
3583 for (;;)
3584 {
3585 mz_uint64 child, root = start;
3586 for (;;)
3587 {
3588 if ((child = (root << 1U) + 1U) >= size)
3589 break;
3590 child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3591 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3592 break;
3593 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3594 root = child;
3595 }
3596 if (!start)
3597 break;
3598 start--;
3599 }
3600
3601 end = size - 1;
3602 while (end > 0)
3603 {
3604 mz_uint64 child, root = 0;
3605 MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3606 for (;;)
3607 {
3608 if ((child = (root << 1U) + 1U) >= end)
3609 break;
3610 child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3611 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3612 break;
3613 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3614 root = child;
3615 }
3616 end--;
3617 }
3618}
3619
3621{
3622 mz_int64 cur_file_ofs;
3623 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3624 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3625
3626 /* Basic sanity checks - reject files which are too small */
3627 if (pZip->m_archive_size < record_size)
3628 return MZ_FALSE;
3629
3630 /* Find the record by scanning the file from the end towards the beginning. */
3631 cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3632 for (;;)
3633 {
3634 int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3635
3636 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3637 return MZ_FALSE;
3638
3639 for (i = n - 4; i >= 0; --i)
3640 {
3641 mz_uint s = MZ_READ_LE32(pBuf + i);
3642 if (s == record_sig)
3643 {
3644 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3645 break;
3646 }
3647 }
3648
3649 if (i >= 0)
3650 {
3651 cur_file_ofs += i;
3652 break;
3653 }
3654
3655 /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
3656 if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= ((mz_uint64)(MZ_UINT16_MAX) + record_size)))
3657 return MZ_FALSE;
3658
3659 cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3660 }
3661
3662 *pOfs = cur_file_ofs;
3663 return MZ_TRUE;
3664}
3665
3667{
3668 mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3669 mz_uint64 cdir_ofs = 0;
3670 mz_int64 cur_file_ofs = 0;
3671 const mz_uint8 *p;
3672
3673 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3674 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3675 mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3676 mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3677 mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3678
3679 mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3680 mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3681
3682 mz_uint64 zip64_end_of_central_dir_ofs = 0;
3683
3684 /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */
3687
3690
3691 /* Read and verify the end of central directory record. */
3694
3697
3699 {
3701 {
3703 {
3704 zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3705 if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3707
3708 if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
3709 {
3711 {
3712 pZip->m_pState->m_zip64 = MZ_TRUE;
3713 }
3714 }
3715 }
3716 }
3717 }
3718
3720 cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3721 num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3722 cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3723 cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3724 cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3725
3726 if (pZip->m_pState->m_zip64)
3727 {
3728 mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3729 mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3730 mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3731 mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
3732 mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3733
3734 if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3736
3737 if (zip64_total_num_of_disks != 1U)
3739
3740 /* Check for miniz's practical limits */
3741 if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3743
3744 pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3745
3746 if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3748
3749 cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
3750
3751 /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
3752 if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3754
3755 cdir_size = (mz_uint32)zip64_size_of_central_directory;
3756
3757 num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3758
3759 cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3760
3761 cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3762 }
3763
3764 if (pZip->m_total_files != cdir_entries_on_this_disk)
3766
3767 if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3769
3772
3773 if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3775
3776 pZip->m_central_directory_file_ofs = cdir_ofs;
3777
3778 if (pZip->m_total_files)
3779 {
3780 mz_uint i, n;
3781 /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */
3782 if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3785
3786 if (sort_central_dir)
3787 {
3790 }
3791
3792 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3794
3795 /* Now create an index into the central directory file records, do some basic sanity checking on each record */
3796 p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3797 for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3798 {
3799 mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3800 mz_uint64 comp_size, decomp_size, local_header_ofs;
3801
3804
3806
3807 if (sort_central_dir)
3809
3812 local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3813 filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3814 ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3815
3817 (ext_data_size) &&
3818 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3819 {
3820 /* Attempt to find zip64 extended information field in the entry's extra data */
3821 mz_uint32 extra_size_remaining = ext_data_size;
3822
3823 if (extra_size_remaining)
3824 {
3825 const mz_uint8 *pExtra_data;
3826 void* buf = NULL;
3827
3828 if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
3829 {
3830 buf = MZ_MALLOC(ext_data_size);
3831 if(buf==NULL)
3833
3834 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size)
3835 {
3836 MZ_FREE(buf);
3838 }
3839
3840 pExtra_data = (mz_uint8*)buf;
3841 }
3842 else
3843 {
3844 pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3845 }
3846
3847 do
3848 {
3849 mz_uint32 field_id;
3850 mz_uint32 field_data_size;
3851
3852 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
3853 {
3854 MZ_FREE(buf);
3856 }
3857
3858 field_id = MZ_READ_LE16(pExtra_data);
3859 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
3860
3861 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
3862 {
3863 MZ_FREE(buf);
3865 }
3866
3868 {
3869 /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */
3870 pZip->m_pState->m_zip64 = MZ_TRUE;
3872 break;
3873 }
3874
3875 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
3876 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
3877 } while (extra_size_remaining);
3878
3879 MZ_FREE(buf);
3880 }
3881 }
3882
3883 /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
3884 if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3885 {
3886 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3888 }
3889
3890 disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3891 if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3893
3894 if (comp_size != MZ_UINT32_MAX)
3895 {
3898 }
3899
3900 bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3903
3906
3907 n -= total_header_size;
3908 p += total_header_size;
3909 }
3910 }
3911
3912 if (sort_central_dir)
3914
3915 return MZ_TRUE;
3916}
3917
3919{
3920 if (pZip)
3921 MZ_CLEAR_PTR(pZip);
3922}
3923
3925{
3926 mz_bool status = MZ_TRUE;
3927
3928 if (!pZip)
3929 return MZ_FALSE;
3930
3931 if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3932 {
3933 if (set_last_error)
3935
3936 return MZ_FALSE;
3937 }
3938
3939 if (pZip->m_pState)
3940 {
3941 mz_zip_internal_state *pState = pZip->m_pState;
3942 pZip->m_pState = NULL;
3943
3944 mz_zip_array_clear(pZip, &pState->m_central_dir);
3947
3948#ifndef MINIZ_NO_STDIO
3949 if (pState->m_pFile)
3950 {
3951 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
3952 {
3953 if (MZ_FCLOSE(pState->m_pFile) == EOF)
3954 {
3955 if (set_last_error)
3957 status = MZ_FALSE;
3958 }
3959 }
3960 pState->m_pFile = NULL;
3961 }
3962#endif /* #ifndef MINIZ_NO_STDIO */
3963
3964 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3965 }
3967
3968 return status;
3969}
3970
3976{
3977 if ((!pZip) || (!pZip->m_pRead))
3979
3980 if (!mz_zip_reader_init_internal(pZip, flags))
3981 return MZ_FALSE;
3982
3984 pZip->m_archive_size = size;
3985
3986 if (!mz_zip_reader_read_central_dir(pZip, flags))
3987 {
3989 return MZ_FALSE;
3990 }
3991
3992 return MZ_TRUE;
3993}
3994
3995static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3996{
3997 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3998 size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3999 memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
4000 return s;
4001}
4002
4003mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
4004{
4005 if (!pMem)
4007
4010
4011 if (!mz_zip_reader_init_internal(pZip, flags))
4012 return MZ_FALSE;
4013
4015 pZip->m_archive_size = size;
4017 pZip->m_pIO_opaque = pZip;
4018 pZip->m_pNeeds_keepalive = NULL;
4019
4020#ifdef __cplusplus
4021 pZip->m_pState->m_pMem = const_cast<void *>(pMem);
4022#else
4023 pZip->m_pState->m_pMem = (void *)pMem;
4024#endif
4025
4026 pZip->m_pState->m_mem_size = size;
4027
4028 if (!mz_zip_reader_read_central_dir(pZip, flags))
4029 {
4031 return MZ_FALSE;
4032 }
4033
4034 return MZ_TRUE;
4035}
4036
4037#ifndef MINIZ_NO_STDIO
4038static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
4039{
4040 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4041 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
4042
4043 file_ofs += pZip->m_pState->m_file_archive_start_ofs;
4044
4045 if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
4046 return 0;
4047
4048 return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
4049}
4050
4051mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
4052{
4053 return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
4054}
4055
4056mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)
4057{
4058 mz_uint64 file_size;
4059 MZ_FILE *pFile;
4060
4061 if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
4063
4064 pFile = MZ_FOPEN(pFilename, "rb");
4065 if (!pFile)
4067
4068 file_size = archive_size;
4069 if (!file_size)
4070 {
4071 if (MZ_FSEEK64(pFile, 0, SEEK_END))
4072 {
4073 MZ_FCLOSE(pFile);
4075 }
4076
4077 file_size = MZ_FTELL64(pFile);
4078 }
4079
4080 /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
4081
4083 {
4084 MZ_FCLOSE(pFile);
4086 }
4087
4088 if (!mz_zip_reader_init_internal(pZip, flags))
4089 {
4090 MZ_FCLOSE(pFile);
4091 return MZ_FALSE;
4092 }
4093
4096 pZip->m_pIO_opaque = pZip;
4097 pZip->m_pState->m_pFile = pFile;
4098 pZip->m_archive_size = file_size;
4099 pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
4100
4101 if (!mz_zip_reader_read_central_dir(pZip, flags))
4102 {
4104 return MZ_FALSE;
4105 }
4106
4107 return MZ_TRUE;
4108}
4109
4111{
4112 mz_uint64 cur_file_ofs;
4113
4114 if ((!pZip) || (!pFile))
4116
4117 cur_file_ofs = MZ_FTELL64(pFile);
4118
4119 if (!archive_size)
4120 {
4121 if (MZ_FSEEK64(pFile, 0, SEEK_END))
4123
4124 archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
4125
4126 if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4128 }
4129
4130 if (!mz_zip_reader_init_internal(pZip, flags))
4131 return MZ_FALSE;
4132
4135
4136 pZip->m_pIO_opaque = pZip;
4137 pZip->m_pState->m_pFile = pFile;
4138 pZip->m_archive_size = archive_size;
4139 pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
4140
4141 if (!mz_zip_reader_read_central_dir(pZip, flags))
4142 {
4144 return MZ_FALSE;
4145 }
4146
4147 return MZ_TRUE;
4148}
4149
4150#endif /* #ifndef MINIZ_NO_STDIO */
4151
4153{
4154 if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
4155 return NULL;
4157}
4158
4160{
4161 mz_uint m_bit_flag;
4162 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4163 if (!p)
4164 {
4166 return MZ_FALSE;
4167 }
4168
4169 m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4171}
4172
4174{
4175 mz_uint bit_flag;
4176 mz_uint method;
4177
4178 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4179 if (!p)
4180 {
4182 return MZ_FALSE;
4183 }
4184
4185 method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4186 bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4187
4188 if ((method != 0) && (method != MZ_DEFLATED))
4189 {
4191 return MZ_FALSE;
4192 }
4193
4195 {
4197 return MZ_FALSE;
4198 }
4199
4201 {
4203 return MZ_FALSE;
4204 }
4205
4206 return MZ_TRUE;
4207}
4208
4210{
4211 mz_uint filename_len, attribute_mapping_id, external_attr;
4212 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4213 if (!p)
4214 {
4216 return MZ_FALSE;
4217 }
4218
4219 filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4220 if (filename_len)
4221 {
4222 if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
4223 return MZ_TRUE;
4224 }
4225
4226 /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
4227 /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */
4228 /* FIXME: Remove this check? Is it necessary - we already check the filename. */
4229 attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4230 (void)attribute_mapping_id;
4231
4232 external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4233 if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4234 {
4235 return MZ_TRUE;
4236 }
4237
4238 return MZ_FALSE;
4239}
4240
4241static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)
4242{
4243 mz_uint n;
4244 const mz_uint8 *p = pCentral_dir_header;
4245
4246 if (pFound_zip64_extra_data)
4247 *pFound_zip64_extra_data = MZ_FALSE;
4248
4249 if ((!p) || (!pStat))
4251
4252 /* Extract fields from the central directory record. */
4253 pStat->m_file_index = file_index;
4259#ifndef MINIZ_NO_TIME
4261#endif
4268
4269 /* Copy as much of the filename and comment as possible. */
4272 memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4273 pStat->m_filename[n] = '\0';
4274
4277 pStat->m_comment_size = n;
4279 pStat->m_comment[n] = '\0';
4280
4281 /* Set some flags for convienance */
4282 pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4283 pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4284 pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
4285
4286 /* See if we need to read any zip64 extended information fields. */
4287 /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */
4289 {
4290 /* Attempt to find zip64 extended information field in the entry's extra data */
4291 mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4292
4293 if (extra_size_remaining)
4294 {
4296
4297 do
4298 {
4299 mz_uint32 field_id;
4300 mz_uint32 field_data_size;
4301
4302 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4304
4305 field_id = MZ_READ_LE16(pExtra_data);
4306 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4307
4308 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
4310
4312 {
4313 const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
4314 mz_uint32 field_data_remaining = field_data_size;
4315
4316 if (pFound_zip64_extra_data)
4317 *pFound_zip64_extra_data = MZ_TRUE;
4318
4319 if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4320 {
4321 if (field_data_remaining < sizeof(mz_uint64))
4323
4324 pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4325 pField_data += sizeof(mz_uint64);
4326 field_data_remaining -= sizeof(mz_uint64);
4327 }
4328
4329 if (pStat->m_comp_size == MZ_UINT32_MAX)
4330 {
4331 if (field_data_remaining < sizeof(mz_uint64))
4333
4334 pStat->m_comp_size = MZ_READ_LE64(pField_data);
4335 pField_data += sizeof(mz_uint64);
4336 field_data_remaining -= sizeof(mz_uint64);
4337 }
4338
4339 if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4340 {
4341 if (field_data_remaining < sizeof(mz_uint64))
4343
4344 pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4345 pField_data += sizeof(mz_uint64);
4346 field_data_remaining -= sizeof(mz_uint64);
4347 }
4348
4349 break;
4350 }
4351
4352 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4353 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4354 } while (extra_size_remaining);
4355 }
4356 }
4357
4358 return MZ_TRUE;
4359}
4360
4361static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
4362{
4363 mz_uint i;
4364 if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4365 return 0 == memcmp(pA, pB, len);
4366 for (i = 0; i < len; ++i)
4367 if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4368 return MZ_FALSE;
4369 return MZ_TRUE;
4370}
4371
4372static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
4373{
4374 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
4376 mz_uint8 l = 0, r = 0;
4378 pE = pL + MZ_MIN(l_len, r_len);
4379 while (pL < pE)
4380 {
4381 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4382 break;
4383 pL++;
4384 pR++;
4385 }
4386 return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4387}
4388
4389static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
4390{
4391 mz_zip_internal_state *pState = pZip->m_pState;
4392 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4393 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4395 const mz_uint32 size = pZip->m_total_files;
4396 const mz_uint filename_len = (mz_uint)strlen(pFilename);
4397
4398 if (pIndex)
4399 *pIndex = 0;
4400
4401 if (size)
4402 {
4403 /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
4404 /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
4405 mz_int64 l = 0, h = (mz_int64)size - 1;
4406
4407 while (l <= h)
4408 {
4409 mz_int64 m = l + ((h - l) >> 1);
4410 mz_uint32 file_index = pIndices[(mz_uint32)m];
4411
4412 int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4413 if (!comp)
4414 {
4415 if (pIndex)
4416 *pIndex = file_index;
4417 return MZ_TRUE;
4418 }
4419 else if (comp < 0)
4420 l = m + 1;
4421 else
4422 h = m - 1;
4423 }
4424 }
4425
4427}
4428
4429int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
4430{
4431 mz_uint32 index;
4432 if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4433 return -1;
4434 else
4435 return (int)index;
4436}
4437
4438mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
4439{
4440 mz_uint file_index;
4441 size_t name_len, comment_len;
4442
4443 if (pIndex)
4444 *pIndex = 0;
4445
4446 if ((!pZip) || (!pZip->m_pState) || (!pName))
4448
4449 /* See if we can use a binary search */
4451 (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4453 {
4454 return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4455 }
4456
4457 /* Locate the entry by scanning the entire central directory */
4458 name_len = strlen(pName);
4459 if (name_len > MZ_UINT16_MAX)
4461
4462 comment_len = pComment ? strlen(pComment) : 0;
4463 if (comment_len > MZ_UINT16_MAX)
4465
4466 for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4467 {
4469 mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4470 const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4471 if (filename_len < name_len)
4472 continue;
4473 if (comment_len)
4474 {
4475 mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4476 const char *pFile_comment = pFilename + filename_len + file_extra_len;
4477 if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4478 continue;
4479 }
4480 if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4481 {
4482 int ofs = filename_len - 1;
4483 do
4484 {
4485 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
4486 break;
4487 } while (--ofs >= 0);
4488 ofs++;
4489 pFilename += ofs;
4490 filename_len -= ofs;
4491 }
4492 if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4493 {
4494 if (pIndex)
4495 *pIndex = file_index;
4496 return MZ_TRUE;
4497 }
4498 }
4499
4501}
4502
4503static
4504mz_bool mz_zip_reader_extract_to_mem_no_alloc1(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size, const mz_zip_archive_file_stat *st)
4505{
4506 int status = TINFL_STATUS_DONE;
4507 mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4508 mz_zip_archive_file_stat file_stat;
4509 void *pRead_buf;
4510 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4511 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4512 tinfl_decompressor inflator;
4513
4514 if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4516
4517 if (st) {
4518 file_stat = *st;
4519 } else
4520 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4521 return MZ_FALSE;
4522
4523 /* A directory or zero length file */
4524 if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4525 return MZ_TRUE;
4526
4527 /* Encryption and patch files are not supported. */
4530
4531 /* This function only supports decompressing stored and deflate. */
4532 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4534
4535 /* Ensure supplied output buffer is large enough. */
4536 needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4537 if (buf_size < needed_size)
4539
4540 /* Read and parse the local directory entry. */
4541 cur_file_ofs = file_stat.m_local_header_ofs;
4542 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4544
4545 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4547
4549 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4551
4552 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4553 {
4554 /* The file is stored or the caller has requested the compressed data. */
4555 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
4557
4558#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4559 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4560 {
4561 if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4563 }
4564#endif
4565
4566 return MZ_TRUE;
4567 }
4568
4569 /* Decompress the file either directly from memory or from a file input buffer. */
4570 tinfl_init(&inflator);
4571
4572 if (pZip->m_pState->m_pMem)
4573 {
4574 /* Read directly from the archive in memory. */
4575 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4576 read_buf_size = read_buf_avail = file_stat.m_comp_size;
4577 comp_remaining = 0;
4578 }
4579 else if (pUser_read_buf)
4580 {
4581 /* Use a user provided read buffer. */
4582 if (!user_read_buf_size)
4583 return MZ_FALSE;
4584 pRead_buf = (mz_uint8 *)pUser_read_buf;
4585 read_buf_size = user_read_buf_size;
4586 read_buf_avail = 0;
4587 comp_remaining = file_stat.m_comp_size;
4588 }
4589 else
4590 {
4591 /* Temporarily allocate a read buffer. */
4592 read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4593 if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4595
4596 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4598
4599 read_buf_avail = 0;
4600 comp_remaining = file_stat.m_comp_size;
4601 }
4602
4603 do
4604 {
4605 /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
4606 size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4607 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4608 {
4609 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4610 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4611 {
4612 status = TINFL_STATUS_FAILED;
4614 break;
4615 }
4616 cur_file_ofs += read_buf_avail;
4617 comp_remaining -= read_buf_avail;
4618 read_buf_ofs = 0;
4619 }
4620 in_buf_size = (size_t)read_buf_avail;
4621 status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
4622 read_buf_avail -= in_buf_size;
4623 read_buf_ofs += in_buf_size;
4624 out_buf_ofs += out_buf_size;
4625 } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4626
4627 if (status == TINFL_STATUS_DONE)
4628 {
4629 /* Make sure the entire file was decompressed, and check its CRC. */
4630 if (out_buf_ofs != file_stat.m_uncomp_size)
4631 {
4633 status = TINFL_STATUS_FAILED;
4634 }
4635#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4636 else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4637 {
4639 status = TINFL_STATUS_FAILED;
4640 }
4641#endif
4642 }
4643
4644 if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4645 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4646
4647 return status == TINFL_STATUS_DONE;
4648}
4649
4650mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4651{
4652 return mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size, NULL);
4653}
4654
4655mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4656{
4657 mz_uint32 file_index;
4658 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4659 return MZ_FALSE;
4660 return mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size, NULL);
4661}
4662
4663mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
4664{
4665 return mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, buf_size, flags, NULL, 0, NULL);
4666}
4667
4668mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
4669{
4670 return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4671}
4672
4673void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
4674{
4675 mz_zip_archive_file_stat file_stat;
4676 mz_uint64 alloc_size;
4677 void *pBuf;
4678
4679 if (pSize)
4680 *pSize = 0;
4681
4682 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4683 return NULL;
4684
4685 alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4686 if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4687 {
4689 return NULL;
4690 }
4691
4692 if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
4693 {
4695 return NULL;
4696 }
4697
4698 if (!mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, (size_t)alloc_size, flags, NULL, 0, &file_stat))
4699 {
4700 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4701 return NULL;
4702 }
4703
4704 if (pSize)
4705 *pSize = (size_t)alloc_size;
4706 return pBuf;
4707}
4708
4709void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
4710{
4711 mz_uint32 file_index;
4712 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4713 {
4714 if (pSize)
4715 *pSize = 0;
4716 return MZ_FALSE;
4717 }
4718 return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4719}
4720
4722{
4723 int status = TINFL_STATUS_DONE;
4724#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4725 mz_uint file_crc32 = MZ_CRC32_INIT;
4726#endif
4727 mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4728 mz_zip_archive_file_stat file_stat;
4729 void *pRead_buf = NULL;
4730 void *pWrite_buf = NULL;
4731 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4732 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4733
4734 if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4736
4737 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4738 return MZ_FALSE;
4739
4740 /* A directory or zero length file */
4741 if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4742 return MZ_TRUE;
4743
4744 /* Encryption and patch files are not supported. */
4747
4748 /* This function only supports decompressing stored and deflate. */
4749 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4751
4752 /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */
4753 cur_file_ofs = file_stat.m_local_header_ofs;
4754 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4756
4757 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4759
4761 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4763
4764 /* Decompress the file either directly from memory or from a file input buffer. */
4765 if (pZip->m_pState->m_pMem)
4766 {
4767 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4768 read_buf_size = read_buf_avail = file_stat.m_comp_size;
4769 comp_remaining = 0;
4770 }
4771 else
4772 {
4773 read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4774 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4776
4777 read_buf_avail = 0;
4778 comp_remaining = file_stat.m_comp_size;
4779 }
4780
4781 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4782 {
4783 /* The file is stored or the caller has requested the compressed data. */
4784 if (pZip->m_pState->m_pMem)
4785 {
4786 if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4788
4789 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4790 {
4792 status = TINFL_STATUS_FAILED;
4793 }
4794 else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4795 {
4796#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4797 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4798#endif
4799 }
4800
4801 cur_file_ofs += file_stat.m_comp_size;
4802 out_buf_ofs += file_stat.m_comp_size;
4803 comp_remaining = 0;
4804 }
4805 else
4806 {
4807 while (comp_remaining)
4808 {
4809 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4810 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4811 {
4813 status = TINFL_STATUS_FAILED;
4814 break;
4815 }
4816
4817#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4818 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4819 {
4820 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4821 }
4822#endif
4823
4824 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4825 {
4827 status = TINFL_STATUS_FAILED;
4828 break;
4829 }
4830
4831 cur_file_ofs += read_buf_avail;
4832 out_buf_ofs += read_buf_avail;
4833 comp_remaining -= read_buf_avail;
4834 }
4835 }
4836 }
4837 else
4838 {
4839 tinfl_decompressor inflator;
4840 tinfl_init(&inflator);
4841
4842 if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4843 {
4845 status = TINFL_STATUS_FAILED;
4846 }
4847 else
4848 {
4849 do
4850 {
4851 mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4852 size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4853 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4854 {
4855 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4856 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4857 {
4859 status = TINFL_STATUS_FAILED;
4860 break;
4861 }
4862 cur_file_ofs += read_buf_avail;
4863 comp_remaining -= read_buf_avail;
4864 read_buf_ofs = 0;
4865 }
4866
4867 in_buf_size = (size_t)read_buf_avail;
4868 status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
4869 read_buf_avail -= in_buf_size;
4870 read_buf_ofs += in_buf_size;
4871
4872 if (out_buf_size)
4873 {
4874 if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4875 {
4877 status = TINFL_STATUS_FAILED;
4878 break;
4879 }
4880
4881#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4882 file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4883#endif
4884 if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4885 {
4887 status = TINFL_STATUS_FAILED;
4888 break;
4889 }
4890 }
4891 } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4892 }
4893 }
4894
4895 if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4896 {
4897 /* Make sure the entire file was decompressed, and check its CRC. */
4898 if (out_buf_ofs != file_stat.m_uncomp_size)
4899 {
4901 status = TINFL_STATUS_FAILED;
4902 }
4903#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4904 else if (file_crc32 != file_stat.m_crc32)
4905 {
4907 status = TINFL_STATUS_FAILED;
4908 }
4909#endif
4910 }
4911
4912 if (!pZip->m_pState->m_pMem)
4913 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4914
4915 if (pWrite_buf)
4916 pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4917
4918 return status == TINFL_STATUS_DONE;
4919}
4920
4921mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
4922{
4923 mz_uint32 file_index;
4924 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4925 return MZ_FALSE;
4926
4927 return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4928}
4929
4931{
4933 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4934 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4935
4936 /* Argument sanity check */
4937 if ((!pZip) || (!pZip->m_pState))
4938 return NULL;
4939
4940 /* Allocate an iterator status structure */
4942 if (!pState)
4943 {
4945 return NULL;
4946 }
4947
4948 /* Fetch file details */
4949 if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
4950 {
4951 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4952 return NULL;
4953 }
4954
4955 /* Encryption and patch files are not supported. */
4957 {
4959 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4960 return NULL;
4961 }
4962
4963 /* This function only supports decompressing stored and deflate. */
4964 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
4965 {
4967 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4968 return NULL;
4969 }
4970
4971 /* Init state - save args */
4972 pState->pZip = pZip;
4973 pState->flags = flags;
4974
4975 /* Init state - reset variables to defaults */
4976 pState->status = TINFL_STATUS_DONE;
4977#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4978 pState->file_crc32 = MZ_CRC32_INIT;
4979#endif
4980 pState->read_buf_ofs = 0;
4981 pState->out_buf_ofs = 0;
4982 pState->pRead_buf = NULL;
4983 pState->pWrite_buf = NULL;
4984 pState->out_blk_remain = 0;
4985
4986 /* Read and parse the local directory entry. */
4987 pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
4989 {
4991 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4992 return NULL;
4993 }
4994
4995 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4996 {
4998 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4999 return NULL;
5000 }
5001
5003 if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
5004 {
5006 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5007 return NULL;
5008 }
5009
5010 /* Decompress the file either directly from memory or from a file input buffer. */
5011 if (pZip->m_pState->m_pMem)
5012 {
5013 pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
5014 pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
5015 pState->comp_remaining = pState->file_stat.m_comp_size;
5016 }
5017 else
5018 {
5019 if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
5020 {
5021 /* Decompression required, therefore intermediate read buffer required */
5023 if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))
5024 {
5026 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5027 return NULL;
5028 }
5029 }
5030 else
5031 {
5032 /* Decompression not required - we will be reading directly into user buffer, no temp buf required */
5033 pState->read_buf_size = 0;
5034 }
5035 pState->read_buf_avail = 0;
5036 pState->comp_remaining = pState->file_stat.m_comp_size;
5037 }
5038
5039 if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
5040 {
5041 /* Decompression required, init decompressor */
5042 tinfl_init( &pState->inflator );
5043
5044 /* Allocate write buffer */
5045 if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
5046 {
5048 if (pState->pRead_buf)
5049 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
5050 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5051 return NULL;
5052 }
5053 }
5054
5055 return pState;
5056}
5057
5059{
5060 mz_uint32 file_index;
5061
5062 /* Locate file index by name */
5063 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
5064 return NULL;
5065
5066 /* Construct iterator */
5067 return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
5068}
5069
5070size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size)
5071{
5072 size_t copied_to_caller = 0;
5073
5074 /* Argument sanity check */
5075 if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
5076 return 0;
5077
5078 if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
5079 {
5080 /* The file is stored or the caller has requested the compressed data, calc amount to return. */
5081 copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining );
5082
5083 /* Zip is in memory....or requires reading from a file? */
5084 if (pState->pZip->m_pState->m_pMem)
5085 {
5086 /* Copy data to caller's buffer */
5087 memcpy( pvBuf, pState->pRead_buf, copied_to_caller );
5088 pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;
5089 }
5090 else
5091 {
5092 /* Read directly into caller's buffer */
5093 if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
5094 {
5095 /* Failed to read all that was asked for, flag failure and alert user */
5097 pState->status = TINFL_STATUS_FAILED;
5098 copied_to_caller = 0;
5099 }
5100 }
5101
5102#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5103 /* Compute CRC if not returning compressed data only */
5104 if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5105 pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
5106#endif
5107
5108 /* Advance offsets, dec counters */
5109 pState->cur_file_ofs += copied_to_caller;
5110 pState->out_buf_ofs += copied_to_caller;
5111 pState->comp_remaining -= copied_to_caller;
5112 }
5113 else
5114 {
5115 do
5116 {
5117 /* Calc ptr to write buffer - given current output pos and block size */
5118 mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5119
5120 /* Calc max output size - given current output pos and block size */
5121 size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5122
5123 if (!pState->out_blk_remain)
5124 {
5125 /* Read more data from file if none available (and reading from file) */
5126 if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
5127 {
5128 /* Calc read size */
5129 pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
5130 if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pState->pRead_buf, (size_t)pState->read_buf_avail) != pState->read_buf_avail)
5131 {
5133 pState->status = TINFL_STATUS_FAILED;
5134 break;
5135 }
5136
5137 /* Advance offsets, dec counters */
5138 pState->cur_file_ofs += pState->read_buf_avail;
5139 pState->comp_remaining -= pState->read_buf_avail;
5140 pState->read_buf_ofs = 0;
5141 }
5142
5143 /* Perform decompression */
5144 in_buf_size = (size_t)pState->read_buf_avail;
5145 pState->status = tinfl_decompress(&pState->inflator, (const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs, &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur, &out_buf_size, pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5146 pState->read_buf_avail -= in_buf_size;
5147 pState->read_buf_ofs += in_buf_size;
5148
5149 /* Update current output block size remaining */
5150 pState->out_blk_remain = out_buf_size;
5151 }
5152
5153 if (pState->out_blk_remain)
5154 {
5155 /* Calc amount to return. */
5156 size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );
5157
5158 /* Copy data to caller's buffer */
5159 memcpy( (mz_uint8*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );
5160
5161#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5162 /* Perform CRC */
5163 pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
5164#endif
5165
5166 /* Decrement data consumed from block */
5167 pState->out_blk_remain -= to_copy;
5168
5169 /* Inc output offset, while performing sanity check */
5170 if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
5171 {
5173 pState->status = TINFL_STATUS_FAILED;
5174 break;
5175 }
5176
5177 /* Increment counter of data copied to caller */
5178 copied_to_caller += to_copy;
5179 }
5180 } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );
5181 }
5182
5183 /* Return how many bytes were copied into user buffer */
5184 return copied_to_caller;
5185}
5186
5188{
5189 int status;
5190
5191 /* Argument sanity check */
5192 if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
5193 return MZ_FALSE;
5194
5195 /* Was decompression completed and requested? */
5196 if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
5197 {
5198 /* Make sure the entire file was decompressed, and check its CRC. */
5199 if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
5200 {
5202 pState->status = TINFL_STATUS_FAILED;
5203 }
5204#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5205 else if (pState->file_crc32 != pState->file_stat.m_crc32)
5206 {
5208 pState->status = TINFL_STATUS_FAILED;
5209 }
5210#endif
5211 }
5212
5213 /* Free buffers */
5214 if (!pState->pZip->m_pState->m_pMem)
5215 pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
5216 if (pState->pWrite_buf)
5217 pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
5218
5219 /* Save status */
5220 status = pState->status;
5221
5222 /* Free context */
5223 pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
5224
5225 return status == TINFL_STATUS_DONE;
5226}
5227
5228#ifndef MINIZ_NO_STDIO
5229static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
5230{
5231 (void)ofs;
5232
5233 return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5234}
5235
5236mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
5237{
5238 mz_bool status;
5239 mz_zip_archive_file_stat file_stat;
5240 MZ_FILE *pFile;
5241
5242 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5243 return MZ_FALSE;
5244
5245 if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5247
5248 pFile = MZ_FOPEN(pDst_filename, "wb");
5249 if (!pFile)
5251
5252 status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5253
5254 if (MZ_FCLOSE(pFile) == EOF)
5255 {
5256 if (status)
5258
5259 status = MZ_FALSE;
5260 }
5261
5262#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
5263 if (status)
5264 mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5265#endif
5266
5267 return status;
5268}
5269
5270mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
5271{
5272 mz_uint32 file_index;
5273 if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5274 return MZ_FALSE;
5275
5276 return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5277}
5278
5280{
5281 mz_zip_archive_file_stat file_stat;
5282
5283 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5284 return MZ_FALSE;
5285
5286 if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5288
5289 return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5290}
5291
5292mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
5293{
5294 mz_uint32 file_index;
5295 if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5296 return MZ_FALSE;
5297
5298 return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
5299}
5300#endif /* #ifndef MINIZ_NO_STDIO */
5301
5302static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5303{
5304 mz_uint32 *p = (mz_uint32 *)pOpaque;
5305 (void)file_ofs;
5306 *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
5307 return n;
5308}
5309
5311{
5312 mz_zip_archive_file_stat file_stat;
5313 mz_zip_internal_state *pState;
5314 const mz_uint8 *pCentral_dir_header;
5315 mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
5316 mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
5317 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
5318 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5319 mz_uint64 local_header_ofs = 0;
5320 mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
5321 mz_uint64 local_header_comp_size, local_header_uncomp_size;
5322 mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
5323 mz_bool has_data_descriptor;
5324 mz_uint32 local_header_bit_flags;
5325
5326 mz_zip_array file_data_array;
5327 mz_zip_array_init(&file_data_array, 1);
5328
5329 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5331
5332 if (file_index > pZip->m_total_files)
5334
5335 pState = pZip->m_pState;
5336
5337 pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
5338
5339 if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
5340 return MZ_FALSE;
5341
5342 /* A directory or zero length file */
5343 if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
5344 return MZ_TRUE;
5345
5346 /* Encryption and patch files are not supported. */
5347 if (file_stat.m_is_encrypted)
5349
5350 /* This function only supports stored and deflate. */
5351 if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
5353
5354 if (!file_stat.m_is_supported)
5356
5357 /* Read and parse the local directory entry. */
5358 local_header_ofs = file_stat.m_local_header_ofs;
5359 if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5361
5362 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5364
5365 local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
5366 local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5367 local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
5368 local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
5369 local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
5370 local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
5371 has_data_descriptor = (local_header_bit_flags & 8) != 0;
5372
5373 if (local_header_filename_len != strlen(file_stat.m_filename))
5375
5376 if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size)
5378
5379 if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
5380 {
5382 goto handle_failure;
5383 }
5384
5385 if (local_header_filename_len)
5386 {
5387 if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len)
5388 {
5390 goto handle_failure;
5391 }
5392
5393 /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */
5394 if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
5395 {
5397 goto handle_failure;
5398 }
5399 }
5400
5401 if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
5402 {
5403 mz_uint32 extra_size_remaining = local_header_extra_len;
5404 const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
5405
5406 if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
5407 {
5409 goto handle_failure;
5410 }
5411
5412 do
5413 {
5414 mz_uint32 field_id, field_data_size, field_total_size;
5415
5416 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
5417 {
5419 goto handle_failure;
5420 }
5421
5422 field_id = MZ_READ_LE16(pExtra_data);
5423 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
5424 field_total_size = field_data_size + sizeof(mz_uint16) * 2;
5425
5426 if (field_total_size > extra_size_remaining)
5427 {
5429 goto handle_failure;
5430 }
5431
5433 {
5434 const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
5435
5436 if (field_data_size < sizeof(mz_uint64) * 2)
5437 {
5439 goto handle_failure;
5440 }
5441
5442 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
5443 local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
5444
5445 found_zip64_ext_data_in_ldir = MZ_TRUE;
5446 break;
5447 }
5448
5449 pExtra_data += field_total_size;
5450 extra_size_remaining -= field_total_size;
5451 } while (extra_size_remaining);
5452 }
5453
5454 /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */
5455 /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */
5456 if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
5457 {
5458 mz_uint8 descriptor_buf[32];
5459 mz_bool has_id;
5460 const mz_uint8 *pSrc;
5461 mz_uint32 file_crc32;
5462 mz_uint64 comp_size = 0, uncomp_size = 0;
5463
5464 mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
5465
5466 if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s))
5467 {
5469 goto handle_failure;
5470 }
5471
5472 has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
5473 pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
5474
5475 file_crc32 = MZ_READ_LE32(pSrc);
5476
5477 if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
5478 {
5479 comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
5480 uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
5481 }
5482 else
5483 {
5484 comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
5485 uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
5486 }
5487
5488 if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
5489 {
5491 goto handle_failure;
5492 }
5493 }
5494 else
5495 {
5496 if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size))
5497 {
5499 goto handle_failure;
5500 }
5501 }
5502
5503 mz_zip_array_clear(pZip, &file_data_array);
5504
5505 if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
5506 {
5507 if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
5508 return MZ_FALSE;
5509
5510 /* 1 more check to be sure, although the extract checks too. */
5511 if (uncomp_crc32 != file_stat.m_crc32)
5512 {
5514 return MZ_FALSE;
5515 }
5516 }
5517
5518 return MZ_TRUE;
5519
5520handle_failure:
5521 mz_zip_array_clear(pZip, &file_data_array);
5522 return MZ_FALSE;
5523}
5524
5526{
5527 mz_zip_internal_state *pState;
5528 mz_uint32 i;
5529
5530 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5532
5533 pState = pZip->m_pState;
5534
5535 /* Basic sanity checks */
5536 if (!pState->m_zip64)
5537 {
5538 if (pZip->m_total_files > MZ_UINT16_MAX)
5540
5541 if (pZip->m_archive_size > MZ_UINT32_MAX)
5543 }
5544 else
5545 {
5546 if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5548 }
5549
5550 for (i = 0; i < pZip->m_total_files; i++)
5551 {
5553 {
5554 mz_uint32 found_index;
5556
5557 if (!mz_zip_reader_file_stat(pZip, i, &stat))
5558 return MZ_FALSE;
5559
5560 if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5561 return MZ_FALSE;
5562
5563 /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */
5564 if (found_index != i)
5566 }
5567
5568 if (!mz_zip_validate_file(pZip, i, flags))
5569 return MZ_FALSE;
5570 }
5571
5572 return MZ_TRUE;
5573}
5574
5575mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
5576{
5577 mz_bool success = MZ_TRUE;
5578 mz_zip_archive zip;
5579 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5580
5581 if ((!pMem) || (!size))
5582 {
5583 if (pErr)
5585 return MZ_FALSE;
5586 }
5587
5588 mz_zip_zero_struct(&zip);
5589
5590 if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5591 {
5592 if (pErr)
5593 *pErr = zip.m_last_error;
5594 return MZ_FALSE;
5595 }
5596
5597 if (!mz_zip_validate_archive(&zip, flags))
5598 {
5599 actual_err = zip.m_last_error;
5600 success = MZ_FALSE;
5601 }
5602
5603 if (!mz_zip_reader_end_internal(&zip, success))
5604 {
5605 if (!actual_err)
5606 actual_err = zip.m_last_error;
5607 success = MZ_FALSE;
5608 }
5609
5610 if (pErr)
5611 *pErr = actual_err;
5612
5613 return success;
5614}
5615
5616#ifndef MINIZ_NO_STDIO
5617mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
5618{
5619 mz_bool success = MZ_TRUE;
5620 mz_zip_archive zip;
5621 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5622
5623 if (!pFilename)
5624 {
5625 if (pErr)
5627 return MZ_FALSE;
5628 }
5629
5630 mz_zip_zero_struct(&zip);
5631
5632 if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5633 {
5634 if (pErr)
5635 *pErr = zip.m_last_error;
5636 return MZ_FALSE;
5637 }
5638
5639 if (!mz_zip_validate_archive(&zip, flags))
5640 {
5641 actual_err = zip.m_last_error;
5642 success = MZ_FALSE;
5643 }
5644
5645 if (!mz_zip_reader_end_internal(&zip, success))
5646 {
5647 if (!actual_err)
5648 actual_err = zip.m_last_error;
5649 success = MZ_FALSE;
5650 }
5651
5652 if (pErr)
5653 *pErr = actual_err;
5654
5655 return success;
5656}
5657#endif /* #ifndef MINIZ_NO_STDIO */
5658
5659/* ------------------- .ZIP archive writing */
5660
5661#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5662
5664{
5665 p[0] = (mz_uint8)v;
5666 p[1] = (mz_uint8)(v >> 8);
5667}
5669{
5670 p[0] = (mz_uint8)v;
5671 p[1] = (mz_uint8)(v >> 8);
5672 p[2] = (mz_uint8)(v >> 16);
5673 p[3] = (mz_uint8)(v >> 24);
5674}
5676{
5677 mz_write_le32(p, (mz_uint32)v);
5678 mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
5679}
5680
5681#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5682#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5683#define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
5684
5685static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5686{
5687 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5688 mz_zip_internal_state *pState = pZip->m_pState;
5689 mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5690
5691 if (!n)
5692 return 0;
5693
5694 /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
5695 if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5696 {
5698 return 0;
5699 }
5700
5701 if (new_size > pState->m_mem_capacity)
5702 {
5703 void *pNew_block;
5704 size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5705
5706 while (new_capacity < new_size)
5707 new_capacity *= 2;
5708
5709 if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5710 {
5712 return 0;
5713 }
5714
5715 pState->m_pMem = pNew_block;
5716 pState->m_mem_capacity = new_capacity;
5717 }
5718 memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5719 pState->m_mem_size = (size_t)new_size;
5720 return n;
5721}
5722
5724{
5725 mz_zip_internal_state *pState;
5726 mz_bool status = MZ_TRUE;
5727
5728 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
5729 {
5730 if (set_last_error)
5732 return MZ_FALSE;
5733 }
5734
5735 pState = pZip->m_pState;
5736 pZip->m_pState = NULL;
5737 mz_zip_array_clear(pZip, &pState->m_central_dir);
5740
5741#ifndef MINIZ_NO_STDIO
5742 if (pState->m_pFile)
5743 {
5744 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5745 {
5746 if (MZ_FCLOSE(pState->m_pFile) == EOF)
5747 {
5748 if (set_last_error)
5750 status = MZ_FALSE;
5751 }
5752 }
5753
5754 pState->m_pFile = NULL;
5755 }
5756#endif /* #ifndef MINIZ_NO_STDIO */
5757
5758 if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5759 {
5760 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5761 pState->m_pMem = NULL;
5762 }
5763
5764 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5766 return status;
5767}
5768
5770{
5771 mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5772
5773 if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5775
5777 {
5778 if (!pZip->m_pRead)
5780 }
5781
5782 if (pZip->m_file_offset_alignment)
5783 {
5784 /* Ensure user specified file offset alignment is a power of 2. */
5785 if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5787 }
5788
5789 if (!pZip->m_pAlloc)
5791 if (!pZip->m_pFree)
5793 if (!pZip->m_pRealloc)
5795
5796 pZip->m_archive_size = existing_size;
5798 pZip->m_total_files = 0;
5799
5800 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5802
5803 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5804
5808
5809 pZip->m_pState->m_zip64 = zip64;
5811
5814
5815 return MZ_TRUE;
5816}
5817
5819{
5820 return mz_zip_writer_init_v2(pZip, existing_size, 0);
5821}
5822
5823mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
5824{
5826 pZip->m_pNeeds_keepalive = NULL;
5827
5830
5831 pZip->m_pIO_opaque = pZip;
5832
5833 if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5834 return MZ_FALSE;
5835
5837
5838 if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5839 {
5840 if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5841 {
5844 }
5845 pZip->m_pState->m_mem_capacity = initial_allocation_size;
5846 }
5847
5848 return MZ_TRUE;
5849}
5850
5851mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
5852{
5853 return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5854}
5855
5856#ifndef MINIZ_NO_STDIO
5857static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5858{
5859 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5860 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5861
5862 file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5863
5864 if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5865 {
5867 return 0;
5868 }
5869
5870 return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5871}
5872
5873mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5874{
5875 return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5876}
5877
5878mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)
5879{
5880 MZ_FILE *pFile;
5881
5883 pZip->m_pNeeds_keepalive = NULL;
5884
5887
5888 pZip->m_pIO_opaque = pZip;
5889
5890 if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5891 return MZ_FALSE;
5892
5893 if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
5894 {
5895 mz_zip_writer_end(pZip);
5897 }
5898
5899 pZip->m_pState->m_pFile = pFile;
5901
5902 if (size_to_reserve_at_beginning)
5903 {
5904 mz_uint64 cur_ofs = 0;
5905 char buf[4096];
5906
5908
5909 do
5910 {
5911 size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5912 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5913 {
5914 mz_zip_writer_end(pZip);
5916 }
5917 cur_ofs += n;
5918 size_to_reserve_at_beginning -= n;
5919 } while (size_to_reserve_at_beginning);
5920 }
5921
5922 return MZ_TRUE;
5923}
5924
5926{
5928 pZip->m_pNeeds_keepalive = NULL;
5929
5932
5933 pZip->m_pIO_opaque = pZip;
5934
5935 if (!mz_zip_writer_init_v2(pZip, 0, flags))
5936 return MZ_FALSE;
5937
5938 pZip->m_pState->m_pFile = pFile;
5941
5942 return MZ_TRUE;
5943}
5944#endif /* #ifndef MINIZ_NO_STDIO */
5945
5947{
5948 mz_zip_internal_state *pState;
5949
5950 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5952
5953 if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
5954 {
5955 /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */
5956 if (!pZip->m_pState->m_zip64)
5958 }
5959
5960 /* No sense in trying to write to an archive that's already at the support max size */
5961 if (pZip->m_pState->m_zip64)
5962 {
5963 if (pZip->m_total_files == MZ_UINT32_MAX)
5965 }
5966 else
5967 {
5968 if (pZip->m_total_files == MZ_UINT16_MAX)
5970
5973 }
5974
5975 pState = pZip->m_pState;
5976
5977 if (pState->m_pFile)
5978 {
5979#ifdef MINIZ_NO_STDIO
5980 (void)pFilename;
5982#else
5983 if (pZip->m_pIO_opaque != pZip)
5985
5986 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5987 {
5988 if (!pFilename)
5990
5991 /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
5992 if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
5993 {
5994 /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
5997 }
5998 }
5999
6001 pZip->m_pNeeds_keepalive = NULL;
6002#endif /* #ifdef MINIZ_NO_STDIO */
6003 }
6004 else if (pState->m_pMem)
6005 {
6006 /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
6007 if (pZip->m_pIO_opaque != pZip)
6009
6010 pState->m_mem_capacity = pState->m_mem_size;
6012 pZip->m_pNeeds_keepalive = NULL;
6013 }
6014 /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
6015 else if (!pZip->m_pWrite)
6017
6018 /* Start writing new files at the archive's current central directory location. */
6019 /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */
6022
6023 /* Clear the sorted central dir offsets, they aren't useful or maintained now. */
6024 /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */
6025 /* TODO: We could easily maintain the sorted central directory offsets. */
6027
6029
6030 return MZ_TRUE;
6031}
6032
6034{
6035 return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
6036}
6037
6038/* TODO: pArchive_name is a terrible name here! */
6039mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
6040{
6041 return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
6042}
6043
6050
6051static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
6052{
6054 if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
6055 return MZ_FALSE;
6056
6057 pState->m_cur_archive_file_ofs += len;
6058 pState->m_comp_size += len;
6059 return MZ_TRUE;
6060}
6061
6062#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
6063#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
6064static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)
6065{
6066 mz_uint8 *pDst = pBuf;
6067 mz_uint32 field_size = 0;
6068
6070 MZ_WRITE_LE16(pDst + 2, 0);
6071 pDst += sizeof(mz_uint16) * 2;
6072
6073 if (pUncomp_size)
6074 {
6075 MZ_WRITE_LE64(pDst, *pUncomp_size);
6076 pDst += sizeof(mz_uint64);
6077 field_size += sizeof(mz_uint64);
6078 }
6079
6080 if (pComp_size)
6081 {
6082 MZ_WRITE_LE64(pDst, *pComp_size);
6083 pDst += sizeof(mz_uint64);
6084 field_size += sizeof(mz_uint64);
6085 }
6086
6087 if (pLocal_header_ofs)
6088 {
6089 MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
6090 pDst += sizeof(mz_uint64);
6091 field_size += sizeof(mz_uint64);
6092 }
6093
6094 MZ_WRITE_LE16(pBuf + 2, field_size);
6095
6096 return (mz_uint32)(pDst - pBuf);
6097}
6098
6099static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
6100{
6101 (void)pZip;
6102 memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
6104 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6105 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
6106 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
6107 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
6108 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
6109 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
6112 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6113 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6114 return MZ_TRUE;
6115}
6116
6118 mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
6119 mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6120 mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6121 mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
6122{
6123 (void)pZip;
6124 memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6126 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6127 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6128 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6129 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6130 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6131 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6134 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6135 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6136 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6137 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6139 return MZ_TRUE;
6140}
6141
6142static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6143 const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,
6144 mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6145 mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6146 mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
6147 const char *user_extra_data, mz_uint user_extra_data_len)
6148{
6149 mz_zip_internal_state *pState = pZip->m_pState;
6150 mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6151 size_t orig_central_dir_size = pState->m_central_dir.m_size;
6152 mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6153
6154 if (!pZip->m_pState->m_zip64)
6155 {
6156 if (local_header_ofs > 0xFFFFFFFF)
6158 }
6159
6160 /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6161 if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX)
6163
6164 if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, (mz_uint16)(extra_size + user_extra_data_len), comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
6166
6167 if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6168 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
6169 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
6170 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
6171 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
6172 (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
6173 {
6174 /* Try to resize the central directory array back into its original state. */
6175 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6177 }
6178
6179 return MZ_TRUE;
6180}
6181
6182static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
6183{
6184 /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */
6185 if (*pArchive_name == '/')
6186 return MZ_FALSE;
6187
6188 /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/
6189
6190 return MZ_TRUE;
6191}
6192
6194{
6195 mz_uint32 n;
6196 if (!pZip->m_file_offset_alignment)
6197 return 0;
6198 n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6199 return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
6200}
6201
6203{
6204 char buf[4096];
6205 memset(buf, 0, MZ_MIN(sizeof(buf), n));
6206 while (n)
6207 {
6208 mz_uint32 s = MZ_MIN(sizeof(buf), n);
6209 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6211
6212 cur_file_ofs += s;
6213 n -= s;
6214 }
6215 return MZ_TRUE;
6216}
6217
6218mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6219 mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
6220{
6221 return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0);
6222}
6223
6224mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size,
6225 mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
6226 const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6227{
6228 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6229 mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6230 mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6231 size_t archive_name_size;
6232 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6233 tdefl_compressor *pComp = NULL;
6234 mz_bool store_data_uncompressed;
6235 mz_zip_internal_state *pState;
6236 mz_uint8 *pExtra_data = NULL;
6237 mz_uint32 extra_size = 0;
6239 mz_uint16 bit_flags = 0;
6240
6241 if ((int)level_and_flags < 0)
6242 level_and_flags = MZ_DEFAULT_LEVEL;
6243
6244 if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
6246
6247 if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6249
6250 level = level_and_flags & 0xF;
6251 store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6252
6253 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6255
6256 pState = pZip->m_pState;
6257
6258 if (pState->m_zip64)
6259 {
6260 if (pZip->m_total_files == MZ_UINT32_MAX)
6262 }
6263 else
6264 {
6265 if (pZip->m_total_files == MZ_UINT16_MAX)
6266 {
6267 pState->m_zip64 = MZ_TRUE;
6268 /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6269 }
6270 if (((mz_uint64)buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6271 {
6272 pState->m_zip64 = MZ_TRUE;
6273 /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6274 }
6275 }
6276
6277 if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6279
6280 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6282
6283#ifndef MINIZ_NO_TIME
6284 if (last_modified != NULL)
6285 {
6286 mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
6287 }
6288 else
6289 {
6290 MZ_TIME_T cur_time;
6291 time(&cur_time);
6292 mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6293 }
6294#endif /* #ifndef MINIZ_NO_TIME */
6295
6296 if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6297 {
6298 uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6299 uncomp_size = buf_size;
6300 if (uncomp_size <= 3)
6301 {
6302 level = 0;
6303 store_data_uncompressed = MZ_TRUE;
6304 }
6305 }
6306
6307 archive_name_size = strlen(pArchive_name);
6308 if (archive_name_size > MZ_UINT16_MAX)
6310
6311 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6312
6313 /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6316
6317 if (!pState->m_zip64)
6318 {
6319 /* Bail early if the archive would obviously become too large */
6320 if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size
6321 + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len +
6322 pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len
6323 + MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)
6324 {
6325 pState->m_zip64 = MZ_TRUE;
6326 /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6327 }
6328 }
6329
6330 if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
6331 {
6332 /* Set DOS Subdirectory attribute bit. */
6333 ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
6334
6335 /* Subdirectories cannot contain data. */
6336 if ((buf_size) || (uncomp_size))
6338 }
6339
6340 /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */
6341 if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6343
6344 if ((!store_data_uncompressed) && (buf_size))
6345 {
6346 if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6348 }
6349
6350 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6351 {
6352 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6353 return MZ_FALSE;
6354 }
6355
6356 local_dir_header_ofs += num_alignment_padding_bytes;
6357 if (pZip->m_file_offset_alignment)
6358 {
6359 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6360 }
6361 cur_archive_file_ofs += num_alignment_padding_bytes;
6362
6363 MZ_CLEAR_ARR(local_dir_header);
6364
6365 if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6366 {
6367 method = MZ_DEFLATED;
6368 }
6369
6370 if (pState->m_zip64)
6371 {
6372 if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6373 {
6374 pExtra_data = extra_data;
6375 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6376 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6377 }
6378
6379 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, bit_flags, dos_time, dos_date))
6381
6382 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6384
6385 cur_archive_file_ofs += sizeof(local_dir_header);
6386
6387 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6388 {
6389 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6391 }
6392 cur_archive_file_ofs += archive_name_size;
6393
6394 if (pExtra_data != NULL)
6395 {
6396 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6398
6399 cur_archive_file_ofs += extra_size;
6400 }
6401 }
6402 else
6403 {
6404 if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6406 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
6408
6409 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6411
6412 cur_archive_file_ofs += sizeof(local_dir_header);
6413
6414 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6415 {
6416 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6418 }
6419 cur_archive_file_ofs += archive_name_size;
6420 }
6421
6422 if (user_extra_data_len > 0)
6423 {
6424 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6426
6427 cur_archive_file_ofs += user_extra_data_len;
6428 }
6429
6430 if (store_data_uncompressed)
6431 {
6432 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
6433 {
6434 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6436 }
6437
6438 cur_archive_file_ofs += buf_size;
6439 comp_size = buf_size;
6440 }
6441 else if (buf_size)
6442 {
6444
6445 state.m_pZip = pZip;
6446 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6447 state.m_comp_size = 0;
6448
6450 (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
6451 {
6452 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6454 }
6455
6456 comp_size = state.m_comp_size;
6457 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6458 }
6459
6460 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6461 pComp = NULL;
6462
6463 if (uncomp_size)
6464 {
6465 mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6466 mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6467
6469
6470 MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6471 MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6472 if (pExtra_data == NULL)
6473 {
6474 if (comp_size > MZ_UINT32_MAX)
6476
6477 MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6478 MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6479 }
6480 else
6481 {
6482 MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6483 MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6484 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6485 }
6486
6487 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6488 return MZ_FALSE;
6489
6490 cur_archive_file_ofs += local_dir_footer_size;
6491 }
6492
6493 if (pExtra_data != NULL)
6494 {
6495 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6496 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6497 }
6498
6499 if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment,
6500 comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6501 user_extra_data_central, user_extra_data_central_len))
6502 return MZ_FALSE;
6503
6504 pZip->m_total_files++;
6505 pZip->m_archive_size = cur_archive_file_ofs;
6506
6507 return MZ_TRUE;
6508}
6509
6510mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6511 const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6512{
6513 mz_uint16 gen_flags;
6514 mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6515 mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6516 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
6517 size_t archive_name_size;
6518 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6519 mz_uint8 *pExtra_data = NULL;
6520 mz_uint32 extra_size = 0;
6522 mz_zip_internal_state *pState;
6523 mz_uint64 file_ofs = 0, cur_archive_header_file_ofs;
6524
6525 if ((int)level_and_flags < 0)
6526 level_and_flags = MZ_DEFAULT_LEVEL;
6527 level = level_and_flags & 0xF;
6528
6529 gen_flags = (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) ? 0 : MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6530
6531 if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6533
6534 /* Sanity checks */
6535 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6537
6538 pState = pZip->m_pState;
6539
6540 if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX))
6541 {
6542 /* Source file is too large for non-zip64 */
6543 /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6544 pState->m_zip64 = MZ_TRUE;
6545 }
6546
6547 /* We could support this, but why? */
6548 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6550
6551 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6553
6554 if (pState->m_zip64)
6555 {
6556 if (pZip->m_total_files == MZ_UINT32_MAX)
6558 }
6559 else
6560 {
6561 if (pZip->m_total_files == MZ_UINT16_MAX)
6562 {
6563 pState->m_zip64 = MZ_TRUE;
6564 /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6565 }
6566 }
6567
6568 archive_name_size = strlen(pArchive_name);
6569 if (archive_name_size > MZ_UINT16_MAX)
6571
6572 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6573
6574 /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6577
6578 if (!pState->m_zip64)
6579 {
6580 /* Bail early if the archive would obviously become too large */
6581 if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
6582 + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024
6583 + MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)
6584 {
6585 pState->m_zip64 = MZ_TRUE;
6586 /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6587 }
6588 }
6589
6590#ifndef MINIZ_NO_TIME
6591 if (pFile_time)
6592 {
6593 mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6594 }
6595#endif
6596
6597 if (max_size <= 3)
6598 level = 0;
6599
6600 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6601 {
6603 }
6604
6605 cur_archive_file_ofs += num_alignment_padding_bytes;
6606 local_dir_header_ofs = cur_archive_file_ofs;
6607
6608 if (pZip->m_file_offset_alignment)
6609 {
6610 MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6611 }
6612
6613 if (max_size && level)
6614 {
6615 method = MZ_DEFLATED;
6616 }
6617
6618 MZ_CLEAR_ARR(local_dir_header);
6619 if (pState->m_zip64)
6620 {
6621 if (max_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6622 {
6623 pExtra_data = extra_data;
6624 if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)
6625 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6626 (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL,
6627 (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6628 else
6629 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, NULL,
6630 NULL,
6631 (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6632 }
6633
6634 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date))
6636
6637 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6639
6640 cur_archive_file_ofs += sizeof(local_dir_header);
6641
6642 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6643 {
6645 }
6646
6647 cur_archive_file_ofs += archive_name_size;
6648
6649 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6651
6652 cur_archive_file_ofs += extra_size;
6653 }
6654 else
6655 {
6656 if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6658 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
6660
6661 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6663
6664 cur_archive_file_ofs += sizeof(local_dir_header);
6665
6666 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6667 {
6669 }
6670
6671 cur_archive_file_ofs += archive_name_size;
6672 }
6673
6674 if (user_extra_data_len > 0)
6675 {
6676 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6678
6679 cur_archive_file_ofs += user_extra_data_len;
6680 }
6681
6682 if (max_size)
6683 {
6684 void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6685 if (!pRead_buf)
6686 {
6688 }
6689
6690 if (!level)
6691 {
6692 while (1)
6693 {
6694 size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE);
6695 if (n == 0)
6696 break;
6697
6698 if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size))
6699 {
6700 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6702 }
6703 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)
6704 {
6705 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6707 }
6708 file_ofs += n;
6709 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6710 cur_archive_file_ofs += n;
6711 }
6712 uncomp_size = file_ofs;
6713 comp_size = uncomp_size;
6714 }
6715 else
6716 {
6717 mz_bool result = MZ_FALSE;
6719 tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6720 if (!pComp)
6721 {
6722 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6724 }
6725
6726 state.m_pZip = pZip;
6727 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6728 state.m_comp_size = 0;
6729
6731 {
6732 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6733 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6735 }
6736
6737 for (;;)
6738 {
6739 tdefl_status status;
6741
6742 size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE);
6743 if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size))
6744 {
6746 break;
6747 }
6748
6749 file_ofs += n;
6750 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6751
6752 if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6753 flush = TDEFL_FULL_FLUSH;
6754
6755 if (n == 0)
6756 flush = TDEFL_FINISH;
6757
6758 status = tdefl_compress_buffer(pComp, pRead_buf, n, flush);
6759 if (status == TDEFL_STATUS_DONE)
6760 {
6761 result = MZ_TRUE;
6762 break;
6763 }
6764 else if (status != TDEFL_STATUS_OKAY)
6765 {
6767 break;
6768 }
6769 }
6770
6771 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6772
6773 if (!result)
6774 {
6775 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6776 return MZ_FALSE;
6777 }
6778
6779 uncomp_size = file_ofs;
6780 comp_size = state.m_comp_size;
6781 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6782 }
6783
6784 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6785 }
6786
6787 if (!(level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE))
6788 {
6789 mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6790 mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6791
6792 MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6793 MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6794 if (pExtra_data == NULL)
6795 {
6796 if (comp_size > MZ_UINT32_MAX)
6798
6799 MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6800 MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6801 }
6802 else
6803 {
6804 MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6805 MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6806 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6807 }
6808
6809 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6810 return MZ_FALSE;
6811
6812 cur_archive_file_ofs += local_dir_footer_size;
6813 }
6814
6815 if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)
6816 {
6817 if (pExtra_data != NULL)
6818 {
6819 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6820 (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6821 }
6822
6823 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header,
6824 (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len),
6825 (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size,
6826 (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size,
6827 uncomp_crc32, method, gen_flags, dos_time, dos_date))
6829
6830 cur_archive_header_file_ofs = local_dir_header_ofs;
6831
6832 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6834
6835 if (pExtra_data != NULL)
6836 {
6837 cur_archive_header_file_ofs += sizeof(local_dir_header);
6838
6839 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6840 {
6842 }
6843
6844 cur_archive_header_file_ofs += archive_name_size;
6845
6846 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, extra_data, extra_size) != extra_size)
6848
6849 cur_archive_header_file_ofs += extra_size;
6850 }
6851 }
6852
6853 if (pExtra_data != NULL)
6854 {
6855 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6856 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6857 }
6858
6859 if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, comment_size,
6860 uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6861 user_extra_data_central, user_extra_data_central_len))
6862 return MZ_FALSE;
6863
6864 pZip->m_total_files++;
6865 pZip->m_archive_size = cur_archive_file_ofs;
6866
6867 return MZ_TRUE;
6868}
6869
6870#ifndef MINIZ_NO_STDIO
6871
6872static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
6873{
6874 MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
6875 mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
6876
6877 if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
6878 return 0;
6879
6880 return MZ_FREAD(pBuf, 1, n, pSrc_file);
6881}
6882
6883mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6884 const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6885{
6886 return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, max_size, pFile_time, pComment, comment_size, level_and_flags,
6887 user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len);
6888}
6889
6890mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
6891{
6892 MZ_FILE *pSrc_file = NULL;
6893 mz_uint64 uncomp_size = 0;
6894 MZ_TIME_T file_modified_time;
6895 MZ_TIME_T *pFile_time = NULL;
6896 mz_bool status;
6897
6898 memset(&file_modified_time, 0, sizeof(file_modified_time));
6899
6900#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6901 pFile_time = &file_modified_time;
6902 if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6904#endif
6905
6906 pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6907 if (!pSrc_file)
6909
6910 MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6911 uncomp_size = MZ_FTELL64(pSrc_file);
6912 MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6913
6914 status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0);
6915
6916 MZ_FCLOSE(pSrc_file);
6917
6918 return status;
6919}
6920#endif /* #ifndef MINIZ_NO_STDIO */
6921
6922static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, mz_uint32 ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)
6923{
6924 /* + 64 should be enough for any new zip64 data */
6925 if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6927
6928 mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6929
6930 if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6931 {
6932 mz_uint8 new_ext_block[64];
6933 mz_uint8 *pDst = new_ext_block;
6935 mz_write_le16(pDst + sizeof(mz_uint16), 0);
6936 pDst += sizeof(mz_uint16) * 2;
6937
6938 if (pUncomp_size)
6939 {
6940 mz_write_le64(pDst, *pUncomp_size);
6941 pDst += sizeof(mz_uint64);
6942 }
6943
6944 if (pComp_size)
6945 {
6946 mz_write_le64(pDst, *pComp_size);
6947 pDst += sizeof(mz_uint64);
6948 }
6949
6950 if (pLocal_header_ofs)
6951 {
6952 mz_write_le64(pDst, *pLocal_header_ofs);
6953 pDst += sizeof(mz_uint64);
6954 }
6955
6956 if (pDisk_start)
6957 {
6958 mz_write_le32(pDst, *pDisk_start);
6959 pDst += sizeof(mz_uint32);
6960 }
6961
6962 mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
6963
6964 if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
6966 }
6967
6968 if ((pExt) && (ext_len))
6969 {
6970 mz_uint32 extra_size_remaining = ext_len;
6971 const mz_uint8 *pExtra_data = pExt;
6972
6973 do
6974 {
6975 mz_uint32 field_id, field_data_size, field_total_size;
6976
6977 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6979
6980 field_id = MZ_READ_LE16(pExtra_data);
6981 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6982 field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6983
6984 if (field_total_size > extra_size_remaining)
6986
6988 {
6989 if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
6991 }
6992
6993 pExtra_data += field_total_size;
6994 extra_size_remaining -= field_total_size;
6995 } while (extra_size_remaining);
6996 }
6997
6998 return MZ_TRUE;
6999}
7000
7001/* TODO: This func is now pretty freakin complex due to zip64, split it up? */
7003{
7004 mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
7005 mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
7006 mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
7007 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
7008 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
7009 mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
7010 size_t orig_central_dir_size;
7011 mz_zip_internal_state *pState;
7012 void *pBuf;
7013 const mz_uint8 *pSrc_central_header;
7014 mz_zip_archive_file_stat src_file_stat;
7015 mz_uint32 src_filename_len, src_comment_len, src_ext_len;
7016 mz_uint32 local_header_filename_size, local_header_extra_len;
7017 mz_uint64 local_header_comp_size, local_header_uncomp_size;
7018 mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
7019
7020 /* Sanity checks */
7021 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
7023
7024 pState = pZip->m_pState;
7025
7026 /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */
7027 if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
7029
7030 /* Get pointer to the source central dir header and crack it */
7031 if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
7033
7036
7037 src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7038 src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
7039 src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
7040 src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
7041
7042 /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */
7043 if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
7045
7046 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
7047
7048 if (!pState->m_zip64)
7049 {
7050 if (pZip->m_total_files == MZ_UINT16_MAX)
7052 }
7053 else
7054 {
7055 /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
7056 if (pZip->m_total_files == MZ_UINT32_MAX)
7058 }
7059
7060 if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
7061 return MZ_FALSE;
7062
7063 cur_src_file_ofs = src_file_stat.m_local_header_ofs;
7064 cur_dst_file_ofs = pZip->m_archive_size;
7065
7066 /* Read the source archive's local dir header */
7067 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
7069
7070 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
7072
7073 cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
7074
7075 /* Compute the total size we need to copy (filename+extra data+compressed data) */
7076 local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
7077 local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
7078 local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
7079 local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
7080 src_archive_bytes_remaining = src_file_stat.m_comp_size + local_header_filename_size + local_header_extra_len ;
7081
7082 /* Try to find a zip64 extended information field */
7083 if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
7084 {
7085 mz_zip_array file_data_array;
7086 const mz_uint8 *pExtra_data;
7087 mz_uint32 extra_size_remaining = local_header_extra_len;
7088
7089 mz_zip_array_init(&file_data_array, 1);
7090 if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
7091 {
7093 }
7094
7095 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
7096 {
7097 mz_zip_array_clear(pZip, &file_data_array);
7099 }
7100
7101 pExtra_data = (const mz_uint8 *)file_data_array.m_p;
7102
7103 do
7104 {
7105 mz_uint32 field_id, field_data_size, field_total_size;
7106
7107 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
7108 {
7109 mz_zip_array_clear(pZip, &file_data_array);
7111 }
7112
7113 field_id = MZ_READ_LE16(pExtra_data);
7114 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
7115 field_total_size = field_data_size + sizeof(mz_uint16) * 2;
7116
7117 if (field_total_size > extra_size_remaining)
7118 {
7119 mz_zip_array_clear(pZip, &file_data_array);
7121 }
7122
7124 {
7125 const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
7126
7127 if (field_data_size < sizeof(mz_uint64) * 2)
7128 {
7129 mz_zip_array_clear(pZip, &file_data_array);
7131 }
7132
7133 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
7134 local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
7135
7136 found_zip64_ext_data_in_ldir = MZ_TRUE;
7137 break;
7138 }
7139
7140 pExtra_data += field_total_size;
7141 extra_size_remaining -= field_total_size;
7142 } while (extra_size_remaining);
7143
7144 mz_zip_array_clear(pZip, &file_data_array);
7145 }
7146
7147 if (!pState->m_zip64)
7148 {
7149 /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */
7150 /* We also check when the archive is finalized so this doesn't need to be perfect. */
7151 mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) +
7152 pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64;
7153
7154 if (approx_new_archive_size >= MZ_UINT32_MAX)
7156 }
7157
7158 /* Write dest archive padding */
7159 if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
7160 return MZ_FALSE;
7161
7162 cur_dst_file_ofs += num_alignment_padding_bytes;
7163
7164 local_dir_header_ofs = cur_dst_file_ofs;
7165 if (pZip->m_file_offset_alignment)
7166 {
7167 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
7168 }
7169
7170 /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */
7171 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
7173
7174 cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
7175
7176 /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
7177 if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining)))))
7179
7180 while (src_archive_bytes_remaining)
7181 {
7182 n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
7183 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
7184 {
7185 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7187 }
7188 cur_src_file_ofs += n;
7189
7190 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7191 {
7192 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7194 }
7195 cur_dst_file_ofs += n;
7196
7197 src_archive_bytes_remaining -= n;
7198 }
7199
7200 /* Now deal with the optional data descriptor */
7201 bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
7202 if (bit_flags & 8)
7203 {
7204 /* Copy data descriptor */
7205 if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
7206 {
7207 /* src is zip64, dest must be zip64 */
7208
7209 /* name uint32_t's */
7210 /* id 1 (optional in zip64?) */
7211 /* crc 1 */
7212 /* comp_size 2 */
7213 /* uncomp_size 2 */
7214 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
7215 {
7216 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7218 }
7219
7220 n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
7221 }
7222 else
7223 {
7224 /* src is NOT zip64 */
7225 mz_bool has_id;
7226
7227 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
7228 {
7229 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7231 }
7232
7233 has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
7234
7235 if (pZip->m_pState->m_zip64)
7236 {
7237 /* dest is zip64, so upgrade the data descriptor */
7238 const mz_uint8 *pSrc_descriptor = (const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0);
7239 const mz_uint32 src_crc32 = MZ_READ_LE32(pSrc_descriptor);
7240 const mz_uint64 src_comp_size = MZ_READ_LE32(pSrc_descriptor + sizeof(mz_uint32));
7241 const mz_uint64 src_uncomp_size = MZ_READ_LE32(pSrc_descriptor + 2*sizeof(mz_uint32));
7242
7244 mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
7245 mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
7246 mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
7247
7248 n = sizeof(mz_uint32) * 6;
7249 }
7250 else
7251 {
7252 /* dest is NOT zip64, just copy it as-is */
7253 n = sizeof(mz_uint32) * (has_id ? 4 : 3);
7254 }
7255 }
7256
7257 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7258 {
7259 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7261 }
7262
7263 cur_src_file_ofs += n;
7264 cur_dst_file_ofs += n;
7265 }
7266 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7267
7268 /* Finally, add the new central dir header */
7269 orig_central_dir_size = pState->m_central_dir.m_size;
7270
7271 memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
7272
7273 if (pState->m_zip64)
7274 {
7275 /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */
7276 const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
7277 mz_zip_array new_ext_block;
7278
7279 mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
7280
7284
7285 if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL))
7286 {
7287 mz_zip_array_clear(pZip, &new_ext_block);
7288 return MZ_FALSE;
7289 }
7290
7291 MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
7292
7293 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7294 {
7295 mz_zip_array_clear(pZip, &new_ext_block);
7297 }
7298
7299 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
7300 {
7301 mz_zip_array_clear(pZip, &new_ext_block);
7302 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7304 }
7305
7306 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
7307 {
7308 mz_zip_array_clear(pZip, &new_ext_block);
7309 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7311 }
7312
7313 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len))
7314 {
7315 mz_zip_array_clear(pZip, &new_ext_block);
7316 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7318 }
7319
7320 mz_zip_array_clear(pZip, &new_ext_block);
7321 }
7322 else
7323 {
7324 /* sanity checks */
7325 if (cur_dst_file_ofs > MZ_UINT32_MAX)
7327
7328 if (local_dir_header_ofs >= MZ_UINT32_MAX)
7330
7331 MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
7332
7333 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7335
7336 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size))
7337 {
7338 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7340 }
7341 }
7342
7343 /* This shouldn't trigger unless we screwed up during the initial sanity checks */
7344 if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7345 {
7346 /* TODO: Support central dirs >= 32-bits in size */
7347 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7349 }
7350
7351 n = (mz_uint32)orig_central_dir_size;
7352 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
7353 {
7354 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7356 }
7357
7358 pZip->m_total_files++;
7359 pZip->m_archive_size = cur_dst_file_ofs;
7360
7361 return MZ_TRUE;
7362}
7363
7365{
7366 mz_zip_internal_state *pState;
7367 mz_uint64 central_dir_ofs, central_dir_size;
7368 mz_uint8 hdr[256];
7369
7370 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
7372
7373 pState = pZip->m_pState;
7374
7375 if (pState->m_zip64)
7376 {
7379 }
7380 else
7381 {
7384 }
7385
7386 central_dir_ofs = 0;
7387 central_dir_size = 0;
7388 if (pZip->m_total_files)
7389 {
7390 /* Write central directory */
7391 central_dir_ofs = pZip->m_archive_size;
7392 central_dir_size = pState->m_central_dir.m_size;
7393 pZip->m_central_directory_file_ofs = central_dir_ofs;
7394 if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
7396
7397 pZip->m_archive_size += central_dir_size;
7398 }
7399
7400 if (pState->m_zip64)
7401 {
7402 /* Write zip64 end of central directory header */
7403 mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
7404
7405 MZ_CLEAR_ARR(hdr);
7408 MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */
7412 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
7413 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
7416
7418
7419 /* Write zip64 end of central directory locator */
7420 MZ_CLEAR_ARR(hdr);
7422 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
7426
7428 }
7429
7430 /* Write end of central directory record */
7431 MZ_CLEAR_ARR(hdr);
7437
7440
7441#ifndef MINIZ_NO_STDIO
7442 if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
7444#endif /* #ifndef MINIZ_NO_STDIO */
7445
7447
7449 return MZ_TRUE;
7450}
7451
7453{
7454 if ((!ppBuf) || (!pSize))
7456
7457 *ppBuf = NULL;
7458 *pSize = 0;
7459
7460 if ((!pZip) || (!pZip->m_pState))
7462
7463 if (pZip->m_pWrite != mz_zip_heap_write_func)
7465
7467 return MZ_FALSE;
7468
7469 *ppBuf = pZip->m_pState->m_pMem;
7470 *pSize = pZip->m_pState->m_mem_size;
7471 pZip->m_pState->m_pMem = NULL;
7472 pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
7473
7474 return MZ_TRUE;
7475}
7476
7481
7482#ifndef MINIZ_NO_STDIO
7483mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
7484{
7485 return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL);
7486}
7487
7488mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)
7489{
7490 mz_bool status, created_new_archive = MZ_FALSE;
7491 mz_zip_archive zip_archive;
7492 struct MZ_FILE_STAT_STRUCT file_stat;
7493 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7494
7495 mz_zip_zero_struct(&zip_archive);
7496 if ((int)level_and_flags < 0)
7497 level_and_flags = MZ_DEFAULT_LEVEL;
7498
7499 if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
7500 {
7501 if (pErr)
7503 return MZ_FALSE;
7504 }
7505
7506 if (!mz_zip_writer_validate_archive_name(pArchive_name))
7507 {
7508 if (pErr)
7510 return MZ_FALSE;
7511 }
7512
7513 /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */
7514 /* So be sure to compile with _LARGEFILE64_SOURCE 1 */
7515 if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
7516 {
7517 /* Create a new archive. */
7518 if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
7519 {
7520 if (pErr)
7521 *pErr = zip_archive.m_last_error;
7522 return MZ_FALSE;
7523 }
7524
7525 created_new_archive = MZ_TRUE;
7526 }
7527 else
7528 {
7529 /* Append to an existing archive. */
7530 if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7531 {
7532 if (pErr)
7533 *pErr = zip_archive.m_last_error;
7534 return MZ_FALSE;
7535 }
7536
7537 if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))
7538 {
7539 if (pErr)
7540 *pErr = zip_archive.m_last_error;
7541
7542 mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
7543
7544 return MZ_FALSE;
7545 }
7546 }
7547
7548 status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
7549 actual_err = zip_archive.m_last_error;
7550
7551 /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */
7552 if (!mz_zip_writer_finalize_archive(&zip_archive))
7553 {
7554 if (!actual_err)
7555 actual_err = zip_archive.m_last_error;
7556
7557 status = MZ_FALSE;
7558 }
7559
7560 if (!mz_zip_writer_end_internal(&zip_archive, status))
7561 {
7562 if (!actual_err)
7563 actual_err = zip_archive.m_last_error;
7564
7565 status = MZ_FALSE;
7566 }
7567
7568 if ((!status) && (created_new_archive))
7569 {
7570 /* It's a new archive and something went wrong, so just delete it. */
7571 int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
7572 (void)ignoredStatus;
7573 }
7574
7575 if (pErr)
7576 *pErr = actual_err;
7577
7578 return status;
7579}
7580
7581void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)
7582{
7583 mz_uint32 file_index;
7584 mz_zip_archive zip_archive;
7585 void *p = NULL;
7586
7587 if (pSize)
7588 *pSize = 0;
7589
7590 if ((!pZip_filename) || (!pArchive_name))
7591 {
7592 if (pErr)
7594
7595 return NULL;
7596 }
7597
7598 mz_zip_zero_struct(&zip_archive);
7599 if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7600 {
7601 if (pErr)
7602 *pErr = zip_archive.m_last_error;
7603
7604 return NULL;
7605 }
7606
7607 if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
7608 {
7609 p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
7610 }
7611
7612 mz_zip_reader_end_internal(&zip_archive, p != NULL);
7613
7614 if (pErr)
7615 *pErr = zip_archive.m_last_error;
7616
7617 return p;
7618}
7619
7620void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
7621{
7622 return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
7623}
7624
7625#endif /* #ifndef MINIZ_NO_STDIO */
7626
7627#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
7628
7629/* ------------------- Misc utils */
7630
7632{
7633 return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
7634}
7635
7637{
7638 return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
7639}
7640
7642{
7643 mz_zip_error prev_err;
7644
7645 if (!pZip)
7647
7648 prev_err = pZip->m_last_error;
7649
7650 pZip->m_last_error = err_num;
7651 return prev_err;
7652}
7653
7655{
7656 if (!pZip)
7658
7659 return pZip->m_last_error;
7660}
7661
7666
7668{
7669 mz_zip_error prev_err;
7670
7671 if (!pZip)
7673
7674 prev_err = pZip->m_last_error;
7675
7677 return prev_err;
7678}
7679
7681{
7682 switch (mz_err)
7683 {
7684 case MZ_ZIP_NO_ERROR:
7685 return "no error";
7687 return "undefined error";
7689 return "too many files";
7691 return "file too large";
7693 return "unsupported method";
7695 return "unsupported encryption";
7697 return "unsupported feature";
7699 return "failed finding central directory";
7701 return "not a ZIP archive";
7703 return "invalid header or archive is corrupted";
7705 return "unsupported multidisk archive";
7707 return "decompression failed or archive is corrupted";
7709 return "compression failed";
7711 return "unexpected decompressed size";
7713 return "CRC-32 check failed";
7715 return "unsupported central directory size";
7717 return "allocation failed";
7719 return "file open failed";
7721 return "file create failed";
7723 return "file write failed";
7725 return "file read failed";
7727 return "file close failed";
7729 return "file seek failed";
7731 return "file stat failed";
7733 return "invalid parameter";
7735 return "invalid filename";
7737 return "buffer too small";
7739 return "internal error";
7741 return "file not found";
7743 return "archive is too large";
7745 return "validation failed";
7747 return "write callback failed";
7749 return "total errors";
7750 default:
7751 break;
7752 }
7753
7754 return "unknown error";
7755}
7756
7757/* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
7759{
7760 if ((!pZip) || (!pZip->m_pState))
7761 return MZ_FALSE;
7762
7763 return pZip->m_pState->m_zip64;
7764}
7765
7767{
7768 if ((!pZip) || (!pZip->m_pState))
7769 return 0;
7770
7771 return pZip->m_pState->m_central_dir.m_size;
7772}
7773
7775{
7776 return pZip ? pZip->m_total_files : 0;
7777}
7778
7780{
7781 if (!pZip)
7782 return 0;
7783 return pZip->m_archive_size;
7784}
7785
7787{
7788 if ((!pZip) || (!pZip->m_pState))
7789 return 0;
7790 return pZip->m_pState->m_file_archive_start_ofs;
7791}
7792
7794{
7795 if ((!pZip) || (!pZip->m_pState))
7796 return 0;
7797 return pZip->m_pState->m_pFile;
7798}
7799
7800size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
7801{
7802 if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
7804
7805 return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
7806}
7807
7808mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
7809{
7810 mz_uint n;
7811 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
7812 if (!p)
7813 {
7814 if (filename_buf_size)
7815 pFilename[0] = '\0';
7817 return 0;
7818 }
7820 if (filename_buf_size)
7821 {
7822 n = MZ_MIN(n, filename_buf_size - 1);
7823 memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
7824 pFilename[n] = '\0';
7825 }
7826 return n + 1;
7827}
7828
7830{
7831 return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
7832}
7833
7835{
7836 if (!pZip)
7837 return MZ_FALSE;
7838
7839 if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
7840 return mz_zip_reader_end(pZip);
7841#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7843 return mz_zip_writer_end(pZip);
7844#endif
7845
7846 return MZ_FALSE;
7847}
7848
7849#ifdef __cplusplus
7850}
7851#endif
7852
7853#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/
static GLfloat pA[6]
float y
voidpf void uLong size
Definition ioapi.h:134
voidpf stream
Definition ioapi.h:134
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
voidpf void * buf
Definition ioapi.h:134
#define MZ_WRITE_LE32(p, v)
Definition miniz.c:5682
#define MZ_FILE_STAT
Definition miniz.c:3221
#define TINFL_HUFF_DECODE(state_index, sym, pLookUp, pTree)
Definition miniz.c:2394
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
Definition miniz.c:41
static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes, const char *user_extra_data, mz_uint user_extra_data_len)
Definition miniz.c:6142
mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
Definition miniz.c:7758
@ MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS
Definition miniz.c:3303
@ MZ_ZIP_CDH_FILENAME_LEN_OFS
Definition miniz.c:3262
@ MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR
Definition miniz.c:3282
@ MZ_ZIP_LOCAL_DIR_HEADER_SIG
Definition miniz.c:3236
@ MZ_ZIP_CDH_FILE_DATE_OFS
Definition miniz.c:3258
@ MZ_ZIP_LDH_CRC32_OFS
Definition miniz.c:3277
@ MZ_ZIP64_ECDH_SIG_OFS
Definition miniz.c:3301
@ MZ_ZIP_LDH_BIT_FLAG_OFS
Definition miniz.c:3273
@ MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS
Definition miniz.c:3287
@ MZ_ZIP_CDH_VERSION_NEEDED_OFS
Definition miniz.c:3254
@ MZ_ZIP_DATA_DESCRIPTER_SIZE64
Definition miniz.c:3248
@ MZ_ZIP_CDH_LOCAL_HEADER_OFS
Definition miniz.c:3268
@ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG
Definition miniz.c:3242
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8
Definition miniz.c:3317
@ MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS
Definition miniz.c:3306
@ MZ_ZIP_CDH_COMPRESSED_SIZE_OFS
Definition miniz.c:3260
@ MZ_ZIP_DATA_DESCRIPTER_SIZE32
Definition miniz.c:3249
@ MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS
Definition miniz.c:3288
@ MZ_ZIP_CDH_SIG_OFS
Definition miniz.c:3252
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG
Definition miniz.c:3314
@ MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS
Definition miniz.c:3296
@ MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS
Definition miniz.c:3261
@ MZ_ZIP_ECDH_CDIR_SIZE_OFS
Definition miniz.c:3290
@ MZ_ZIP64_ECDL_SIG_OFS
Definition miniz.c:3295
@ MZ_ZIP_CDH_METHOD_OFS
Definition miniz.c:3256
@ MZ_ZIP_LDH_FILENAME_LEN_OFS
Definition miniz.c:3280
@ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE
Definition miniz.c:3245
@ MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG
Definition miniz.c:3312
@ MZ_ZIP_LDH_FILE_TIME_OFS
Definition miniz.c:3275
@ MZ_ZIP64_ECDH_VERSION_NEEDED_OFS
Definition miniz.c:3304
@ MZ_ZIP_CDH_EXTRA_LEN_OFS
Definition miniz.c:3263
@ MZ_ZIP_LDH_FILE_DATE_OFS
Definition miniz.c:3276
@ MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS
Definition miniz.c:3297
@ MZ_ZIP_LDH_METHOD_OFS
Definition miniz.c:3274
@ MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS
Definition miniz.c:3307
@ MZ_ZIP_LDH_COMPRESSED_SIZE_OFS
Definition miniz.c:3278
@ MZ_ZIP_CDH_FILE_TIME_OFS
Definition miniz.c:3257
@ MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID
Definition miniz.c:3311
@ MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS
Definition miniz.c:3289
@ MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID
Definition miniz.c:3246
@ MZ_ZIP_CENTRAL_DIR_HEADER_SIG
Definition miniz.c:3235
@ MZ_ZIP_ECDH_SIG_OFS
Definition miniz.c:3285
@ MZ_ZIP_ECDH_COMMENT_SIZE_OFS
Definition miniz.c:3292
@ MZ_ZIP64_ECDH_CDIR_SIZE_OFS
Definition miniz.c:3309
@ MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS
Definition miniz.c:3298
@ MZ_ZIP_LDH_SIG_OFS
Definition miniz.c:3271
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION
Definition miniz.c:3315
@ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG
Definition miniz.c:3234
@ MZ_ZIP_CDH_CRC32_OFS
Definition miniz.c:3259
@ MZ_ZIP_CDH_DISK_START_OFS
Definition miniz.c:3265
@ MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS
Definition miniz.c:3308
@ MZ_ZIP_CDH_INTERNAL_ATTR_OFS
Definition miniz.c:3266
@ MZ_ZIP_LDH_VERSION_NEEDED_OFS
Definition miniz.c:3272
@ MZ_ZIP_ECDH_CDIR_OFS_OFS
Definition miniz.c:3291
@ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG
Definition miniz.c:3243
@ MZ_ZIP_LDH_EXTRA_LEN_OFS
Definition miniz.c:3281
@ MZ_ZIP_CDH_EXTERNAL_ATTR_OFS
Definition miniz.c:3267
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED
Definition miniz.c:3316
@ MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS
Definition miniz.c:3305
@ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE
Definition miniz.c:3239
@ MZ_ZIP_LOCAL_DIR_HEADER_SIZE
Definition miniz.c:3237
@ MZ_ZIP64_ECDH_CDIR_OFS_OFS
Definition miniz.c:3310
@ MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS
Definition miniz.c:3279
@ MZ_ZIP_CDH_BIT_FLAG_OFS
Definition miniz.c:3255
@ MZ_ZIP_CDH_COMMENT_LEN_OFS
Definition miniz.c:3264
@ MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
Definition miniz.c:3238
@ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE
Definition miniz.c:3244
@ MZ_ZIP_DATA_DESCRIPTOR_ID
Definition miniz.c:3247
@ MZ_ZIP_CDH_VERSION_MADE_BY_OFS
Definition miniz.c:3253
@ MZ_ZIP_ECDH_NUM_THIS_DISK_OFS
Definition miniz.c:3286
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED
Definition miniz.c:3313
@ MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS
Definition miniz.c:3302
static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
Definition miniz.c:3417
static const mz_uint8 s_tdefl_len_extra[256]
Definition miniz.c:699
mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
Definition miniz.c:3971
int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len)
Definition miniz.c:563
mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
Definition miniz.c:5525
mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
Definition miniz.c:7364
mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
Definition miniz.c:7636
static const mz_uint s_tdefl_num_probes[11]
Definition miniz.c:1255
mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void *callback_opaque, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
Definition miniz.c:6510
static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
Definition miniz.c:4038
mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
Definition miniz.c:2039
static const mz_uint16 s_tdefl_len_sym[256]
Definition miniz.c:687
mz_bool mz_zip_end(mz_zip_archive *pZip)
Definition miniz.c:7834
static const mz_uint8 s_tdefl_packed_code_size_syms_swizzle[]
Definition miniz.c:989
static int tdefl_flush_block(tdefl_compressor *d, int flush)
Definition miniz.c:1257
static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
Definition miniz.c:5668
#define TINFL_CR_BEGIN
Definition miniz.c:2292
mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
Definition miniz.c:7774
void * tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
Definition miniz.c:2145
mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
Definition miniz.c:5873
#define MZ_WRITE_LE16(p, v)
Definition miniz.c:5681
void * tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
Definition miniz.c:2086
static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
Definition miniz.c:3568
static void tdefl_start_dynamic_block(tdefl_compressor *d)
Definition miniz.c:991
mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
Definition miniz.c:4051
int mz_deflateReset(mz_streamp pStream)
Definition miniz.c:234
#define TINFL_GET_BYTE(state_index, c)
Definition miniz.c:2316
#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size)
Definition miniz.c:3351
static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
Definition miniz.c:5723
size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
Definition miniz.c:7766
static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)
Definition miniz.c:4241
#define MZ_FFLUSH
Definition miniz.c:3222
int mz_inflateInit(mz_streamp pStream)
Definition miniz.c:409
int mz_inflate(mz_streamp pStream, int flush)
Definition miniz.c:440
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
Definition miniz.c:350
mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
Definition miniz.c:2034
mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
Definition miniz.c:4921
#define TDEFL_RLE_ZERO_CODE_SIZE()
Definition miniz.c:963
mz_ulong mz_compressBound(mz_ulong source_len)
Definition miniz.c:355
static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
Definition miniz.c:3485
static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)
Definition miniz.c:5663
mz_zip_reader_extract_iter_state * mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
Definition miniz.c:4930
static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
Definition miniz.c:3620
mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
Definition miniz.c:7483
int mz_deflateEnd(mz_streamp pStream)
Definition miniz.c:301
size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
Definition miniz.c:2101
mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
Definition miniz.c:7631
#define MZ_FREOPEN(f, m, s)
Definition miniz.c:3223
static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
Definition miniz.c:788
static const mz_uint8 s_tdefl_small_dist_sym[512]
Definition miniz.c:707
MINIZ_EXPORT void * miniz_def_alloc_func(void *opaque, size_t items, size_t size)
Definition miniz.c:168
tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
Definition miniz.c:1993
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
Definition miniz.c:1198
MINIZ_EXPORT void * miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
Definition miniz.c:178
size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
Definition miniz.c:7800
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
Definition miniz.c:2976
mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)
Definition miniz.c:5878
static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
Definition miniz.c:5857
mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
Definition miniz.c:4209
void * tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
Definition miniz.c:2929
static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
Definition miniz.c:2061
static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
Definition miniz.c:3471
mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)
Definition miniz.c:7488
mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
Definition miniz.c:4650
unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 :-1]
Definition miniz.c:32
mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
Definition miniz.c:6218
#define TINFL_MEMCPY(d, s, l)
Definition miniz.c:2289
#define TINFL_GET_BITS(state_index, b, n)
Definition miniz.c:2346
mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
Definition miniz.c:4438
static const mz_uint8 s_tdefl_small_dist_extra[512]
Definition miniz.c:723
tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
Definition miniz.c:2029
static void tinfl_clear_tree(tinfl_decompressor *r)
Definition miniz.c:2428
mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
Definition miniz.c:5851
#define MZ_FREAD
Definition miniz.c:3211
static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
Definition miniz.c:3505
static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
Definition miniz.c:3924
mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
Definition miniz.c:7654
mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
Definition miniz.c:3975
mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
Definition miniz.c:7667
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
Definition miniz.c:5270
#define MZ_FWRITE
Definition miniz.c:3212
tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
Definition miniz.c:1987
mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
Definition miniz.c:4721
mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
Definition miniz.c:5617
#define MZ_TOLOWER(c)
Definition miniz.c:3228
static const mz_uint8 s_tdefl_large_dist_extra[128]
Definition miniz.c:742
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
Definition miniz.c:198
mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
Definition miniz.c:4003
const char * mz_version(void)
Definition miniz.c:184
static mz_bool tdefl_compress_normal(tdefl_compressor *d)
Definition miniz.c:1753
int mz_deflateInit(mz_streamp pStream, int level)
Definition miniz.c:193
static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
Definition miniz.c:5229
void * mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)
Definition miniz.c:7581
#define MZ_FSEEK64
Definition miniz.c:3218
static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
Definition miniz.c:3364
const char * mz_zip_get_error_string(mz_zip_error mz_err)
Definition miniz.c:7680
static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
Definition miniz.c:1482
void * mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
Definition miniz.c:4673
static MZ_FORCEINLINE const mz_uint8 * mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
Definition miniz.c:4152
static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
Definition miniz.c:848
static void tdefl_start_static_block(tdefl_compressor *d)
Definition miniz.c:1078
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
Definition miniz.c:320
#define MZ_FOPEN(f, m)
Definition miniz.c:3209
static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
Definition miniz.c:3666
mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
Definition miniz.c:7477
static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
Definition miniz.c:6117
void mz_free(void *p)
Definition miniz.c:163
mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
Definition miniz.c:5925
#define TINFL_MEMSET(p, c, l)
Definition miniz.c:2290
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
Definition miniz.c:6890
static mz_bool mz_zip_reader_extract_to_mem_no_alloc1(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size, const mz_zip_archive_file_stat *st)
Definition miniz.c:4504
static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
Definition miniz.c:5685
static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
Definition miniz.c:3448
int mz_inflateReset(mz_streamp pStream)
Definition miniz.c:414
int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
Definition miniz.c:4429
static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
Definition miniz.c:3422
static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
Definition miniz.c:3433
mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
Definition miniz.c:4159
mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
Definition miniz.c:5818
const char * mz_error(int err)
Definition miniz.c:601
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
Definition miniz.c:96
void mz_zip_zero_struct(mz_zip_archive *pZip)
Definition miniz.c:3918
static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
Definition miniz.c:3370
static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
Definition miniz.c:4372
static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)
Definition miniz.c:6064
mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
Definition miniz.c:7779
size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state *pState, void *pvBuf, size_t buf_size)
Definition miniz.c:5070
MZ_FILE * mz_zip_get_cfile(mz_zip_archive *pZip)
Definition miniz.c:7793
static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, mz_uint32 ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)
Definition miniz.c:6922
static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
Definition miniz.c:6193
int mz_inflateInit2(mz_streamp pStream, int window_bits)
Definition miniz.c:373
static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
Definition miniz.c:6051
static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
Definition miniz.c:6182
static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
Definition miniz.c:3995
static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
Definition miniz.c:3539
static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
Definition miniz.c:3498
mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)
Definition miniz.c:7002
mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
Definition miniz.c:4173
#define TINFL_CR_FINISH
Definition miniz.c:2314
mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
Definition miniz.c:4663
#define TINFL_CR_RETURN(state_index, result)
Definition miniz.c:2296
#define TINFL_CR_RETURN_FOREVER(state_index, result)
Definition miniz.c:2305
mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
Definition miniz.c:7641
MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address)
Definition miniz.c:173
tinfl_decompressor * tinfl_decompressor_alloc(void)
Definition miniz.c:3007
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
Definition miniz.c:594
#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE
Definition miniz.c:6063
static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
Definition miniz.c:1712
mz_zip_reader_extract_iter_state * mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
Definition miniz.c:5058
void * mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
Definition miniz.c:7620
static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
Definition miniz.c:3396
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
Definition miniz.c:7829
mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
Definition miniz.c:5946
static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
Definition miniz.c:4389
mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)
Definition miniz.c:4056
void tdefl_compressor_free(tdefl_compressor *pComp)
Definition miniz.c:2238
mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
Definition miniz.c:7786
unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 :-1]
Definition miniz.c:33
int mz_inflateEnd(mz_streamp pStream)
Definition miniz.c:552
mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
Definition miniz.c:6039
static const mz_uint mz_bitmasks[17]
Definition miniz.c:1100
void * mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
Definition miniz.c:4709
int mz_deflate(mz_streamp pStream, int flush)
Definition miniz.c:243
mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
Definition miniz.c:4668
#define MZ_FILE_STAT_STRUCT
Definition miniz.c:3220
mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
Definition miniz.c:6883
mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
Definition miniz.c:4655
static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
Definition miniz.c:6202
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
Definition miniz.c:2967
static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
Definition miniz.c:4361
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
Definition miniz.c:2438
#define MZ_SWAP_UINT32(a, b)
Definition miniz.c:3558
tdefl_compressor * tdefl_compressor_alloc(void)
Definition miniz.c:2233
static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
Definition miniz.c:872
static const mz_uint8 s_tdefl_large_dist_sym[128]
Definition miniz.c:735
#define TDEFL_PROBE
#define MZ_FCLOSE
Definition miniz.c:3210
mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
Definition miniz.c:5575
mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
Definition miniz.c:5310
void * tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
Definition miniz.c:2223
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
Definition miniz.c:313
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
Definition miniz.c:2117
static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
Definition miniz.c:1246
static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
Definition miniz.c:5302
static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
Definition miniz.c:1725
#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index)
Definition miniz.c:3361
mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state *pState)
Definition miniz.c:5187
mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
Definition miniz.c:5279
mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
Definition miniz.c:4110
static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
Definition miniz.c:6099
mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)
Definition miniz.c:7452
unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 :-1]
Definition miniz.c:31
static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
Definition miniz.c:5675
mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
Definition miniz.c:5292
#define MZ_WRITE_LE64(p, v)
Definition miniz.c:5683
mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
Definition miniz.c:5769
tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
Definition miniz.c:1919
mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
Definition miniz.c:6033
@ TDEFL_MAX_SUPPORTED_HUFF_CODESIZE
Definition miniz.c:846
static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
Definition miniz.c:3376
mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
Definition miniz.c:7662
#define TINFL_SKIP_BITS(state_index, n)
Definition miniz.c:2335
mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
Definition miniz.c:6224
static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
Definition miniz.c:3406
#define TDEFL_RLE_PREV_CODE_SIZE()
Definition miniz.c:943
mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
Definition miniz.c:5823
mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
Definition miniz.c:5236
#define MZ_FTELL64
Definition miniz.c:3217
mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
Definition miniz.c:7808
static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
Definition miniz.c:1898
void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
Definition miniz.c:3015
#define TDEFL_PUT_BITS(b, l)
Definition miniz.c:925
#define MZ_DELETE_FILE
Definition miniz.c:3224
static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
Definition miniz.c:6872
static tdefl_sym_freq * tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1)
Definition miniz.c:754
unsigned long mz_ulong
Definition miniz.h:235
@ MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE
Definition miniz.h:991
@ MZ_ZIP_MAX_IO_BUF_SIZE
Definition miniz.h:989
@ MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE
Definition miniz.h:990
#define MZ_MALLOC(x)
Definition miniz.h:589
@ TINFL_FAST_LOOKUP_SIZE
Definition miniz.h:937
@ TINFL_FAST_LOOKUP_BITS
Definition miniz.h:936
@ MZ_ZIP_FLAG_ASCII_FILENAME
Definition miniz.h:1074
@ MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE
Definition miniz.h:1077
@ MZ_ZIP_FLAG_WRITE_ZIP64
Definition miniz.h:1072
@ MZ_ZIP_FLAG_WRITE_ALLOW_READING
Definition miniz.h:1073
@ MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY
Definition miniz.h:1071
@ MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG
Definition miniz.h:1070
@ MZ_ZIP_FLAG_COMPRESSED_DATA
Definition miniz.h:1068
@ MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY
Definition miniz.h:1069
@ MZ_ZIP_FLAG_CASE_SENSITIVE
Definition miniz.h:1066
@ MZ_ZIP_FLAG_IGNORE_PATH
Definition miniz.h:1067
@ TDEFL_MAX_HUFF_SYMBOLS
Definition miniz.h:738
@ TDEFL_LEVEL1_HASH_SIZE_MASK
Definition miniz.h:740
@ TDEFL_LZ_HASH_BITS
Definition miniz.h:739
@ TDEFL_LZ_HASH_SIZE
Definition miniz.h:742
@ TDEFL_LZ_CODE_BUF_SIZE
Definition miniz.h:736
@ TDEFL_LZ_HASH_SHIFT
Definition miniz.h:741
@ TDEFL_OUT_BUF_SIZE
Definition miniz.h:737
#define MZ_READ_LE16(p)
Definition miniz.h:604
#define MZ_REALLOC(p, x)
Definition miniz.h:591
@ TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
Definition miniz.h:844
@ TINFL_FLAG_HAS_MORE_INPUT
Definition miniz.h:843
@ TINFL_FLAG_COMPUTE_ADLER32
Definition miniz.h:845
@ TINFL_FLAG_PARSE_ZLIB_HEADER
Definition miniz.h:842
size_t(* mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
Definition miniz.h:1052
@ TDEFL_MAX_PROBES_MASK
Definition miniz.h:651
#define MZ_FALSE
Definition miniz.h:554
#define MZ_FORCEINLINE
Definition miniz.h:615
@ MZ_SYNC_FLUSH
Definition miniz.h:292
@ MZ_FINISH
Definition miniz.h:294
@ MZ_PARTIAL_FLUSH
Definition miniz.h:291
#define MZ_ASSERT(x)
Definition miniz.h:582
#define tinfl_init(r)
Definition miniz.h:917
tinfl_status
Definition miniz.h:883
@ TINFL_STATUS_ADLER32_MISMATCH
Definition miniz.h:893
@ TINFL_STATUS_FAILED
Definition miniz.h:896
@ TINFL_STATUS_NEEDS_MORE_INPUT
Definition miniz.h:907
@ TINFL_STATUS_HAS_MORE_OUTPUT
Definition miniz.h:913
@ TINFL_STATUS_BAD_PARAM
Definition miniz.h:890
@ TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS
Definition miniz.h:887
@ TINFL_STATUS_DONE
Definition miniz.h:902
#define TINFL_LZ_DICT_SIZE
Definition miniz.h:880
#define MZ_CLEAR_OBJ(obj)
Definition miniz.h:596
#define MZ_DEFLATED
Definition miniz.h:259
unsigned int mz_uint
Definition miniz.h:549
int64_t mz_int64
Definition miniz.h:550
#define MZ_ADLER32_INIT
Definition miniz.h:240
#define MZ_CRC32_INIT
Definition miniz.h:244
int(* tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser)
Definition miniz.h:865
#define MZ_UINT16_MAX
Definition miniz.h:626
#define tinfl_get_adler32(r)
Definition miniz.h:923
signed short mz_int16
Definition miniz.h:546
#define MZ_DEFAULT_WINDOW_BITS
Definition miniz.h:314
#define MZ_VERSION
Definition miniz.h:278
#define MZ_FILE
Definition miniz.h:568
@ MZ_MEM_ERROR
Definition miniz.h:307
@ MZ_PARAM_ERROR
Definition miniz.h:310
@ MZ_NEED_DICT
Definition miniz.h:303
@ MZ_VERSION_ERROR
Definition miniz.h:309
@ MZ_STREAM_END
Definition miniz.h:302
@ MZ_ERRNO
Definition miniz.h:304
@ MZ_OK
Definition miniz.h:301
@ MZ_BUF_ERROR
Definition miniz.h:308
@ MZ_STREAM_ERROR
Definition miniz.h:305
@ MZ_DATA_ERROR
Definition miniz.h:306
@ MZ_UBER_COMPRESSION
Definition miniz.h:273
@ MZ_DEFAULT_LEVEL
Definition miniz.h:274
@ MZ_DEFAULT_COMPRESSION
Definition miniz.h:275
@ TDEFL_FORCE_ALL_RAW_BLOCKS
Definition miniz.h:672
@ TDEFL_GREEDY_PARSING_FLAG
Definition miniz.h:667
@ TDEFL_FORCE_ALL_STATIC_BLOCKS
Definition miniz.h:671
@ TDEFL_COMPUTE_ADLER32
Definition miniz.h:666
@ TDEFL_FILTER_MATCHES
Definition miniz.h:670
@ TDEFL_WRITE_ZLIB_HEADER
Definition miniz.h:665
@ TDEFL_NONDETERMINISTIC_PARSING_FLAG
Definition miniz.h:668
@ TDEFL_RLE_MATCHES
Definition miniz.h:669
@ MZ_FILTERED
Definition miniz.h:252
@ MZ_FIXED
Definition miniz.h:255
@ MZ_DEFAULT_STRATEGY
Definition miniz.h:251
@ MZ_RLE
Definition miniz.h:254
@ MZ_HUFFMAN_ONLY
Definition miniz.h:253
size_t(* mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
Definition miniz.h:1051
#define MZ_TIME_T
Definition miniz.h:579
int mz_bool
Definition miniz.h:552
unsigned char mz_uint8
Definition miniz.h:545
tdefl_flush
Definition miniz.h:755
@ TDEFL_NO_FLUSH
Definition miniz.h:756
@ TDEFL_FULL_FLUSH
Definition miniz.h:758
@ TDEFL_FINISH
Definition miniz.h:759
mz_zip_type
Definition miniz.h:1080
@ MZ_ZIP_TYPE_USER
Definition miniz.h:1082
@ MZ_ZIP_TYPE_FILE
Definition miniz.h:1085
@ MZ_ZIP_TYPE_HEAP
Definition miniz.h:1084
@ MZ_ZIP_TYPE_MEMORY
Definition miniz.h:1083
@ MZ_ZIP_TYPE_CFILE
Definition miniz.h:1086
@ MZ_ZIP_TYPE_INVALID
Definition miniz.h:1081
#define crc32
Definition miniz.h:511
#define MZ_CLEAR_ARR(obj)
Definition miniz.h:597
unsigned int mz_uint32
Definition miniz.h:548
unsigned short mz_uint16
Definition miniz.h:547
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED
Definition miniz.h:860
#define MZ_MIN(a, b)
Definition miniz.h:595
tdefl_status
Definition miniz.h:747
@ TDEFL_STATUS_OKAY
Definition miniz.h:750
@ TDEFL_STATUS_DONE
Definition miniz.h:751
@ TDEFL_STATUS_BAD_PARAM
Definition miniz.h:748
@ TDEFL_STATUS_PUT_BUF_FAILED
Definition miniz.h:749
@ TDEFL_MAX_MATCH_LEN
Definition miniz.h:718
@ TDEFL_MAX_HUFF_SYMBOLS_0
Definition miniz.h:712
@ TDEFL_LZ_DICT_SIZE_MASK
Definition miniz.h:716
@ TDEFL_LZ_DICT_SIZE
Definition miniz.h:715
@ TDEFL_MIN_MATCH_LEN
Definition miniz.h:717
@ TDEFL_MAX_HUFF_SYMBOLS_1
Definition miniz.h:713
@ TDEFL_MAX_HUFF_SYMBOLS_2
Definition miniz.h:714
#define MZ_FREE(x)
Definition miniz.h:590
uint64_t mz_uint64
Definition miniz.h:551
#define MZ_READ_LE32(p)
Definition miniz.h:605
mz_zip_mode
Definition miniz.h:1058
@ MZ_ZIP_MODE_WRITING
Definition miniz.h:1061
@ MZ_ZIP_MODE_READING
Definition miniz.h:1060
@ MZ_ZIP_MODE_INVALID
Definition miniz.h:1059
@ MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED
Definition miniz.h:1062
mz_bool(* tdefl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser)
Definition miniz.h:704
#define MZ_CLEAR_PTR(obj)
Definition miniz.h:598
mz_zip_error
Definition miniz.h:1091
@ MZ_ZIP_UNSUPPORTED_METHOD
Definition miniz.h:1096
@ MZ_ZIP_UNSUPPORTED_FEATURE
Definition miniz.h:1098
@ MZ_ZIP_FILE_OPEN_FAILED
Definition miniz.h:1109
@ MZ_ZIP_FILE_TOO_LARGE
Definition miniz.h:1095
@ MZ_ZIP_WRITE_CALLBACK_FAILED
Definition miniz.h:1123
@ MZ_ZIP_CRC_CHECK_FAILED
Definition miniz.h:1106
@ MZ_ZIP_INTERNAL_ERROR
Definition miniz.h:1119
@ MZ_ZIP_FILE_CLOSE_FAILED
Definition miniz.h:1113
@ MZ_ZIP_FILE_CREATE_FAILED
Definition miniz.h:1110
@ MZ_ZIP_BUF_TOO_SMALL
Definition miniz.h:1118
@ MZ_ZIP_VALIDATION_FAILED
Definition miniz.h:1122
@ MZ_ZIP_FILE_STAT_FAILED
Definition miniz.h:1115
@ MZ_ZIP_INVALID_FILENAME
Definition miniz.h:1117
@ MZ_ZIP_COMPRESSION_FAILED
Definition miniz.h:1104
@ MZ_ZIP_NO_ERROR
Definition miniz.h:1092
@ MZ_ZIP_UNSUPPORTED_ENCRYPTION
Definition miniz.h:1097
@ MZ_ZIP_TOO_MANY_FILES
Definition miniz.h:1094
@ MZ_ZIP_UNDEFINED_ERROR
Definition miniz.h:1093
@ MZ_ZIP_UNSUPPORTED_MULTIDISK
Definition miniz.h:1102
@ MZ_ZIP_ALLOC_FAILED
Definition miniz.h:1108
@ MZ_ZIP_ARCHIVE_TOO_LARGE
Definition miniz.h:1121
@ MZ_ZIP_DECOMPRESSION_FAILED
Definition miniz.h:1103
@ MZ_ZIP_FILE_WRITE_FAILED
Definition miniz.h:1111
@ MZ_ZIP_INVALID_PARAMETER
Definition miniz.h:1116
@ MZ_ZIP_INVALID_HEADER_OR_CORRUPTED
Definition miniz.h:1101
@ MZ_ZIP_UNSUPPORTED_CDIR_SIZE
Definition miniz.h:1107
@ MZ_ZIP_FILE_READ_FAILED
Definition miniz.h:1112
@ MZ_ZIP_FILE_NOT_FOUND
Definition miniz.h:1120
@ MZ_ZIP_FAILED_FINDING_CENTRAL_DIR
Definition miniz.h:1099
@ MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE
Definition miniz.h:1105
@ MZ_ZIP_NOT_AN_ARCHIVE
Definition miniz.h:1100
@ MZ_ZIP_TOTAL_ERRORS
Definition miniz.h:1124
@ MZ_ZIP_FILE_SEEK_FAILED
Definition miniz.h:1114
#define MZ_READ_LE64(p)
Definition miniz.h:608
#define MZ_MAX(a, b)
Definition miniz.h:594
#define MZ_TRUE
Definition miniz.h:555
mz_uint32 tinfl_bit_buf_t
Definition miniz.h:950
#define MZ_UINT32_MAX
Definition miniz.h:627
int m_window_bits
Definition miniz.c:368
mz_uint m_dict_ofs
Definition miniz.c:367
mz_uint m_has_flushed
Definition miniz.c:367
mz_uint m_dict_avail
Definition miniz.c:367
mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]
Definition miniz.c:369
mz_uint m_first_call
Definition miniz.c:367
tinfl_status m_last_status
Definition miniz.c:370
tinfl_decompressor m_decomp
Definition miniz.c:366
mz_ulong adler
Definition miniz.h:337
unsigned char * next_out
Definition miniz.h:325
void * opaque
Definition miniz.h:334
int data_type
Definition miniz.h:336
mz_free_func zfree
Definition miniz.h:333
mz_ulong total_out
Definition miniz.h:327
unsigned int avail_out
Definition miniz.h:326
struct mz_internal_state * state
Definition miniz.h:330
const unsigned char * next_in
Definition miniz.h:321
unsigned int avail_in
Definition miniz.h:322
mz_alloc_func zalloc
Definition miniz.h:332
mz_ulong total_in
Definition miniz.h:323
char * msg
Definition miniz.h:329
mz_ulong reserved
Definition miniz.h:338
mz_uint32 m_external_attr
Definition miniz.h:1019
mz_uint16 m_version_needed
Definition miniz.h:1004
mz_uint16 m_version_made_by
Definition miniz.h:1003
mz_uint64 m_central_dir_ofs
Definition miniz.h:1000
mz_uint32 m_file_index
Definition miniz.h:997
mz_uint64 m_uncomp_size
Definition miniz.h:1015
mz_uint32 m_comment_size
Definition miniz.h:1025
mz_uint64 m_local_header_ofs
Definition miniz.h:1022
mz_uint16 m_internal_attr
Definition miniz.h:1018
char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]
Definition miniz.h:1038
char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]
Definition miniz.h:1042
mz_uint64 m_central_directory_file_ofs
Definition miniz.h:1130
mz_zip_error m_last_error
Definition miniz.h:1136
mz_alloc_func m_pAlloc
Definition miniz.h:1140
mz_zip_mode m_zip_mode
Definition miniz.h:1134
mz_uint64 m_archive_size
Definition miniz.h:1129
void * m_pIO_opaque
Definition miniz.h:1148
void * m_pAlloc_opaque
Definition miniz.h:1143
mz_file_needs_keepalive m_pNeeds_keepalive
Definition miniz.h:1147
mz_file_write_func m_pWrite
Definition miniz.h:1146
mz_zip_internal_state * m_pState
Definition miniz.h:1150
mz_free_func m_pFree
Definition miniz.h:1141
mz_realloc_func m_pRealloc
Definition miniz.h:1142
mz_file_read_func m_pRead
Definition miniz.h:1145
mz_uint64 m_file_offset_alignment
Definition miniz.h:1138
mz_zip_type m_zip_type
Definition miniz.h:1135
mz_uint32 m_total_files
Definition miniz.h:1133
size_t m_size
Definition miniz.c:3323
void * m_p
Definition miniz.c:3322
size_t m_capacity
Definition miniz.c:3323
mz_uint m_element_size
Definition miniz.c:3324
mz_bool m_zip64_has_extended_info_fields
Definition miniz.c:3340
mz_zip_array m_sorted_central_dir_offsets
Definition miniz.c:3331
mz_uint64 m_file_archive_start_ofs
Definition miniz.c:3344
mz_zip_array m_central_dir_offsets
Definition miniz.c:3330
mz_zip_array m_central_dir
Definition miniz.c:3329
tinfl_decompressor inflator
Definition miniz.h:1168
mz_zip_archive_file_stat file_stat
Definition miniz.h:1162
mz_uint64 m_cur_archive_file_ofs
Definition miniz.c:6047
mz_uint64 m_comp_size
Definition miniz.c:6048
mz_zip_archive * m_pZip
Definition miniz.c:6046
mz_uint m_max_probes[2]
Definition miniz.h:767
mz_uint m_block_index
Definition miniz.h:772
mz_uint m_saved_lit
Definition miniz.h:772
mz_uint m_saved_match_dist
Definition miniz.h:772
size_t * m_pOut_buf_size
Definition miniz.h:776
mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]
Definition miniz.h:786
const mz_uint8 * m_pSrc
Definition miniz.h:778
mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]
Definition miniz.h:782
mz_uint m_output_flush_remaining
Definition miniz.h:772
mz_uint m_num_flags_left
Definition miniz.h:771
mz_uint m_lookahead_pos
Definition miniz.h:769
mz_uint m_wants_to_finish
Definition miniz.h:772
mz_uint m_finished
Definition miniz.h:772
mz_uint m_total_lz_bytes
Definition miniz.h:771
size_t m_src_buf_left
Definition miniz.h:779
tdefl_status m_prev_return_status
Definition miniz.h:773
mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE+TDEFL_MAX_MATCH_LEN - 1]
Definition miniz.h:780
tdefl_put_buf_func_ptr m_pPut_buf_func
Definition miniz.h:765
tdefl_flush m_flush
Definition miniz.h:777
mz_uint m_output_flush_ofs
Definition miniz.h:772
size_t m_out_buf_ofs
Definition miniz.h:779
mz_uint m_bit_buffer
Definition miniz.h:771
mz_uint m_bits_in
Definition miniz.h:771
mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]
Definition miniz.h:785
mz_uint8 * m_pOutput_buf_end
Definition miniz.h:770
mz_uint m_lookahead_size
Definition miniz.h:769
mz_uint8 * m_pLZ_flags
Definition miniz.h:770
mz_uint m_saved_match_len
Definition miniz.h:772
mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]
Definition miniz.h:781
void * m_pOut_buf
Definition miniz.h:775
mz_uint m_lz_code_buf_dict_pos
Definition miniz.h:771
const void * m_pIn_buf
Definition miniz.h:774
mz_uint m_flags
Definition miniz.h:767
mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]
Definition miniz.h:784
int m_greedy_parsing
Definition miniz.h:768
void * m_pPut_buf_user
Definition miniz.h:766
mz_uint8 * m_pLZ_code_buf
Definition miniz.h:770
mz_uint m_dict_size
Definition miniz.h:769
mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]
Definition miniz.h:783
size_t * m_pIn_buf_size
Definition miniz.h:776
mz_uint m_adler32
Definition miniz.h:769
mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]
Definition miniz.h:787
mz_uint8 * m_pOutput_buf
Definition miniz.h:770
mz_bool m_expandable
Definition miniz.c:2058
mz_uint8 * m_pBuf
Definition miniz.c:2057
mz_uint16 m_sym_index
Definition miniz.c:752
mz_uint16 m_key
Definition miniz.c:752
mz_uint8 m_code_size_0[TINFL_MAX_HUFF_SYMBOLS_0]
Definition miniz.h:963
mz_uint32 m_final
Definition miniz.h:956
mz_uint32 m_zhdr0
Definition miniz.h:956
tinfl_bit_buf_t m_bit_buf
Definition miniz.h:957
mz_uint32 m_counter
Definition miniz.h:956
size_t m_dist_from_out_buf_start
Definition miniz.h:958
mz_uint32 m_check_adler32
Definition miniz.h:956
mz_int16 m_tree_0[TINFL_MAX_HUFF_SYMBOLS_0 *2]
Definition miniz.h:960
mz_int16 m_tree_1[TINFL_MAX_HUFF_SYMBOLS_1 *2]
Definition miniz.h:961
mz_uint8 m_raw_header[4]
Definition miniz.h:966
mz_uint32 m_zhdr1
Definition miniz.h:956
mz_uint32 m_num_bits
Definition miniz.h:956
mz_int16 m_look_up[TINFL_MAX_HUFF_TABLES][TINFL_FAST_LOOKUP_SIZE]
Definition miniz.h:959
mz_int16 m_tree_2[TINFL_MAX_HUFF_SYMBOLS_2 *2]
Definition miniz.h:962
mz_uint32 m_z_adler32
Definition miniz.h:956
mz_uint32 m_table_sizes[TINFL_MAX_HUFF_TABLES]
Definition miniz.h:956
mz_uint8 m_code_size_2[TINFL_MAX_HUFF_SYMBOLS_2]
Definition miniz.h:965
mz_uint8 m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0+TINFL_MAX_HUFF_SYMBOLS_1+137]
Definition miniz.h:966
mz_uint32 m_num_extra
Definition miniz.h:956
mz_uint8 m_code_size_1[TINFL_MAX_HUFF_SYMBOLS_1]
Definition miniz.h:964