File Coverage

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