File Coverage

miniz.c
Criterion Covered Total %
statement 530 3140 16.8
branch 388 3378 11.4
condition n/a
subroutine n/a
pod n/a
total 918 6518 14.0


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