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