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