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