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