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