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