xref: /aosp_15_r20/external/pytorch/third_party/miniz-2.1.0/miniz.c (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1*da0073e9SAndroid Build Coastguard Worker /**************************************************************************
2*da0073e9SAndroid Build Coastguard Worker  *
3*da0073e9SAndroid Build Coastguard Worker  * Copyright 2013-2014 RAD Game Tools and Valve Software
4*da0073e9SAndroid Build Coastguard Worker  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5*da0073e9SAndroid Build Coastguard Worker  * All Rights Reserved.
6*da0073e9SAndroid Build Coastguard Worker  *
7*da0073e9SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
8*da0073e9SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
9*da0073e9SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
10*da0073e9SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11*da0073e9SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
12*da0073e9SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
13*da0073e9SAndroid Build Coastguard Worker  *
14*da0073e9SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
15*da0073e9SAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
16*da0073e9SAndroid Build Coastguard Worker  *
17*da0073e9SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*da0073e9SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*da0073e9SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20*da0073e9SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*da0073e9SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*da0073e9SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23*da0073e9SAndroid Build Coastguard Worker  * THE SOFTWARE.
24*da0073e9SAndroid Build Coastguard Worker  *
25*da0073e9SAndroid Build Coastguard Worker  **************************************************************************/
26*da0073e9SAndroid Build Coastguard Worker 
27*da0073e9SAndroid Build Coastguard Worker #include  "miniz.h"
28*da0073e9SAndroid Build Coastguard Worker 
29*da0073e9SAndroid Build Coastguard Worker typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
30*da0073e9SAndroid Build Coastguard Worker typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
31*da0073e9SAndroid Build Coastguard Worker typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
32*da0073e9SAndroid Build Coastguard Worker 
33*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
34*da0073e9SAndroid Build Coastguard Worker extern "C" {
35*da0073e9SAndroid Build Coastguard Worker #endif
36*da0073e9SAndroid Build Coastguard Worker 
37*da0073e9SAndroid Build Coastguard Worker /* ------------------- zlib-style API's */
38*da0073e9SAndroid Build Coastguard Worker 
mz_adler32(mz_ulong adler,const unsigned char * ptr,size_t buf_len)39*da0073e9SAndroid Build Coastguard Worker mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
40*da0073e9SAndroid Build Coastguard Worker {
41*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,cppcoreguidelines-init-variables)
42*da0073e9SAndroid Build Coastguard Worker     mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
43*da0073e9SAndroid Build Coastguard Worker     size_t block_len = buf_len % 5552;
44*da0073e9SAndroid Build Coastguard Worker     if (!ptr)
45*da0073e9SAndroid Build Coastguard Worker         return MZ_ADLER32_INIT;
46*da0073e9SAndroid Build Coastguard Worker     while (buf_len)
47*da0073e9SAndroid Build Coastguard Worker     {
48*da0073e9SAndroid Build Coastguard Worker         for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
49*da0073e9SAndroid Build Coastguard Worker         {
50*da0073e9SAndroid Build Coastguard Worker             s1 += ptr[0], s2 += s1;
51*da0073e9SAndroid Build Coastguard Worker             s1 += ptr[1], s2 += s1;
52*da0073e9SAndroid Build Coastguard Worker             s1 += ptr[2], s2 += s1;
53*da0073e9SAndroid Build Coastguard Worker             s1 += ptr[3], s2 += s1;
54*da0073e9SAndroid Build Coastguard Worker             s1 += ptr[4], s2 += s1;
55*da0073e9SAndroid Build Coastguard Worker             s1 += ptr[5], s2 += s1;
56*da0073e9SAndroid Build Coastguard Worker             s1 += ptr[6], s2 += s1;
57*da0073e9SAndroid Build Coastguard Worker             s1 += ptr[7], s2 += s1;
58*da0073e9SAndroid Build Coastguard Worker         }
59*da0073e9SAndroid Build Coastguard Worker         for (; i < block_len; ++i)
60*da0073e9SAndroid Build Coastguard Worker             s1 += *ptr++, s2 += s1;
61*da0073e9SAndroid Build Coastguard Worker         s1 %= 65521U, s2 %= 65521U;
62*da0073e9SAndroid Build Coastguard Worker         buf_len -= block_len;
63*da0073e9SAndroid Build Coastguard Worker         block_len = 5552;
64*da0073e9SAndroid Build Coastguard Worker     }
65*da0073e9SAndroid Build Coastguard Worker     return (s2 << 16) + s1;
66*da0073e9SAndroid Build Coastguard Worker }
67*da0073e9SAndroid Build Coastguard Worker 
68*da0073e9SAndroid Build Coastguard Worker /* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */
69*da0073e9SAndroid Build Coastguard Worker #if 0
70*da0073e9SAndroid Build Coastguard Worker     mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
71*da0073e9SAndroid Build Coastguard Worker     {
72*da0073e9SAndroid Build Coastguard Worker         static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
73*da0073e9SAndroid Build Coastguard Worker                                                0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
74*da0073e9SAndroid Build Coastguard Worker         mz_uint32 crcu32 = (mz_uint32)crc;
75*da0073e9SAndroid Build Coastguard Worker         if (!ptr)
76*da0073e9SAndroid Build Coastguard Worker             return MZ_CRC32_INIT;
77*da0073e9SAndroid Build Coastguard Worker         crcu32 = ~crcu32;
78*da0073e9SAndroid Build Coastguard Worker         while (buf_len--)
79*da0073e9SAndroid Build Coastguard Worker         {
80*da0073e9SAndroid Build Coastguard Worker             mz_uint8 b = *ptr++;
81*da0073e9SAndroid Build Coastguard Worker             crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
82*da0073e9SAndroid Build Coastguard Worker             crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
83*da0073e9SAndroid Build Coastguard Worker         }
84*da0073e9SAndroid Build Coastguard Worker         return ~crcu32;
85*da0073e9SAndroid Build Coastguard Worker     }
86*da0073e9SAndroid Build Coastguard Worker #elif defined(USE_EXTERNAL_MZCRC)
87*da0073e9SAndroid Build Coastguard Worker /* If USE_EXTERNAL_CRC is defined, an external module will export the
88*da0073e9SAndroid Build Coastguard Worker  * mz_crc32() symbol for us to use, e.g. an SSE-accelerated version.
89*da0073e9SAndroid Build Coastguard Worker  * Depending on the impl, it may be necessary to ~ the input/output crc values.
90*da0073e9SAndroid Build Coastguard Worker  */
91*da0073e9SAndroid Build Coastguard Worker mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len);
92*da0073e9SAndroid Build Coastguard Worker #else
93*da0073e9SAndroid Build Coastguard Worker /* Faster, but larger CPU cache footprint.
94*da0073e9SAndroid Build Coastguard Worker  */
mz_crc32(mz_ulong crc,const mz_uint8 * ptr,size_t buf_len)95*da0073e9SAndroid Build Coastguard Worker mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
96*da0073e9SAndroid Build Coastguard Worker {
97*da0073e9SAndroid Build Coastguard Worker     static const mz_uint32 s_crc_table[256] =
98*da0073e9SAndroid Build Coastguard Worker         {
99*da0073e9SAndroid Build Coastguard Worker           0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
100*da0073e9SAndroid Build Coastguard Worker           0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
101*da0073e9SAndroid Build Coastguard Worker           0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
102*da0073e9SAndroid Build Coastguard Worker           0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
103*da0073e9SAndroid Build Coastguard Worker           0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
104*da0073e9SAndroid Build Coastguard Worker           0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
105*da0073e9SAndroid Build Coastguard Worker           0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
106*da0073e9SAndroid Build Coastguard Worker           0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
107*da0073e9SAndroid Build Coastguard Worker           0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
108*da0073e9SAndroid Build Coastguard Worker           0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
109*da0073e9SAndroid Build Coastguard Worker           0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
110*da0073e9SAndroid Build Coastguard Worker           0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
111*da0073e9SAndroid Build Coastguard Worker           0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
112*da0073e9SAndroid Build Coastguard Worker           0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
113*da0073e9SAndroid Build Coastguard Worker           0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
114*da0073e9SAndroid Build Coastguard Worker           0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
115*da0073e9SAndroid Build Coastguard Worker           0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
116*da0073e9SAndroid Build Coastguard Worker           0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
117*da0073e9SAndroid Build Coastguard Worker           0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
118*da0073e9SAndroid Build Coastguard Worker           0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
119*da0073e9SAndroid Build Coastguard Worker           0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
120*da0073e9SAndroid Build Coastguard Worker           0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
121*da0073e9SAndroid Build Coastguard Worker           0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
122*da0073e9SAndroid Build Coastguard Worker           0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
123*da0073e9SAndroid Build Coastguard Worker           0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
124*da0073e9SAndroid Build Coastguard Worker           0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
125*da0073e9SAndroid Build Coastguard Worker           0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
126*da0073e9SAndroid Build Coastguard Worker           0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
127*da0073e9SAndroid Build Coastguard Worker           0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
128*da0073e9SAndroid Build Coastguard Worker           0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
129*da0073e9SAndroid Build Coastguard Worker           0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
130*da0073e9SAndroid Build Coastguard Worker           0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
131*da0073e9SAndroid Build Coastguard Worker           0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
132*da0073e9SAndroid Build Coastguard Worker           0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
133*da0073e9SAndroid Build Coastguard Worker           0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
134*da0073e9SAndroid Build Coastguard Worker           0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
135*da0073e9SAndroid Build Coastguard Worker           0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
136*da0073e9SAndroid Build Coastguard Worker         };
137*da0073e9SAndroid Build Coastguard Worker 
138*da0073e9SAndroid Build Coastguard Worker     mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
139*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
140*da0073e9SAndroid Build Coastguard Worker 
141*da0073e9SAndroid Build Coastguard Worker     while (buf_len >= 4)
142*da0073e9SAndroid Build Coastguard Worker     {
143*da0073e9SAndroid Build Coastguard Worker         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
144*da0073e9SAndroid Build Coastguard Worker         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
145*da0073e9SAndroid Build Coastguard Worker         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
146*da0073e9SAndroid Build Coastguard Worker         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
147*da0073e9SAndroid Build Coastguard Worker         pByte_buf += 4;
148*da0073e9SAndroid Build Coastguard Worker         buf_len -= 4;
149*da0073e9SAndroid Build Coastguard Worker     }
150*da0073e9SAndroid Build Coastguard Worker 
151*da0073e9SAndroid Build Coastguard Worker     while (buf_len)
152*da0073e9SAndroid Build Coastguard Worker     {
153*da0073e9SAndroid Build Coastguard Worker         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
154*da0073e9SAndroid Build Coastguard Worker         ++pByte_buf;
155*da0073e9SAndroid Build Coastguard Worker         --buf_len;
156*da0073e9SAndroid Build Coastguard Worker     }
157*da0073e9SAndroid Build Coastguard Worker 
158*da0073e9SAndroid Build Coastguard Worker     return ~crc32;
159*da0073e9SAndroid Build Coastguard Worker }
160*da0073e9SAndroid Build Coastguard Worker #endif
161*da0073e9SAndroid Build Coastguard Worker 
mz_free(void * p)162*da0073e9SAndroid Build Coastguard Worker void mz_free(void *p)
163*da0073e9SAndroid Build Coastguard Worker {
164*da0073e9SAndroid Build Coastguard Worker     MZ_FREE(p);
165*da0073e9SAndroid Build Coastguard Worker }
166*da0073e9SAndroid Build Coastguard Worker 
miniz_def_alloc_func(void * opaque,size_t items,size_t size)167*da0073e9SAndroid Build Coastguard Worker void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
168*da0073e9SAndroid Build Coastguard Worker {
169*da0073e9SAndroid Build Coastguard Worker     (void)opaque, (void)items, (void)size;
170*da0073e9SAndroid Build Coastguard Worker     return MZ_MALLOC(items * size);
171*da0073e9SAndroid Build Coastguard Worker }
miniz_def_free_func(void * opaque,void * address)172*da0073e9SAndroid Build Coastguard Worker void miniz_def_free_func(void *opaque, void *address)
173*da0073e9SAndroid Build Coastguard Worker {
174*da0073e9SAndroid Build Coastguard Worker     (void)opaque, (void)address;
175*da0073e9SAndroid Build Coastguard Worker     MZ_FREE(address);
176*da0073e9SAndroid Build Coastguard Worker }
miniz_def_realloc_func(void * opaque,void * address,size_t items,size_t size)177*da0073e9SAndroid Build Coastguard Worker void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
178*da0073e9SAndroid Build Coastguard Worker {
179*da0073e9SAndroid Build Coastguard Worker     (void)opaque, (void)address, (void)items, (void)size;
180*da0073e9SAndroid Build Coastguard Worker     return MZ_REALLOC(address, items * size);
181*da0073e9SAndroid Build Coastguard Worker }
182*da0073e9SAndroid Build Coastguard Worker 
mz_version(void)183*da0073e9SAndroid Build Coastguard Worker const char *mz_version(void)
184*da0073e9SAndroid Build Coastguard Worker {
185*da0073e9SAndroid Build Coastguard Worker     return MZ_VERSION;
186*da0073e9SAndroid Build Coastguard Worker }
187*da0073e9SAndroid Build Coastguard Worker 
188*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_ZLIB_APIS
189*da0073e9SAndroid Build Coastguard Worker 
mz_deflateInit(mz_streamp pStream,int level)190*da0073e9SAndroid Build Coastguard Worker int mz_deflateInit(mz_streamp pStream, int level)
191*da0073e9SAndroid Build Coastguard Worker {
192*da0073e9SAndroid Build Coastguard Worker     return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
193*da0073e9SAndroid Build Coastguard Worker }
194*da0073e9SAndroid Build Coastguard Worker 
mz_deflateInit2(mz_streamp pStream,int level,int method,int window_bits,int mem_level,int strategy)195*da0073e9SAndroid Build Coastguard Worker int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
196*da0073e9SAndroid Build Coastguard Worker {
197*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
198*da0073e9SAndroid Build Coastguard Worker     tdefl_compressor *pComp;
199*da0073e9SAndroid Build Coastguard Worker     mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
200*da0073e9SAndroid Build Coastguard Worker 
201*da0073e9SAndroid Build Coastguard Worker     if (!pStream)
202*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
203*da0073e9SAndroid Build Coastguard Worker     if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
204*da0073e9SAndroid Build Coastguard Worker         return MZ_PARAM_ERROR;
205*da0073e9SAndroid Build Coastguard Worker 
206*da0073e9SAndroid Build Coastguard Worker     pStream->data_type = 0;
207*da0073e9SAndroid Build Coastguard Worker     pStream->adler = MZ_ADLER32_INIT;
208*da0073e9SAndroid Build Coastguard Worker     pStream->msg = NULL;
209*da0073e9SAndroid Build Coastguard Worker     pStream->reserved = 0;
210*da0073e9SAndroid Build Coastguard Worker     pStream->total_in = 0;
211*da0073e9SAndroid Build Coastguard Worker     pStream->total_out = 0;
212*da0073e9SAndroid Build Coastguard Worker     if (!pStream->zalloc)
213*da0073e9SAndroid Build Coastguard Worker         pStream->zalloc = miniz_def_alloc_func;
214*da0073e9SAndroid Build Coastguard Worker     if (!pStream->zfree)
215*da0073e9SAndroid Build Coastguard Worker         pStream->zfree = miniz_def_free_func;
216*da0073e9SAndroid Build Coastguard Worker 
217*da0073e9SAndroid Build Coastguard Worker     pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
218*da0073e9SAndroid Build Coastguard Worker     if (!pComp)
219*da0073e9SAndroid Build Coastguard Worker         return MZ_MEM_ERROR;
220*da0073e9SAndroid Build Coastguard Worker 
221*da0073e9SAndroid Build Coastguard Worker     pStream->state = (struct mz_internal_state *)pComp;
222*da0073e9SAndroid Build Coastguard Worker 
223*da0073e9SAndroid Build Coastguard Worker     if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
224*da0073e9SAndroid Build Coastguard Worker     {
225*da0073e9SAndroid Build Coastguard Worker         mz_deflateEnd(pStream);
226*da0073e9SAndroid Build Coastguard Worker         return MZ_PARAM_ERROR;
227*da0073e9SAndroid Build Coastguard Worker     }
228*da0073e9SAndroid Build Coastguard Worker 
229*da0073e9SAndroid Build Coastguard Worker     return MZ_OK;
230*da0073e9SAndroid Build Coastguard Worker }
231*da0073e9SAndroid Build Coastguard Worker 
mz_deflateReset(mz_streamp pStream)232*da0073e9SAndroid Build Coastguard Worker int mz_deflateReset(mz_streamp pStream)
233*da0073e9SAndroid Build Coastguard Worker {
234*da0073e9SAndroid Build Coastguard Worker     if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
235*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
236*da0073e9SAndroid Build Coastguard Worker     pStream->total_in = pStream->total_out = 0;
237*da0073e9SAndroid Build Coastguard Worker     tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
238*da0073e9SAndroid Build Coastguard Worker     return MZ_OK;
239*da0073e9SAndroid Build Coastguard Worker }
240*da0073e9SAndroid Build Coastguard Worker 
mz_deflate(mz_streamp pStream,int flush)241*da0073e9SAndroid Build Coastguard Worker int mz_deflate(mz_streamp pStream, int flush)
242*da0073e9SAndroid Build Coastguard Worker {
243*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
244*da0073e9SAndroid Build Coastguard Worker     size_t in_bytes, out_bytes;
245*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
246*da0073e9SAndroid Build Coastguard Worker     mz_ulong orig_total_in, orig_total_out;
247*da0073e9SAndroid Build Coastguard Worker     int mz_status = MZ_OK;
248*da0073e9SAndroid Build Coastguard Worker 
249*da0073e9SAndroid Build Coastguard Worker     if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
250*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
251*da0073e9SAndroid Build Coastguard Worker     if (!pStream->avail_out)
252*da0073e9SAndroid Build Coastguard Worker         return MZ_BUF_ERROR;
253*da0073e9SAndroid Build Coastguard Worker 
254*da0073e9SAndroid Build Coastguard Worker     if (flush == MZ_PARTIAL_FLUSH)
255*da0073e9SAndroid Build Coastguard Worker         flush = MZ_SYNC_FLUSH;
256*da0073e9SAndroid Build Coastguard Worker 
257*da0073e9SAndroid Build Coastguard Worker     if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
258*da0073e9SAndroid Build Coastguard Worker         return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
259*da0073e9SAndroid Build Coastguard Worker 
260*da0073e9SAndroid Build Coastguard Worker     orig_total_in = pStream->total_in;
261*da0073e9SAndroid Build Coastguard Worker     orig_total_out = pStream->total_out;
262*da0073e9SAndroid Build Coastguard Worker     for (;;)
263*da0073e9SAndroid Build Coastguard Worker     {
264*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
265*da0073e9SAndroid Build Coastguard Worker         tdefl_status defl_status;
266*da0073e9SAndroid Build Coastguard Worker         in_bytes = pStream->avail_in;
267*da0073e9SAndroid Build Coastguard Worker         out_bytes = pStream->avail_out;
268*da0073e9SAndroid Build Coastguard Worker 
269*da0073e9SAndroid Build Coastguard Worker         defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
270*da0073e9SAndroid Build Coastguard Worker         pStream->next_in += (mz_uint)in_bytes;
271*da0073e9SAndroid Build Coastguard Worker         pStream->avail_in -= (mz_uint)in_bytes;
272*da0073e9SAndroid Build Coastguard Worker         pStream->total_in += (mz_uint)in_bytes;
273*da0073e9SAndroid Build Coastguard Worker         pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
274*da0073e9SAndroid Build Coastguard Worker 
275*da0073e9SAndroid Build Coastguard Worker         pStream->next_out += (mz_uint)out_bytes;
276*da0073e9SAndroid Build Coastguard Worker         pStream->avail_out -= (mz_uint)out_bytes;
277*da0073e9SAndroid Build Coastguard Worker         pStream->total_out += (mz_uint)out_bytes;
278*da0073e9SAndroid Build Coastguard Worker 
279*da0073e9SAndroid Build Coastguard Worker         if (defl_status < 0)
280*da0073e9SAndroid Build Coastguard Worker         {
281*da0073e9SAndroid Build Coastguard Worker             mz_status = MZ_STREAM_ERROR;
282*da0073e9SAndroid Build Coastguard Worker             break;
283*da0073e9SAndroid Build Coastguard Worker         }
284*da0073e9SAndroid Build Coastguard Worker         else if (defl_status == TDEFL_STATUS_DONE)
285*da0073e9SAndroid Build Coastguard Worker         {
286*da0073e9SAndroid Build Coastguard Worker             mz_status = MZ_STREAM_END;
287*da0073e9SAndroid Build Coastguard Worker             break;
288*da0073e9SAndroid Build Coastguard Worker         }
289*da0073e9SAndroid Build Coastguard Worker         else if (!pStream->avail_out)
290*da0073e9SAndroid Build Coastguard Worker             break;
291*da0073e9SAndroid Build Coastguard Worker         else if ((!pStream->avail_in) && (flush != MZ_FINISH))
292*da0073e9SAndroid Build Coastguard Worker         {
293*da0073e9SAndroid Build Coastguard Worker             if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
294*da0073e9SAndroid Build Coastguard Worker                 break;
295*da0073e9SAndroid Build Coastguard Worker             return MZ_BUF_ERROR; /* Can't make forward progress without some input.
296*da0073e9SAndroid Build Coastguard Worker  */
297*da0073e9SAndroid Build Coastguard Worker         }
298*da0073e9SAndroid Build Coastguard Worker     }
299*da0073e9SAndroid Build Coastguard Worker     return mz_status;
300*da0073e9SAndroid Build Coastguard Worker }
301*da0073e9SAndroid Build Coastguard Worker 
mz_deflateEnd(mz_streamp pStream)302*da0073e9SAndroid Build Coastguard Worker int mz_deflateEnd(mz_streamp pStream)
303*da0073e9SAndroid Build Coastguard Worker {
304*da0073e9SAndroid Build Coastguard Worker     if (!pStream)
305*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
306*da0073e9SAndroid Build Coastguard Worker     if (pStream->state)
307*da0073e9SAndroid Build Coastguard Worker     {
308*da0073e9SAndroid Build Coastguard Worker         pStream->zfree(pStream->opaque, pStream->state);
309*da0073e9SAndroid Build Coastguard Worker         pStream->state = NULL;
310*da0073e9SAndroid Build Coastguard Worker     }
311*da0073e9SAndroid Build Coastguard Worker     return MZ_OK;
312*da0073e9SAndroid Build Coastguard Worker }
313*da0073e9SAndroid Build Coastguard Worker 
mz_deflateBound(mz_streamp pStream,mz_ulong source_len)314*da0073e9SAndroid Build Coastguard Worker mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
315*da0073e9SAndroid Build Coastguard Worker {
316*da0073e9SAndroid Build Coastguard Worker     (void)pStream;
317*da0073e9SAndroid Build Coastguard Worker     /* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */
318*da0073e9SAndroid Build Coastguard Worker     return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
319*da0073e9SAndroid Build Coastguard Worker }
320*da0073e9SAndroid Build Coastguard Worker 
mz_compress2(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len,int level)321*da0073e9SAndroid Build Coastguard Worker int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
322*da0073e9SAndroid Build Coastguard Worker {
323*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
324*da0073e9SAndroid Build Coastguard Worker     int status;
325*da0073e9SAndroid Build Coastguard Worker     mz_stream stream;
326*da0073e9SAndroid Build Coastguard Worker     memset(&stream, 0, sizeof(stream));
327*da0073e9SAndroid Build Coastguard Worker 
328*da0073e9SAndroid Build Coastguard Worker     /* In case mz_ulong is 64-bits (argh I hate longs). */
329*da0073e9SAndroid Build Coastguard Worker     if ((source_len | *pDest_len) > 0xFFFFFFFFU)
330*da0073e9SAndroid Build Coastguard Worker         return MZ_PARAM_ERROR;
331*da0073e9SAndroid Build Coastguard Worker 
332*da0073e9SAndroid Build Coastguard Worker     stream.next_in = pSource;
333*da0073e9SAndroid Build Coastguard Worker     stream.avail_in = (mz_uint32)source_len;
334*da0073e9SAndroid Build Coastguard Worker     stream.next_out = pDest;
335*da0073e9SAndroid Build Coastguard Worker     stream.avail_out = (mz_uint32)*pDest_len;
336*da0073e9SAndroid Build Coastguard Worker 
337*da0073e9SAndroid Build Coastguard Worker     status = mz_deflateInit(&stream, level);
338*da0073e9SAndroid Build Coastguard Worker     if (status != MZ_OK)
339*da0073e9SAndroid Build Coastguard Worker         return status;
340*da0073e9SAndroid Build Coastguard Worker 
341*da0073e9SAndroid Build Coastguard Worker     status = mz_deflate(&stream, MZ_FINISH);
342*da0073e9SAndroid Build Coastguard Worker     if (status != MZ_STREAM_END)
343*da0073e9SAndroid Build Coastguard Worker     {
344*da0073e9SAndroid Build Coastguard Worker         mz_deflateEnd(&stream);
345*da0073e9SAndroid Build Coastguard Worker         return (status == MZ_OK) ? MZ_BUF_ERROR : status;
346*da0073e9SAndroid Build Coastguard Worker     }
347*da0073e9SAndroid Build Coastguard Worker 
348*da0073e9SAndroid Build Coastguard Worker     *pDest_len = stream.total_out;
349*da0073e9SAndroid Build Coastguard Worker     return mz_deflateEnd(&stream);
350*da0073e9SAndroid Build Coastguard Worker }
351*da0073e9SAndroid Build Coastguard Worker 
mz_compress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)352*da0073e9SAndroid Build Coastguard Worker int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
353*da0073e9SAndroid Build Coastguard Worker {
354*da0073e9SAndroid Build Coastguard Worker     return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
355*da0073e9SAndroid Build Coastguard Worker }
356*da0073e9SAndroid Build Coastguard Worker 
mz_compressBound(mz_ulong source_len)357*da0073e9SAndroid Build Coastguard Worker mz_ulong mz_compressBound(mz_ulong source_len)
358*da0073e9SAndroid Build Coastguard Worker {
359*da0073e9SAndroid Build Coastguard Worker     return mz_deflateBound(NULL, source_len);
360*da0073e9SAndroid Build Coastguard Worker }
361*da0073e9SAndroid Build Coastguard Worker 
362*da0073e9SAndroid Build Coastguard Worker typedef struct
363*da0073e9SAndroid Build Coastguard Worker {
364*da0073e9SAndroid Build Coastguard Worker     tinfl_decompressor m_decomp;
365*da0073e9SAndroid Build Coastguard Worker     mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
366*da0073e9SAndroid Build Coastguard Worker     int m_window_bits;
367*da0073e9SAndroid Build Coastguard Worker     mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
368*da0073e9SAndroid Build Coastguard Worker     tinfl_status m_last_status;
369*da0073e9SAndroid Build Coastguard Worker } inflate_state;
370*da0073e9SAndroid Build Coastguard Worker 
mz_inflateInit2(mz_streamp pStream,int window_bits)371*da0073e9SAndroid Build Coastguard Worker int mz_inflateInit2(mz_streamp pStream, int window_bits)
372*da0073e9SAndroid Build Coastguard Worker {
373*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
374*da0073e9SAndroid Build Coastguard Worker     inflate_state *pDecomp;
375*da0073e9SAndroid Build Coastguard Worker     if (!pStream)
376*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
377*da0073e9SAndroid Build Coastguard Worker     if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
378*da0073e9SAndroid Build Coastguard Worker         return MZ_PARAM_ERROR;
379*da0073e9SAndroid Build Coastguard Worker 
380*da0073e9SAndroid Build Coastguard Worker     pStream->data_type = 0;
381*da0073e9SAndroid Build Coastguard Worker     pStream->adler = 0;
382*da0073e9SAndroid Build Coastguard Worker     pStream->msg = NULL;
383*da0073e9SAndroid Build Coastguard Worker     pStream->total_in = 0;
384*da0073e9SAndroid Build Coastguard Worker     pStream->total_out = 0;
385*da0073e9SAndroid Build Coastguard Worker     pStream->reserved = 0;
386*da0073e9SAndroid Build Coastguard Worker     if (!pStream->zalloc)
387*da0073e9SAndroid Build Coastguard Worker         pStream->zalloc = miniz_def_alloc_func;
388*da0073e9SAndroid Build Coastguard Worker     if (!pStream->zfree)
389*da0073e9SAndroid Build Coastguard Worker         pStream->zfree = miniz_def_free_func;
390*da0073e9SAndroid Build Coastguard Worker 
391*da0073e9SAndroid Build Coastguard Worker     pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
392*da0073e9SAndroid Build Coastguard Worker     if (!pDecomp)
393*da0073e9SAndroid Build Coastguard Worker         return MZ_MEM_ERROR;
394*da0073e9SAndroid Build Coastguard Worker 
395*da0073e9SAndroid Build Coastguard Worker     pStream->state = (struct mz_internal_state *)pDecomp;
396*da0073e9SAndroid Build Coastguard Worker 
397*da0073e9SAndroid Build Coastguard Worker     tinfl_init(&pDecomp->m_decomp);
398*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_dict_ofs = 0;
399*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_dict_avail = 0;
400*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
401*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_first_call = 1;
402*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_has_flushed = 0;
403*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_window_bits = window_bits;
404*da0073e9SAndroid Build Coastguard Worker 
405*da0073e9SAndroid Build Coastguard Worker     return MZ_OK;
406*da0073e9SAndroid Build Coastguard Worker }
407*da0073e9SAndroid Build Coastguard Worker 
mz_inflateInit(mz_streamp pStream)408*da0073e9SAndroid Build Coastguard Worker int mz_inflateInit(mz_streamp pStream)
409*da0073e9SAndroid Build Coastguard Worker {
410*da0073e9SAndroid Build Coastguard Worker     return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
411*da0073e9SAndroid Build Coastguard Worker }
412*da0073e9SAndroid Build Coastguard Worker 
mz_inflateReset(mz_streamp pStream)413*da0073e9SAndroid Build Coastguard Worker int mz_inflateReset(mz_streamp pStream)
414*da0073e9SAndroid Build Coastguard Worker {
415*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
416*da0073e9SAndroid Build Coastguard Worker     inflate_state *pDecomp;
417*da0073e9SAndroid Build Coastguard Worker     if (!pStream)
418*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
419*da0073e9SAndroid Build Coastguard Worker 
420*da0073e9SAndroid Build Coastguard Worker     pStream->data_type = 0;
421*da0073e9SAndroid Build Coastguard Worker     pStream->adler = 0;
422*da0073e9SAndroid Build Coastguard Worker     pStream->msg = NULL;
423*da0073e9SAndroid Build Coastguard Worker     pStream->total_in = 0;
424*da0073e9SAndroid Build Coastguard Worker     pStream->total_out = 0;
425*da0073e9SAndroid Build Coastguard Worker     pStream->reserved = 0;
426*da0073e9SAndroid Build Coastguard Worker 
427*da0073e9SAndroid Build Coastguard Worker     pDecomp = (inflate_state *)pStream->state;
428*da0073e9SAndroid Build Coastguard Worker 
429*da0073e9SAndroid Build Coastguard Worker     tinfl_init(&pDecomp->m_decomp);
430*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_dict_ofs = 0;
431*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_dict_avail = 0;
432*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
433*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_first_call = 1;
434*da0073e9SAndroid Build Coastguard Worker     pDecomp->m_has_flushed = 0;
435*da0073e9SAndroid Build Coastguard Worker     /* pDecomp->m_window_bits = window_bits */;
436*da0073e9SAndroid Build Coastguard Worker 
437*da0073e9SAndroid Build Coastguard Worker     return MZ_OK;
438*da0073e9SAndroid Build Coastguard Worker }
439*da0073e9SAndroid Build Coastguard Worker 
mz_inflate(mz_streamp pStream,int flush)440*da0073e9SAndroid Build Coastguard Worker int mz_inflate(mz_streamp pStream, int flush)
441*da0073e9SAndroid Build Coastguard Worker {
442*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
443*da0073e9SAndroid Build Coastguard Worker     inflate_state *pState;
444*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
445*da0073e9SAndroid Build Coastguard Worker     mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
446*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
447*da0073e9SAndroid Build Coastguard Worker     size_t in_bytes, out_bytes, orig_avail_in;
448*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
449*da0073e9SAndroid Build Coastguard Worker     tinfl_status status;
450*da0073e9SAndroid Build Coastguard Worker 
451*da0073e9SAndroid Build Coastguard Worker     if ((!pStream) || (!pStream->state))
452*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
453*da0073e9SAndroid Build Coastguard Worker     if (flush == MZ_PARTIAL_FLUSH)
454*da0073e9SAndroid Build Coastguard Worker         flush = MZ_SYNC_FLUSH;
455*da0073e9SAndroid Build Coastguard Worker     if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
456*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
457*da0073e9SAndroid Build Coastguard Worker 
458*da0073e9SAndroid Build Coastguard Worker     pState = (inflate_state *)pStream->state;
459*da0073e9SAndroid Build Coastguard Worker     if (pState->m_window_bits > 0)
460*da0073e9SAndroid Build Coastguard Worker         decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
461*da0073e9SAndroid Build Coastguard Worker     orig_avail_in = pStream->avail_in;
462*da0073e9SAndroid Build Coastguard Worker 
463*da0073e9SAndroid Build Coastguard Worker     first_call = pState->m_first_call;
464*da0073e9SAndroid Build Coastguard Worker     pState->m_first_call = 0;
465*da0073e9SAndroid Build Coastguard Worker     if (pState->m_last_status < 0)
466*da0073e9SAndroid Build Coastguard Worker         return MZ_DATA_ERROR;
467*da0073e9SAndroid Build Coastguard Worker 
468*da0073e9SAndroid Build Coastguard Worker     if (pState->m_has_flushed && (flush != MZ_FINISH))
469*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
470*da0073e9SAndroid Build Coastguard Worker     pState->m_has_flushed |= (flush == MZ_FINISH);
471*da0073e9SAndroid Build Coastguard Worker 
472*da0073e9SAndroid Build Coastguard Worker     if ((flush == MZ_FINISH) && (first_call))
473*da0073e9SAndroid Build Coastguard Worker     {
474*da0073e9SAndroid Build Coastguard Worker         /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
475*da0073e9SAndroid Build Coastguard Worker         decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
476*da0073e9SAndroid Build Coastguard Worker         in_bytes = pStream->avail_in;
477*da0073e9SAndroid Build Coastguard Worker         out_bytes = pStream->avail_out;
478*da0073e9SAndroid Build Coastguard Worker         status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
479*da0073e9SAndroid Build Coastguard Worker         pState->m_last_status = status;
480*da0073e9SAndroid Build Coastguard Worker         pStream->next_in += (mz_uint)in_bytes;
481*da0073e9SAndroid Build Coastguard Worker         pStream->avail_in -= (mz_uint)in_bytes;
482*da0073e9SAndroid Build Coastguard Worker         pStream->total_in += (mz_uint)in_bytes;
483*da0073e9SAndroid Build Coastguard Worker         pStream->adler = tinfl_get_adler32(&pState->m_decomp);
484*da0073e9SAndroid Build Coastguard Worker         pStream->next_out += (mz_uint)out_bytes;
485*da0073e9SAndroid Build Coastguard Worker         pStream->avail_out -= (mz_uint)out_bytes;
486*da0073e9SAndroid Build Coastguard Worker         pStream->total_out += (mz_uint)out_bytes;
487*da0073e9SAndroid Build Coastguard Worker 
488*da0073e9SAndroid Build Coastguard Worker         if (status < 0)
489*da0073e9SAndroid Build Coastguard Worker             return MZ_DATA_ERROR;
490*da0073e9SAndroid Build Coastguard Worker         else if (status != TINFL_STATUS_DONE)
491*da0073e9SAndroid Build Coastguard Worker         {
492*da0073e9SAndroid Build Coastguard Worker             pState->m_last_status = TINFL_STATUS_FAILED;
493*da0073e9SAndroid Build Coastguard Worker             return MZ_BUF_ERROR;
494*da0073e9SAndroid Build Coastguard Worker         }
495*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_END;
496*da0073e9SAndroid Build Coastguard Worker     }
497*da0073e9SAndroid Build Coastguard Worker     /* flush != MZ_FINISH then we must assume there's more input. */
498*da0073e9SAndroid Build Coastguard Worker     if (flush != MZ_FINISH)
499*da0073e9SAndroid Build Coastguard Worker         decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
500*da0073e9SAndroid Build Coastguard Worker 
501*da0073e9SAndroid Build Coastguard Worker     if (pState->m_dict_avail)
502*da0073e9SAndroid Build Coastguard Worker     {
503*da0073e9SAndroid Build Coastguard Worker         n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
504*da0073e9SAndroid Build Coastguard Worker         memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
505*da0073e9SAndroid Build Coastguard Worker         pStream->next_out += n;
506*da0073e9SAndroid Build Coastguard Worker         pStream->avail_out -= n;
507*da0073e9SAndroid Build Coastguard Worker         pStream->total_out += n;
508*da0073e9SAndroid Build Coastguard Worker         pState->m_dict_avail -= n;
509*da0073e9SAndroid Build Coastguard Worker         pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
510*da0073e9SAndroid Build Coastguard Worker         return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
511*da0073e9SAndroid Build Coastguard Worker     }
512*da0073e9SAndroid Build Coastguard Worker 
513*da0073e9SAndroid Build Coastguard Worker     for (;;)
514*da0073e9SAndroid Build Coastguard Worker     {
515*da0073e9SAndroid Build Coastguard Worker         in_bytes = pStream->avail_in;
516*da0073e9SAndroid Build Coastguard Worker         out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
517*da0073e9SAndroid Build Coastguard Worker 
518*da0073e9SAndroid Build Coastguard Worker         status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
519*da0073e9SAndroid Build Coastguard Worker         pState->m_last_status = status;
520*da0073e9SAndroid Build Coastguard Worker 
521*da0073e9SAndroid Build Coastguard Worker         pStream->next_in += (mz_uint)in_bytes;
522*da0073e9SAndroid Build Coastguard Worker         pStream->avail_in -= (mz_uint)in_bytes;
523*da0073e9SAndroid Build Coastguard Worker         pStream->total_in += (mz_uint)in_bytes;
524*da0073e9SAndroid Build Coastguard Worker         pStream->adler = tinfl_get_adler32(&pState->m_decomp);
525*da0073e9SAndroid Build Coastguard Worker 
526*da0073e9SAndroid Build Coastguard Worker         pState->m_dict_avail = (mz_uint)out_bytes;
527*da0073e9SAndroid Build Coastguard Worker 
528*da0073e9SAndroid Build Coastguard Worker         n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
529*da0073e9SAndroid Build Coastguard Worker         memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
530*da0073e9SAndroid Build Coastguard Worker         pStream->next_out += n;
531*da0073e9SAndroid Build Coastguard Worker         pStream->avail_out -= n;
532*da0073e9SAndroid Build Coastguard Worker         pStream->total_out += n;
533*da0073e9SAndroid Build Coastguard Worker         pState->m_dict_avail -= n;
534*da0073e9SAndroid Build Coastguard Worker         pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
535*da0073e9SAndroid Build Coastguard Worker 
536*da0073e9SAndroid Build Coastguard Worker         if (status < 0)
537*da0073e9SAndroid Build Coastguard Worker             return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
538*da0073e9SAndroid Build Coastguard Worker         else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
539*da0073e9SAndroid Build Coastguard Worker             return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
540*da0073e9SAndroid Build Coastguard Worker         else if (flush == MZ_FINISH)
541*da0073e9SAndroid Build Coastguard Worker         {
542*da0073e9SAndroid Build Coastguard Worker             /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
543*da0073e9SAndroid Build Coastguard Worker             if (status == TINFL_STATUS_DONE)
544*da0073e9SAndroid Build Coastguard Worker                 return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
545*da0073e9SAndroid Build Coastguard Worker             /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */
546*da0073e9SAndroid Build Coastguard Worker             else if (!pStream->avail_out)
547*da0073e9SAndroid Build Coastguard Worker                 return MZ_BUF_ERROR;
548*da0073e9SAndroid Build Coastguard Worker         }
549*da0073e9SAndroid Build Coastguard Worker         else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
550*da0073e9SAndroid Build Coastguard Worker             break;
551*da0073e9SAndroid Build Coastguard Worker     }
552*da0073e9SAndroid Build Coastguard Worker 
553*da0073e9SAndroid Build Coastguard Worker     return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
554*da0073e9SAndroid Build Coastguard Worker }
555*da0073e9SAndroid Build Coastguard Worker 
mz_inflateEnd(mz_streamp pStream)556*da0073e9SAndroid Build Coastguard Worker int mz_inflateEnd(mz_streamp pStream)
557*da0073e9SAndroid Build Coastguard Worker {
558*da0073e9SAndroid Build Coastguard Worker     if (!pStream)
559*da0073e9SAndroid Build Coastguard Worker         return MZ_STREAM_ERROR;
560*da0073e9SAndroid Build Coastguard Worker     if (pStream->state)
561*da0073e9SAndroid Build Coastguard Worker     {
562*da0073e9SAndroid Build Coastguard Worker         pStream->zfree(pStream->opaque, pStream->state);
563*da0073e9SAndroid Build Coastguard Worker         pStream->state = NULL;
564*da0073e9SAndroid Build Coastguard Worker     }
565*da0073e9SAndroid Build Coastguard Worker     return MZ_OK;
566*da0073e9SAndroid Build Coastguard Worker }
567*da0073e9SAndroid Build Coastguard Worker 
mz_uncompress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)568*da0073e9SAndroid Build Coastguard Worker int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
569*da0073e9SAndroid Build Coastguard Worker {
570*da0073e9SAndroid Build Coastguard Worker     mz_stream stream;
571*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
572*da0073e9SAndroid Build Coastguard Worker     int status;
573*da0073e9SAndroid Build Coastguard Worker     memset(&stream, 0, sizeof(stream));
574*da0073e9SAndroid Build Coastguard Worker 
575*da0073e9SAndroid Build Coastguard Worker     /* In case mz_ulong is 64-bits (argh I hate longs). */
576*da0073e9SAndroid Build Coastguard Worker     if ((source_len | *pDest_len) > 0xFFFFFFFFU)
577*da0073e9SAndroid Build Coastguard Worker         return MZ_PARAM_ERROR;
578*da0073e9SAndroid Build Coastguard Worker 
579*da0073e9SAndroid Build Coastguard Worker     stream.next_in = pSource;
580*da0073e9SAndroid Build Coastguard Worker     stream.avail_in = (mz_uint32)source_len;
581*da0073e9SAndroid Build Coastguard Worker     stream.next_out = pDest;
582*da0073e9SAndroid Build Coastguard Worker     stream.avail_out = (mz_uint32)*pDest_len;
583*da0073e9SAndroid Build Coastguard Worker 
584*da0073e9SAndroid Build Coastguard Worker     status = mz_inflateInit(&stream);
585*da0073e9SAndroid Build Coastguard Worker     if (status != MZ_OK)
586*da0073e9SAndroid Build Coastguard Worker         return status;
587*da0073e9SAndroid Build Coastguard Worker 
588*da0073e9SAndroid Build Coastguard Worker     status = mz_inflate(&stream, MZ_FINISH);
589*da0073e9SAndroid Build Coastguard Worker     if (status != MZ_STREAM_END)
590*da0073e9SAndroid Build Coastguard Worker     {
591*da0073e9SAndroid Build Coastguard Worker         mz_inflateEnd(&stream);
592*da0073e9SAndroid Build Coastguard Worker         return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
593*da0073e9SAndroid Build Coastguard Worker     }
594*da0073e9SAndroid Build Coastguard Worker     *pDest_len = stream.total_out;
595*da0073e9SAndroid Build Coastguard Worker 
596*da0073e9SAndroid Build Coastguard Worker     return mz_inflateEnd(&stream);
597*da0073e9SAndroid Build Coastguard Worker }
598*da0073e9SAndroid Build Coastguard Worker 
mz_error(int err)599*da0073e9SAndroid Build Coastguard Worker const char *mz_error(int err)
600*da0073e9SAndroid Build Coastguard Worker {
601*da0073e9SAndroid Build Coastguard Worker     static struct
602*da0073e9SAndroid Build Coastguard Worker     {
603*da0073e9SAndroid Build Coastguard Worker         int m_err;
604*da0073e9SAndroid Build Coastguard Worker         const char *m_pDesc;
605*da0073e9SAndroid Build Coastguard Worker     } s_error_descs[] =
606*da0073e9SAndroid Build Coastguard Worker         {
607*da0073e9SAndroid Build Coastguard Worker           { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
608*da0073e9SAndroid Build Coastguard Worker         };
609*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
610*da0073e9SAndroid Build Coastguard Worker     mz_uint i;
611*da0073e9SAndroid Build Coastguard Worker     for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
612*da0073e9SAndroid Build Coastguard Worker         if (s_error_descs[i].m_err == err)
613*da0073e9SAndroid Build Coastguard Worker             return s_error_descs[i].m_pDesc;
614*da0073e9SAndroid Build Coastguard Worker     return NULL;
615*da0073e9SAndroid Build Coastguard Worker }
616*da0073e9SAndroid Build Coastguard Worker 
617*da0073e9SAndroid Build Coastguard Worker #endif /*MINIZ_NO_ZLIB_APIS */
618*da0073e9SAndroid Build Coastguard Worker 
619*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
620*da0073e9SAndroid Build Coastguard Worker }
621*da0073e9SAndroid Build Coastguard Worker #endif
622*da0073e9SAndroid Build Coastguard Worker 
623*da0073e9SAndroid Build Coastguard Worker /*
624*da0073e9SAndroid Build Coastguard Worker   This is free and unencumbered software released into the public domain.
625*da0073e9SAndroid Build Coastguard Worker 
626*da0073e9SAndroid Build Coastguard Worker   Anyone is free to copy, modify, publish, use, compile, sell, or
627*da0073e9SAndroid Build Coastguard Worker   distribute this software, either in source code form or as a compiled
628*da0073e9SAndroid Build Coastguard Worker   binary, for any purpose, commercial or non-commercial, and by any
629*da0073e9SAndroid Build Coastguard Worker   means.
630*da0073e9SAndroid Build Coastguard Worker 
631*da0073e9SAndroid Build Coastguard Worker   In jurisdictions that recognize copyright laws, the author or authors
632*da0073e9SAndroid Build Coastguard Worker   of this software dedicate any and all copyright interest in the
633*da0073e9SAndroid Build Coastguard Worker   software to the public domain. We make this dedication for the benefit
634*da0073e9SAndroid Build Coastguard Worker   of the public at large and to the detriment of our heirs and
635*da0073e9SAndroid Build Coastguard Worker   successors. We intend this dedication to be an overt act of
636*da0073e9SAndroid Build Coastguard Worker   relinquishment in perpetuity of all present and future rights to this
637*da0073e9SAndroid Build Coastguard Worker   software under copyright law.
638*da0073e9SAndroid Build Coastguard Worker 
639*da0073e9SAndroid Build Coastguard Worker   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
640*da0073e9SAndroid Build Coastguard Worker   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
641*da0073e9SAndroid Build Coastguard Worker   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
642*da0073e9SAndroid Build Coastguard Worker   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
643*da0073e9SAndroid Build Coastguard Worker   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
644*da0073e9SAndroid Build Coastguard Worker   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
645*da0073e9SAndroid Build Coastguard Worker   OTHER DEALINGS IN THE SOFTWARE.
646*da0073e9SAndroid Build Coastguard Worker 
647*da0073e9SAndroid Build Coastguard Worker   For more information, please refer to <http://unlicense.org/>
648*da0073e9SAndroid Build Coastguard Worker */
649*da0073e9SAndroid Build Coastguard Worker /**************************************************************************
650*da0073e9SAndroid Build Coastguard Worker  *
651*da0073e9SAndroid Build Coastguard Worker  * Copyright 2013-2014 RAD Game Tools and Valve Software
652*da0073e9SAndroid Build Coastguard Worker  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
653*da0073e9SAndroid Build Coastguard Worker  * All Rights Reserved.
654*da0073e9SAndroid Build Coastguard Worker  *
655*da0073e9SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
656*da0073e9SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
657*da0073e9SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
658*da0073e9SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
659*da0073e9SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
660*da0073e9SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
661*da0073e9SAndroid Build Coastguard Worker  *
662*da0073e9SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
663*da0073e9SAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
664*da0073e9SAndroid Build Coastguard Worker  *
665*da0073e9SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
666*da0073e9SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
667*da0073e9SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
668*da0073e9SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
669*da0073e9SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
670*da0073e9SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
671*da0073e9SAndroid Build Coastguard Worker  * THE SOFTWARE.
672*da0073e9SAndroid Build Coastguard Worker  *
673*da0073e9SAndroid Build Coastguard Worker  **************************************************************************/
674*da0073e9SAndroid Build Coastguard Worker 
675*da0073e9SAndroid Build Coastguard Worker 
676*da0073e9SAndroid Build Coastguard Worker 
677*da0073e9SAndroid Build Coastguard Worker 
678*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
679*da0073e9SAndroid Build Coastguard Worker extern "C" {
680*da0073e9SAndroid Build Coastguard Worker #endif
681*da0073e9SAndroid Build Coastguard Worker 
682*da0073e9SAndroid Build Coastguard Worker /* ------------------- Low-level Compression (independent from all decompression API's) */
683*da0073e9SAndroid Build Coastguard Worker 
684*da0073e9SAndroid Build Coastguard Worker /* Purposely making these tables static for faster init and thread safety. */
685*da0073e9SAndroid Build Coastguard Worker static const mz_uint16 s_tdefl_len_sym[256] =
686*da0073e9SAndroid Build Coastguard Worker     {
687*da0073e9SAndroid Build Coastguard Worker       257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,
688*da0073e9SAndroid Build Coastguard Worker       273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,
689*da0073e9SAndroid Build Coastguard Worker       277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
690*da0073e9SAndroid Build Coastguard Worker       279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
691*da0073e9SAndroid Build Coastguard Worker       281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
692*da0073e9SAndroid Build Coastguard Worker       282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
693*da0073e9SAndroid Build Coastguard Worker       283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
694*da0073e9SAndroid Build Coastguard Worker       284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285
695*da0073e9SAndroid Build Coastguard Worker     };
696*da0073e9SAndroid Build Coastguard Worker 
697*da0073e9SAndroid Build Coastguard Worker static const mz_uint8 s_tdefl_len_extra[256] =
698*da0073e9SAndroid Build Coastguard Worker     {
699*da0073e9SAndroid Build Coastguard Worker       0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
700*da0073e9SAndroid Build Coastguard Worker       4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
701*da0073e9SAndroid Build Coastguard Worker       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
702*da0073e9SAndroid Build Coastguard Worker       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 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
703*da0073e9SAndroid Build Coastguard Worker     };
704*da0073e9SAndroid Build Coastguard Worker 
705*da0073e9SAndroid Build Coastguard Worker static const mz_uint8 s_tdefl_small_dist_sym[512] =
706*da0073e9SAndroid Build Coastguard Worker     {
707*da0073e9SAndroid Build Coastguard Worker       0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
708*da0073e9SAndroid Build Coastguard Worker       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,
709*da0073e9SAndroid Build Coastguard Worker       13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
710*da0073e9SAndroid Build Coastguard Worker       14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
711*da0073e9SAndroid Build Coastguard Worker       14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
712*da0073e9SAndroid Build Coastguard Worker       15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
713*da0073e9SAndroid Build Coastguard Worker       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
714*da0073e9SAndroid Build Coastguard Worker       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
715*da0073e9SAndroid Build Coastguard Worker       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
716*da0073e9SAndroid Build Coastguard Worker       17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
717*da0073e9SAndroid Build Coastguard Worker       17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
718*da0073e9SAndroid Build Coastguard Worker       17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17
719*da0073e9SAndroid Build Coastguard Worker     };
720*da0073e9SAndroid Build Coastguard Worker 
721*da0073e9SAndroid Build Coastguard Worker static const mz_uint8 s_tdefl_small_dist_extra[512] =
722*da0073e9SAndroid Build Coastguard Worker     {
723*da0073e9SAndroid Build Coastguard Worker       0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
724*da0073e9SAndroid Build Coastguard Worker       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
725*da0073e9SAndroid Build Coastguard Worker       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
726*da0073e9SAndroid Build Coastguard Worker       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
727*da0073e9SAndroid Build Coastguard Worker       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
728*da0073e9SAndroid Build Coastguard Worker       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
729*da0073e9SAndroid Build Coastguard Worker       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
730*da0073e9SAndroid Build Coastguard Worker       7, 7, 7, 7, 7, 7, 7, 7
731*da0073e9SAndroid Build Coastguard Worker     };
732*da0073e9SAndroid Build Coastguard Worker 
733*da0073e9SAndroid Build Coastguard Worker static const mz_uint8 s_tdefl_large_dist_sym[128] =
734*da0073e9SAndroid Build Coastguard Worker     {
735*da0073e9SAndroid Build Coastguard Worker       0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
736*da0073e9SAndroid Build Coastguard Worker       26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
737*da0073e9SAndroid Build Coastguard Worker       28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
738*da0073e9SAndroid Build Coastguard Worker     };
739*da0073e9SAndroid Build Coastguard Worker 
740*da0073e9SAndroid Build Coastguard Worker static const mz_uint8 s_tdefl_large_dist_extra[128] =
741*da0073e9SAndroid Build Coastguard Worker     {
742*da0073e9SAndroid Build Coastguard Worker       0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
743*da0073e9SAndroid Build Coastguard Worker       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
744*da0073e9SAndroid Build Coastguard Worker       13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13
745*da0073e9SAndroid Build Coastguard Worker     };
746*da0073e9SAndroid Build Coastguard Worker 
747*da0073e9SAndroid Build Coastguard Worker /* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */
748*da0073e9SAndroid Build Coastguard Worker typedef struct
749*da0073e9SAndroid Build Coastguard Worker {
750*da0073e9SAndroid Build Coastguard Worker     mz_uint16 m_key, m_sym_index;
751*da0073e9SAndroid Build Coastguard Worker } tdefl_sym_freq;
tdefl_radix_sort_syms(mz_uint num_syms,tdefl_sym_freq * pSyms0,tdefl_sym_freq * pSyms1)752*da0073e9SAndroid Build Coastguard Worker static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1)
753*da0073e9SAndroid Build Coastguard Worker {
754*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,cppcoreguidelines-init-variables)
755*da0073e9SAndroid Build Coastguard Worker     mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
756*da0073e9SAndroid Build Coastguard Worker     tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
757*da0073e9SAndroid Build Coastguard Worker     MZ_CLEAR_OBJ(hist);
758*da0073e9SAndroid Build Coastguard Worker     for (i = 0; i < num_syms; i++)
759*da0073e9SAndroid Build Coastguard Worker     {
760*da0073e9SAndroid Build Coastguard Worker         mz_uint freq = pSyms0[i].m_key;
761*da0073e9SAndroid Build Coastguard Worker         hist[freq & 0xFF]++;
762*da0073e9SAndroid Build Coastguard Worker         hist[256 + ((freq >> 8) & 0xFF)]++;
763*da0073e9SAndroid Build Coastguard Worker     }
764*da0073e9SAndroid Build Coastguard Worker     while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
765*da0073e9SAndroid Build Coastguard Worker         total_passes--;
766*da0073e9SAndroid Build Coastguard Worker     for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
767*da0073e9SAndroid Build Coastguard Worker     {
768*da0073e9SAndroid Build Coastguard Worker         const mz_uint32 *pHist = &hist[pass << 8];
769*da0073e9SAndroid Build Coastguard Worker         mz_uint offsets[256], cur_ofs = 0;
770*da0073e9SAndroid Build Coastguard Worker         for (i = 0; i < 256; i++)
771*da0073e9SAndroid Build Coastguard Worker         {
772*da0073e9SAndroid Build Coastguard Worker             offsets[i] = cur_ofs;
773*da0073e9SAndroid Build Coastguard Worker             cur_ofs += pHist[i];
774*da0073e9SAndroid Build Coastguard Worker         }
775*da0073e9SAndroid Build Coastguard Worker         for (i = 0; i < num_syms; i++)
776*da0073e9SAndroid Build Coastguard Worker             pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
777*da0073e9SAndroid Build Coastguard Worker         {
778*da0073e9SAndroid Build Coastguard Worker             tdefl_sym_freq *t = pCur_syms;
779*da0073e9SAndroid Build Coastguard Worker             pCur_syms = pNew_syms;
780*da0073e9SAndroid Build Coastguard Worker             pNew_syms = t;
781*da0073e9SAndroid Build Coastguard Worker         }
782*da0073e9SAndroid Build Coastguard Worker     }
783*da0073e9SAndroid Build Coastguard Worker     return pCur_syms;
784*da0073e9SAndroid Build Coastguard Worker }
785*da0073e9SAndroid Build Coastguard Worker 
786*da0073e9SAndroid Build Coastguard Worker /* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, [email protected], Jyrki Katajainen, [email protected], November 1996. */
tdefl_calculate_minimum_redundancy(tdefl_sym_freq * A,int n)787*da0073e9SAndroid Build Coastguard Worker static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
788*da0073e9SAndroid Build Coastguard Worker {
789*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
790*da0073e9SAndroid Build Coastguard Worker     int root, leaf, next, avbl, used, dpth;
791*da0073e9SAndroid Build Coastguard Worker     if (n == 0)
792*da0073e9SAndroid Build Coastguard Worker         return;
793*da0073e9SAndroid Build Coastguard Worker     else if (n == 1)
794*da0073e9SAndroid Build Coastguard Worker     {
795*da0073e9SAndroid Build Coastguard Worker         A[0].m_key = 1;
796*da0073e9SAndroid Build Coastguard Worker         return;
797*da0073e9SAndroid Build Coastguard Worker     }
798*da0073e9SAndroid Build Coastguard Worker     A[0].m_key += A[1].m_key;
799*da0073e9SAndroid Build Coastguard Worker     root = 0;
800*da0073e9SAndroid Build Coastguard Worker     leaf = 2;
801*da0073e9SAndroid Build Coastguard Worker     for (next = 1; next < n - 1; next++)
802*da0073e9SAndroid Build Coastguard Worker     {
803*da0073e9SAndroid Build Coastguard Worker         if (leaf >= n || A[root].m_key < A[leaf].m_key)
804*da0073e9SAndroid Build Coastguard Worker         {
805*da0073e9SAndroid Build Coastguard Worker             A[next].m_key = A[root].m_key;
806*da0073e9SAndroid Build Coastguard Worker             A[root++].m_key = (mz_uint16)next;
807*da0073e9SAndroid Build Coastguard Worker         }
808*da0073e9SAndroid Build Coastguard Worker         else
809*da0073e9SAndroid Build Coastguard Worker             A[next].m_key = A[leaf++].m_key;
810*da0073e9SAndroid Build Coastguard Worker         if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
811*da0073e9SAndroid Build Coastguard Worker         {
812*da0073e9SAndroid Build Coastguard Worker             A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
813*da0073e9SAndroid Build Coastguard Worker             A[root++].m_key = (mz_uint16)next;
814*da0073e9SAndroid Build Coastguard Worker         }
815*da0073e9SAndroid Build Coastguard Worker         else
816*da0073e9SAndroid Build Coastguard Worker             A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
817*da0073e9SAndroid Build Coastguard Worker     }
818*da0073e9SAndroid Build Coastguard Worker     A[n - 2].m_key = 0;
819*da0073e9SAndroid Build Coastguard Worker     for (next = n - 3; next >= 0; next--)
820*da0073e9SAndroid Build Coastguard Worker         A[next].m_key = A[A[next].m_key].m_key + 1;
821*da0073e9SAndroid Build Coastguard Worker     avbl = 1;
822*da0073e9SAndroid Build Coastguard Worker     used = dpth = 0;
823*da0073e9SAndroid Build Coastguard Worker     root = n - 2;
824*da0073e9SAndroid Build Coastguard Worker     next = n - 1;
825*da0073e9SAndroid Build Coastguard Worker     while (avbl > 0)
826*da0073e9SAndroid Build Coastguard Worker     {
827*da0073e9SAndroid Build Coastguard Worker         while (root >= 0 && (int)A[root].m_key == dpth)
828*da0073e9SAndroid Build Coastguard Worker         {
829*da0073e9SAndroid Build Coastguard Worker             used++;
830*da0073e9SAndroid Build Coastguard Worker             root--;
831*da0073e9SAndroid Build Coastguard Worker         }
832*da0073e9SAndroid Build Coastguard Worker         while (avbl > used)
833*da0073e9SAndroid Build Coastguard Worker         {
834*da0073e9SAndroid Build Coastguard Worker             A[next--].m_key = (mz_uint16)(dpth);
835*da0073e9SAndroid Build Coastguard Worker             avbl--;
836*da0073e9SAndroid Build Coastguard Worker         }
837*da0073e9SAndroid Build Coastguard Worker         avbl = 2 * used;
838*da0073e9SAndroid Build Coastguard Worker         dpth++;
839*da0073e9SAndroid Build Coastguard Worker         used = 0;
840*da0073e9SAndroid Build Coastguard Worker     }
841*da0073e9SAndroid Build Coastguard Worker }
842*da0073e9SAndroid Build Coastguard Worker 
843*da0073e9SAndroid Build Coastguard Worker /* Limits canonical Huffman code table's max code size. */
844*da0073e9SAndroid Build Coastguard Worker enum
845*da0073e9SAndroid Build Coastguard Worker {
846*da0073e9SAndroid Build Coastguard Worker     TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32
847*da0073e9SAndroid Build Coastguard Worker };
tdefl_huffman_enforce_max_code_size(int * pNum_codes,int code_list_len,int max_code_size)848*da0073e9SAndroid Build Coastguard Worker static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
849*da0073e9SAndroid Build Coastguard Worker {
850*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
851*da0073e9SAndroid Build Coastguard Worker     int i;
852*da0073e9SAndroid Build Coastguard Worker     mz_uint32 total = 0;
853*da0073e9SAndroid Build Coastguard Worker     if (code_list_len <= 1)
854*da0073e9SAndroid Build Coastguard Worker         return;
855*da0073e9SAndroid Build Coastguard Worker     for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
856*da0073e9SAndroid Build Coastguard Worker         pNum_codes[max_code_size] += pNum_codes[i];
857*da0073e9SAndroid Build Coastguard Worker     for (i = max_code_size; i > 0; i--)
858*da0073e9SAndroid Build Coastguard Worker         total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
859*da0073e9SAndroid Build Coastguard Worker     while (total != (1UL << max_code_size))
860*da0073e9SAndroid Build Coastguard Worker     {
861*da0073e9SAndroid Build Coastguard Worker         pNum_codes[max_code_size]--;
862*da0073e9SAndroid Build Coastguard Worker         for (i = max_code_size - 1; i > 0; i--)
863*da0073e9SAndroid Build Coastguard Worker             if (pNum_codes[i])
864*da0073e9SAndroid Build Coastguard Worker             {
865*da0073e9SAndroid Build Coastguard Worker                 pNum_codes[i]--;
866*da0073e9SAndroid Build Coastguard Worker                 pNum_codes[i + 1] += 2;
867*da0073e9SAndroid Build Coastguard Worker                 break;
868*da0073e9SAndroid Build Coastguard Worker             }
869*da0073e9SAndroid Build Coastguard Worker         total--;
870*da0073e9SAndroid Build Coastguard Worker     }
871*da0073e9SAndroid Build Coastguard Worker }
872*da0073e9SAndroid Build Coastguard Worker 
tdefl_optimize_huffman_table(tdefl_compressor * d,int table_num,int table_len,int code_size_limit,int static_table)873*da0073e9SAndroid Build Coastguard Worker static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
874*da0073e9SAndroid Build Coastguard Worker {
875*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
876*da0073e9SAndroid Build Coastguard Worker     int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
877*da0073e9SAndroid Build Coastguard Worker     mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
878*da0073e9SAndroid Build Coastguard Worker     MZ_CLEAR_OBJ(num_codes);
879*da0073e9SAndroid Build Coastguard Worker     if (static_table)
880*da0073e9SAndroid Build Coastguard Worker     {
881*da0073e9SAndroid Build Coastguard Worker         for (i = 0; i < table_len; i++)
882*da0073e9SAndroid Build Coastguard Worker             num_codes[d->m_huff_code_sizes[table_num][i]]++;
883*da0073e9SAndroid Build Coastguard Worker     }
884*da0073e9SAndroid Build Coastguard Worker     else
885*da0073e9SAndroid Build Coastguard Worker     {
886*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
887*da0073e9SAndroid Build Coastguard Worker         tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
888*da0073e9SAndroid Build Coastguard Worker         int num_used_syms = 0;
889*da0073e9SAndroid Build Coastguard Worker         const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
890*da0073e9SAndroid Build Coastguard Worker         for (i = 0; i < table_len; i++)
891*da0073e9SAndroid Build Coastguard Worker             if (pSym_count[i])
892*da0073e9SAndroid Build Coastguard Worker             {
893*da0073e9SAndroid Build Coastguard Worker                 syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
894*da0073e9SAndroid Build Coastguard Worker                 syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
895*da0073e9SAndroid Build Coastguard Worker             }
896*da0073e9SAndroid Build Coastguard Worker 
897*da0073e9SAndroid Build Coastguard Worker         pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
898*da0073e9SAndroid Build Coastguard Worker         tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
899*da0073e9SAndroid Build Coastguard Worker 
900*da0073e9SAndroid Build Coastguard Worker         for (i = 0; i < num_used_syms; i++)
901*da0073e9SAndroid Build Coastguard Worker             num_codes[pSyms[i].m_key]++;
902*da0073e9SAndroid Build Coastguard Worker 
903*da0073e9SAndroid Build Coastguard Worker         tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
904*da0073e9SAndroid Build Coastguard Worker 
905*da0073e9SAndroid Build Coastguard Worker         MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
906*da0073e9SAndroid Build Coastguard Worker         MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
907*da0073e9SAndroid Build Coastguard Worker         for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
908*da0073e9SAndroid Build Coastguard Worker             for (l = num_codes[i]; l > 0; l--)
909*da0073e9SAndroid Build Coastguard Worker                 d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
910*da0073e9SAndroid Build Coastguard Worker     }
911*da0073e9SAndroid Build Coastguard Worker 
912*da0073e9SAndroid Build Coastguard Worker     next_code[1] = 0;
913*da0073e9SAndroid Build Coastguard Worker     for (j = 0, i = 2; i <= code_size_limit; i++)
914*da0073e9SAndroid Build Coastguard Worker         next_code[i] = j = ((j + num_codes[i - 1]) << 1);
915*da0073e9SAndroid Build Coastguard Worker 
916*da0073e9SAndroid Build Coastguard Worker     for (i = 0; i < table_len; i++)
917*da0073e9SAndroid Build Coastguard Worker     {
918*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
919*da0073e9SAndroid Build Coastguard Worker         mz_uint rev_code = 0, code, code_size;
920*da0073e9SAndroid Build Coastguard Worker         if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
921*da0073e9SAndroid Build Coastguard Worker             continue;
922*da0073e9SAndroid Build Coastguard Worker         code = next_code[code_size]++;
923*da0073e9SAndroid Build Coastguard Worker         for (l = code_size; l > 0; l--, code >>= 1)
924*da0073e9SAndroid Build Coastguard Worker             rev_code = (rev_code << 1) | (code & 1);
925*da0073e9SAndroid Build Coastguard Worker         d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
926*da0073e9SAndroid Build Coastguard Worker     }
927*da0073e9SAndroid Build Coastguard Worker }
928*da0073e9SAndroid Build Coastguard Worker 
929*da0073e9SAndroid Build Coastguard Worker #define TDEFL_PUT_BITS(b, l)                                       \
930*da0073e9SAndroid Build Coastguard Worker     do                                                             \
931*da0073e9SAndroid Build Coastguard Worker     {                                                              \
932*da0073e9SAndroid Build Coastguard Worker         mz_uint bits = b;                                          \
933*da0073e9SAndroid Build Coastguard Worker         mz_uint len = l;                                           \
934*da0073e9SAndroid Build Coastguard Worker         MZ_ASSERT(bits <= ((1U << len) - 1U));                     \
935*da0073e9SAndroid Build Coastguard Worker         d->m_bit_buffer |= (bits << d->m_bits_in);                 \
936*da0073e9SAndroid Build Coastguard Worker         d->m_bits_in += len;                                       \
937*da0073e9SAndroid Build Coastguard Worker         while (d->m_bits_in >= 8)                                  \
938*da0073e9SAndroid Build Coastguard Worker         {                                                          \
939*da0073e9SAndroid Build Coastguard Worker             if (d->m_pOutput_buf < d->m_pOutput_buf_end)           \
940*da0073e9SAndroid Build Coastguard Worker                 *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
941*da0073e9SAndroid Build Coastguard Worker             d->m_bit_buffer >>= 8;                                 \
942*da0073e9SAndroid Build Coastguard Worker             d->m_bits_in -= 8;                                     \
943*da0073e9SAndroid Build Coastguard Worker         }                                                          \
944*da0073e9SAndroid Build Coastguard Worker     }                                                              \
945*da0073e9SAndroid Build Coastguard Worker     MZ_MACRO_END
946*da0073e9SAndroid Build Coastguard Worker 
947*da0073e9SAndroid Build Coastguard Worker #define TDEFL_RLE_PREV_CODE_SIZE()                                                                                       \
948*da0073e9SAndroid Build Coastguard Worker     {                                                                                                                    \
949*da0073e9SAndroid Build Coastguard Worker         if (rle_repeat_count)                                                                                            \
950*da0073e9SAndroid Build Coastguard Worker         {                                                                                                                \
951*da0073e9SAndroid Build Coastguard Worker             if (rle_repeat_count < 3)                                                                                    \
952*da0073e9SAndroid Build Coastguard Worker             {                                                                                                            \
953*da0073e9SAndroid Build Coastguard Worker                 d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
954*da0073e9SAndroid Build Coastguard Worker                 while (rle_repeat_count--)                                                                               \
955*da0073e9SAndroid Build Coastguard Worker                     packed_code_sizes[num_packed_code_sizes++] = prev_code_size;                                         \
956*da0073e9SAndroid Build Coastguard Worker             }                                                                                                            \
957*da0073e9SAndroid Build Coastguard Worker             else                                                                                                         \
958*da0073e9SAndroid Build Coastguard Worker             {                                                                                                            \
959*da0073e9SAndroid Build Coastguard Worker                 d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1);                                        \
960*da0073e9SAndroid Build Coastguard Worker                 packed_code_sizes[num_packed_code_sizes++] = 16;                                                         \
961*da0073e9SAndroid Build Coastguard Worker                 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3);                           \
962*da0073e9SAndroid Build Coastguard Worker             }                                                                                                            \
963*da0073e9SAndroid Build Coastguard Worker             rle_repeat_count = 0;                                                                                        \
964*da0073e9SAndroid Build Coastguard Worker         }                                                                                                                \
965*da0073e9SAndroid Build Coastguard Worker     }
966*da0073e9SAndroid Build Coastguard Worker 
967*da0073e9SAndroid Build Coastguard Worker #define TDEFL_RLE_ZERO_CODE_SIZE()                                                         \
968*da0073e9SAndroid Build Coastguard Worker     {                                                                                      \
969*da0073e9SAndroid Build Coastguard Worker         if (rle_z_count)                                                                   \
970*da0073e9SAndroid Build Coastguard Worker         {                                                                                  \
971*da0073e9SAndroid Build Coastguard Worker             if (rle_z_count < 3)                                                           \
972*da0073e9SAndroid Build Coastguard Worker             {                                                                              \
973*da0073e9SAndroid Build Coastguard Worker                 d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);  \
974*da0073e9SAndroid Build Coastguard Worker                 while (rle_z_count--)                                                      \
975*da0073e9SAndroid Build Coastguard Worker                     packed_code_sizes[num_packed_code_sizes++] = 0;                        \
976*da0073e9SAndroid Build Coastguard Worker             }                                                                              \
977*da0073e9SAndroid Build Coastguard Worker             else if (rle_z_count <= 10)                                                    \
978*da0073e9SAndroid Build Coastguard Worker             {                                                                              \
979*da0073e9SAndroid Build Coastguard Worker                 d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);          \
980*da0073e9SAndroid Build Coastguard Worker                 packed_code_sizes[num_packed_code_sizes++] = 17;                           \
981*da0073e9SAndroid Build Coastguard Worker                 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3);  \
982*da0073e9SAndroid Build Coastguard Worker             }                                                                              \
983*da0073e9SAndroid Build Coastguard Worker             else                                                                           \
984*da0073e9SAndroid Build Coastguard Worker             {                                                                              \
985*da0073e9SAndroid Build Coastguard Worker                 d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);          \
986*da0073e9SAndroid Build Coastguard Worker                 packed_code_sizes[num_packed_code_sizes++] = 18;                           \
987*da0073e9SAndroid Build Coastguard Worker                 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
988*da0073e9SAndroid Build Coastguard Worker             }                                                                              \
989*da0073e9SAndroid Build Coastguard Worker             rle_z_count = 0;                                                               \
990*da0073e9SAndroid Build Coastguard Worker         }                                                                                  \
991*da0073e9SAndroid Build Coastguard Worker     }
992*da0073e9SAndroid Build Coastguard Worker 
993*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables,cppcoreguidelines-avoid-magic-numbers)
994*da0073e9SAndroid Build Coastguard Worker static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
995*da0073e9SAndroid Build Coastguard Worker 
tdefl_start_dynamic_block(tdefl_compressor * d)996*da0073e9SAndroid Build Coastguard Worker static void tdefl_start_dynamic_block(tdefl_compressor *d)
997*da0073e9SAndroid Build Coastguard Worker {
998*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
999*da0073e9SAndroid Build Coastguard Worker     int num_lit_codes, num_dist_codes, num_bit_lengths;
1000*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1001*da0073e9SAndroid Build Coastguard Worker     mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
1002*da0073e9SAndroid Build Coastguard Worker     mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
1003*da0073e9SAndroid Build Coastguard Worker 
1004*da0073e9SAndroid Build Coastguard Worker     d->m_huff_count[0][256] = 1;
1005*da0073e9SAndroid Build Coastguard Worker 
1006*da0073e9SAndroid Build Coastguard Worker     tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
1007*da0073e9SAndroid Build Coastguard Worker     tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
1008*da0073e9SAndroid Build Coastguard Worker 
1009*da0073e9SAndroid Build Coastguard Worker     for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
1010*da0073e9SAndroid Build Coastguard Worker         if (d->m_huff_code_sizes[0][num_lit_codes - 1])
1011*da0073e9SAndroid Build Coastguard Worker             break;
1012*da0073e9SAndroid Build Coastguard Worker     for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
1013*da0073e9SAndroid Build Coastguard Worker         if (d->m_huff_code_sizes[1][num_dist_codes - 1])
1014*da0073e9SAndroid Build Coastguard Worker             break;
1015*da0073e9SAndroid Build Coastguard Worker 
1016*da0073e9SAndroid Build Coastguard Worker     memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
1017*da0073e9SAndroid Build Coastguard Worker     memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
1018*da0073e9SAndroid Build Coastguard Worker     total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
1019*da0073e9SAndroid Build Coastguard Worker     num_packed_code_sizes = 0;
1020*da0073e9SAndroid Build Coastguard Worker     rle_z_count = 0;
1021*da0073e9SAndroid Build Coastguard Worker     rle_repeat_count = 0;
1022*da0073e9SAndroid Build Coastguard Worker 
1023*da0073e9SAndroid Build Coastguard Worker     memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
1024*da0073e9SAndroid Build Coastguard Worker     for (i = 0; i < total_code_sizes_to_pack; i++)
1025*da0073e9SAndroid Build Coastguard Worker     {
1026*da0073e9SAndroid Build Coastguard Worker         mz_uint8 code_size = code_sizes_to_pack[i];
1027*da0073e9SAndroid Build Coastguard Worker         if (!code_size)
1028*da0073e9SAndroid Build Coastguard Worker         {
1029*da0073e9SAndroid Build Coastguard Worker             TDEFL_RLE_PREV_CODE_SIZE();
1030*da0073e9SAndroid Build Coastguard Worker             if (++rle_z_count == 138)
1031*da0073e9SAndroid Build Coastguard Worker             {
1032*da0073e9SAndroid Build Coastguard Worker                 TDEFL_RLE_ZERO_CODE_SIZE();
1033*da0073e9SAndroid Build Coastguard Worker             }
1034*da0073e9SAndroid Build Coastguard Worker         }
1035*da0073e9SAndroid Build Coastguard Worker         else
1036*da0073e9SAndroid Build Coastguard Worker         {
1037*da0073e9SAndroid Build Coastguard Worker             TDEFL_RLE_ZERO_CODE_SIZE();
1038*da0073e9SAndroid Build Coastguard Worker             if (code_size != prev_code_size)
1039*da0073e9SAndroid Build Coastguard Worker             {
1040*da0073e9SAndroid Build Coastguard Worker                 TDEFL_RLE_PREV_CODE_SIZE();
1041*da0073e9SAndroid Build Coastguard Worker                 d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
1042*da0073e9SAndroid Build Coastguard Worker                 packed_code_sizes[num_packed_code_sizes++] = code_size;
1043*da0073e9SAndroid Build Coastguard Worker             }
1044*da0073e9SAndroid Build Coastguard Worker             else if (++rle_repeat_count == 6)
1045*da0073e9SAndroid Build Coastguard Worker             {
1046*da0073e9SAndroid Build Coastguard Worker                 TDEFL_RLE_PREV_CODE_SIZE();
1047*da0073e9SAndroid Build Coastguard Worker             }
1048*da0073e9SAndroid Build Coastguard Worker         }
1049*da0073e9SAndroid Build Coastguard Worker         prev_code_size = code_size;
1050*da0073e9SAndroid Build Coastguard Worker     }
1051*da0073e9SAndroid Build Coastguard Worker     if (rle_repeat_count)
1052*da0073e9SAndroid Build Coastguard Worker     {
1053*da0073e9SAndroid Build Coastguard Worker         TDEFL_RLE_PREV_CODE_SIZE();
1054*da0073e9SAndroid Build Coastguard Worker     }
1055*da0073e9SAndroid Build Coastguard Worker     else
1056*da0073e9SAndroid Build Coastguard Worker     {
1057*da0073e9SAndroid Build Coastguard Worker         TDEFL_RLE_ZERO_CODE_SIZE();
1058*da0073e9SAndroid Build Coastguard Worker     }
1059*da0073e9SAndroid Build Coastguard Worker 
1060*da0073e9SAndroid Build Coastguard Worker     tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1061*da0073e9SAndroid Build Coastguard Worker 
1062*da0073e9SAndroid Build Coastguard Worker     TDEFL_PUT_BITS(2, 2);
1063*da0073e9SAndroid Build Coastguard Worker 
1064*da0073e9SAndroid Build Coastguard Worker     TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1065*da0073e9SAndroid Build Coastguard Worker     TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1066*da0073e9SAndroid Build Coastguard Worker 
1067*da0073e9SAndroid Build Coastguard Worker     for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
1068*da0073e9SAndroid Build Coastguard Worker         if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
1069*da0073e9SAndroid Build Coastguard Worker             break;
1070*da0073e9SAndroid Build Coastguard Worker     num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
1071*da0073e9SAndroid Build Coastguard Worker     TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1072*da0073e9SAndroid Build Coastguard Worker     for (i = 0; (int)i < num_bit_lengths; i++)
1073*da0073e9SAndroid Build Coastguard Worker         TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1074*da0073e9SAndroid Build Coastguard Worker 
1075*da0073e9SAndroid Build Coastguard Worker     for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
1076*da0073e9SAndroid Build Coastguard Worker     {
1077*da0073e9SAndroid Build Coastguard Worker         mz_uint code = packed_code_sizes[packed_code_sizes_index++];
1078*da0073e9SAndroid Build Coastguard Worker         MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1079*da0073e9SAndroid Build Coastguard Worker         TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1080*da0073e9SAndroid Build Coastguard Worker         if (code >= 16)
1081*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(bugprone-signed-char-misuse)
1082*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1083*da0073e9SAndroid Build Coastguard Worker     }
1084*da0073e9SAndroid Build Coastguard Worker }
1085*da0073e9SAndroid Build Coastguard Worker 
tdefl_start_static_block(tdefl_compressor * d)1086*da0073e9SAndroid Build Coastguard Worker static void tdefl_start_static_block(tdefl_compressor *d)
1087*da0073e9SAndroid Build Coastguard Worker {
1088*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1089*da0073e9SAndroid Build Coastguard Worker     mz_uint i;
1090*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1091*da0073e9SAndroid Build Coastguard Worker 
1092*da0073e9SAndroid Build Coastguard Worker     for (i = 0; i <= 143; ++i)
1093*da0073e9SAndroid Build Coastguard Worker         *p++ = 8;
1094*da0073e9SAndroid Build Coastguard Worker     for (; i <= 255; ++i)
1095*da0073e9SAndroid Build Coastguard Worker         *p++ = 9;
1096*da0073e9SAndroid Build Coastguard Worker     for (; i <= 279; ++i)
1097*da0073e9SAndroid Build Coastguard Worker         *p++ = 7;
1098*da0073e9SAndroid Build Coastguard Worker     for (; i <= 287; ++i)
1099*da0073e9SAndroid Build Coastguard Worker         *p++ = 8;
1100*da0073e9SAndroid Build Coastguard Worker 
1101*da0073e9SAndroid Build Coastguard Worker     memset(d->m_huff_code_sizes[1], 5, 32);
1102*da0073e9SAndroid Build Coastguard Worker 
1103*da0073e9SAndroid Build Coastguard Worker     tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1104*da0073e9SAndroid Build Coastguard Worker     tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
1105*da0073e9SAndroid Build Coastguard Worker 
1106*da0073e9SAndroid Build Coastguard Worker     TDEFL_PUT_BITS(1, 2);
1107*da0073e9SAndroid Build Coastguard Worker }
1108*da0073e9SAndroid Build Coastguard Worker 
1109*da0073e9SAndroid Build Coastguard Worker static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1110*da0073e9SAndroid Build Coastguard Worker 
1111*da0073e9SAndroid Build Coastguard Worker #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
tdefl_compress_lz_codes(tdefl_compressor * d)1112*da0073e9SAndroid Build Coastguard Worker static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1113*da0073e9SAndroid Build Coastguard Worker {
1114*da0073e9SAndroid Build Coastguard Worker     mz_uint flags;
1115*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLZ_codes;
1116*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pOutput_buf = d->m_pOutput_buf;
1117*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
1118*da0073e9SAndroid Build Coastguard Worker     mz_uint64 bit_buffer = d->m_bit_buffer;
1119*da0073e9SAndroid Build Coastguard Worker     mz_uint bits_in = d->m_bits_in;
1120*da0073e9SAndroid Build Coastguard Worker 
1121*da0073e9SAndroid Build Coastguard Worker #define TDEFL_PUT_BITS_FAST(b, l)                    \
1122*da0073e9SAndroid Build Coastguard Worker     {                                                \
1123*da0073e9SAndroid Build Coastguard Worker         bit_buffer |= (((mz_uint64)(b)) << bits_in); \
1124*da0073e9SAndroid Build Coastguard Worker         bits_in += (l);                              \
1125*da0073e9SAndroid Build Coastguard Worker     }
1126*da0073e9SAndroid Build Coastguard Worker 
1127*da0073e9SAndroid Build Coastguard Worker     flags = 1;
1128*da0073e9SAndroid Build Coastguard Worker     for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
1129*da0073e9SAndroid Build Coastguard Worker     {
1130*da0073e9SAndroid Build Coastguard Worker         if (flags == 1)
1131*da0073e9SAndroid Build Coastguard Worker             flags = *pLZ_codes++ | 0x100;
1132*da0073e9SAndroid Build Coastguard Worker 
1133*da0073e9SAndroid Build Coastguard Worker         if (flags & 1)
1134*da0073e9SAndroid Build Coastguard Worker         {
1135*da0073e9SAndroid Build Coastguard Worker             mz_uint s0, s1, n0, n1, sym, num_extra_bits;
1136*da0073e9SAndroid Build Coastguard Worker             mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
1137*da0073e9SAndroid Build Coastguard Worker             pLZ_codes += 3;
1138*da0073e9SAndroid Build Coastguard Worker 
1139*da0073e9SAndroid Build Coastguard Worker             MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1140*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1141*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1142*da0073e9SAndroid Build Coastguard Worker 
1143*da0073e9SAndroid Build Coastguard Worker             /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
1144*da0073e9SAndroid Build Coastguard Worker             s0 = s_tdefl_small_dist_sym[match_dist & 511];
1145*da0073e9SAndroid Build Coastguard Worker             n0 = s_tdefl_small_dist_extra[match_dist & 511];
1146*da0073e9SAndroid Build Coastguard Worker             s1 = s_tdefl_large_dist_sym[match_dist >> 8];
1147*da0073e9SAndroid Build Coastguard Worker             n1 = s_tdefl_large_dist_extra[match_dist >> 8];
1148*da0073e9SAndroid Build Coastguard Worker             sym = (match_dist < 512) ? s0 : s1;
1149*da0073e9SAndroid Build Coastguard Worker             num_extra_bits = (match_dist < 512) ? n0 : n1;
1150*da0073e9SAndroid Build Coastguard Worker 
1151*da0073e9SAndroid Build Coastguard Worker             MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1152*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1153*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1154*da0073e9SAndroid Build Coastguard Worker         }
1155*da0073e9SAndroid Build Coastguard Worker         else
1156*da0073e9SAndroid Build Coastguard Worker         {
1157*da0073e9SAndroid Build Coastguard Worker             mz_uint lit = *pLZ_codes++;
1158*da0073e9SAndroid Build Coastguard Worker             MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1159*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1160*da0073e9SAndroid Build Coastguard Worker 
1161*da0073e9SAndroid Build Coastguard Worker             if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1162*da0073e9SAndroid Build Coastguard Worker             {
1163*da0073e9SAndroid Build Coastguard Worker                 flags >>= 1;
1164*da0073e9SAndroid Build Coastguard Worker                 lit = *pLZ_codes++;
1165*da0073e9SAndroid Build Coastguard Worker                 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1166*da0073e9SAndroid Build Coastguard Worker                 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1167*da0073e9SAndroid Build Coastguard Worker 
1168*da0073e9SAndroid Build Coastguard Worker                 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1169*da0073e9SAndroid Build Coastguard Worker                 {
1170*da0073e9SAndroid Build Coastguard Worker                     flags >>= 1;
1171*da0073e9SAndroid Build Coastguard Worker                     lit = *pLZ_codes++;
1172*da0073e9SAndroid Build Coastguard Worker                     MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1173*da0073e9SAndroid Build Coastguard Worker                     TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1174*da0073e9SAndroid Build Coastguard Worker                 }
1175*da0073e9SAndroid Build Coastguard Worker             }
1176*da0073e9SAndroid Build Coastguard Worker         }
1177*da0073e9SAndroid Build Coastguard Worker 
1178*da0073e9SAndroid Build Coastguard Worker         if (pOutput_buf >= d->m_pOutput_buf_end)
1179*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
1180*da0073e9SAndroid Build Coastguard Worker 
1181*da0073e9SAndroid Build Coastguard Worker         *(mz_uint64 *)pOutput_buf = bit_buffer;
1182*da0073e9SAndroid Build Coastguard Worker         pOutput_buf += (bits_in >> 3);
1183*da0073e9SAndroid Build Coastguard Worker         bit_buffer >>= (bits_in & ~7);
1184*da0073e9SAndroid Build Coastguard Worker         bits_in &= 7;
1185*da0073e9SAndroid Build Coastguard Worker     }
1186*da0073e9SAndroid Build Coastguard Worker 
1187*da0073e9SAndroid Build Coastguard Worker #undef TDEFL_PUT_BITS_FAST
1188*da0073e9SAndroid Build Coastguard Worker 
1189*da0073e9SAndroid Build Coastguard Worker     d->m_pOutput_buf = pOutput_buf;
1190*da0073e9SAndroid Build Coastguard Worker     d->m_bits_in = 0;
1191*da0073e9SAndroid Build Coastguard Worker     d->m_bit_buffer = 0;
1192*da0073e9SAndroid Build Coastguard Worker 
1193*da0073e9SAndroid Build Coastguard Worker     while (bits_in)
1194*da0073e9SAndroid Build Coastguard Worker     {
1195*da0073e9SAndroid Build Coastguard Worker         mz_uint32 n = MZ_MIN(bits_in, 16);
1196*da0073e9SAndroid Build Coastguard Worker         TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
1197*da0073e9SAndroid Build Coastguard Worker         bit_buffer >>= n;
1198*da0073e9SAndroid Build Coastguard Worker         bits_in -= n;
1199*da0073e9SAndroid Build Coastguard Worker     }
1200*da0073e9SAndroid Build Coastguard Worker 
1201*da0073e9SAndroid Build Coastguard Worker     TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1202*da0073e9SAndroid Build Coastguard Worker 
1203*da0073e9SAndroid Build Coastguard Worker     return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1204*da0073e9SAndroid Build Coastguard Worker }
1205*da0073e9SAndroid Build Coastguard Worker #else
tdefl_compress_lz_codes(tdefl_compressor * d)1206*da0073e9SAndroid Build Coastguard Worker static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1207*da0073e9SAndroid Build Coastguard Worker {
1208*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1209*da0073e9SAndroid Build Coastguard Worker     mz_uint flags;
1210*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1211*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLZ_codes;
1212*da0073e9SAndroid Build Coastguard Worker 
1213*da0073e9SAndroid Build Coastguard Worker     flags = 1;
1214*da0073e9SAndroid Build Coastguard Worker     for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1215*da0073e9SAndroid Build Coastguard Worker     {
1216*da0073e9SAndroid Build Coastguard Worker         if (flags == 1)
1217*da0073e9SAndroid Build Coastguard Worker             flags = *pLZ_codes++ | 0x100;
1218*da0073e9SAndroid Build Coastguard Worker         if (flags & 1)
1219*da0073e9SAndroid Build Coastguard Worker         {
1220*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1221*da0073e9SAndroid Build Coastguard Worker             mz_uint sym, num_extra_bits;
1222*da0073e9SAndroid Build Coastguard Worker             mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1223*da0073e9SAndroid Build Coastguard Worker             pLZ_codes += 3;
1224*da0073e9SAndroid Build Coastguard Worker 
1225*da0073e9SAndroid Build Coastguard Worker             MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1226*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1227*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1228*da0073e9SAndroid Build Coastguard Worker 
1229*da0073e9SAndroid Build Coastguard Worker             if (match_dist < 512)
1230*da0073e9SAndroid Build Coastguard Worker             {
1231*da0073e9SAndroid Build Coastguard Worker                 sym = s_tdefl_small_dist_sym[match_dist];
1232*da0073e9SAndroid Build Coastguard Worker                 num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1233*da0073e9SAndroid Build Coastguard Worker             }
1234*da0073e9SAndroid Build Coastguard Worker             else
1235*da0073e9SAndroid Build Coastguard Worker             {
1236*da0073e9SAndroid Build Coastguard Worker                 sym = s_tdefl_large_dist_sym[match_dist >> 8];
1237*da0073e9SAndroid Build Coastguard Worker                 num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1238*da0073e9SAndroid Build Coastguard Worker             }
1239*da0073e9SAndroid Build Coastguard Worker             MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1240*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1241*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1242*da0073e9SAndroid Build Coastguard Worker         }
1243*da0073e9SAndroid Build Coastguard Worker         else
1244*da0073e9SAndroid Build Coastguard Worker         {
1245*da0073e9SAndroid Build Coastguard Worker             mz_uint lit = *pLZ_codes++;
1246*da0073e9SAndroid Build Coastguard Worker             MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1247*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1248*da0073e9SAndroid Build Coastguard Worker         }
1249*da0073e9SAndroid Build Coastguard Worker     }
1250*da0073e9SAndroid Build Coastguard Worker 
1251*da0073e9SAndroid Build Coastguard Worker     TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1252*da0073e9SAndroid Build Coastguard Worker 
1253*da0073e9SAndroid Build Coastguard Worker     return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1254*da0073e9SAndroid Build Coastguard Worker }
1255*da0073e9SAndroid Build Coastguard Worker #endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */
1256*da0073e9SAndroid Build Coastguard Worker 
tdefl_compress_block(tdefl_compressor * d,mz_bool static_block)1257*da0073e9SAndroid Build Coastguard Worker static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
1258*da0073e9SAndroid Build Coastguard Worker {
1259*da0073e9SAndroid Build Coastguard Worker     if (static_block)
1260*da0073e9SAndroid Build Coastguard Worker         tdefl_start_static_block(d);
1261*da0073e9SAndroid Build Coastguard Worker     else
1262*da0073e9SAndroid Build Coastguard Worker         tdefl_start_dynamic_block(d);
1263*da0073e9SAndroid Build Coastguard Worker     return tdefl_compress_lz_codes(d);
1264*da0073e9SAndroid Build Coastguard Worker }
1265*da0073e9SAndroid Build Coastguard Worker 
tdefl_flush_block(tdefl_compressor * d,int flush)1266*da0073e9SAndroid Build Coastguard Worker static int tdefl_flush_block(tdefl_compressor *d, int flush)
1267*da0073e9SAndroid Build Coastguard Worker {
1268*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1269*da0073e9SAndroid Build Coastguard Worker     mz_uint saved_bit_buf, saved_bits_in;
1270*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1271*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pSaved_output_buf;
1272*da0073e9SAndroid Build Coastguard Worker     mz_bool comp_block_succeeded = MZ_FALSE;
1273*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1274*da0073e9SAndroid Build Coastguard Worker     int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
1275*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
1276*da0073e9SAndroid Build Coastguard Worker 
1277*da0073e9SAndroid Build Coastguard Worker     d->m_pOutput_buf = pOutput_buf_start;
1278*da0073e9SAndroid Build Coastguard Worker     d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
1279*da0073e9SAndroid Build Coastguard Worker 
1280*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT(!d->m_output_flush_remaining);
1281*da0073e9SAndroid Build Coastguard Worker     d->m_output_flush_ofs = 0;
1282*da0073e9SAndroid Build Coastguard Worker     d->m_output_flush_remaining = 0;
1283*da0073e9SAndroid Build Coastguard Worker 
1284*da0073e9SAndroid Build Coastguard Worker     *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
1285*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1286*da0073e9SAndroid Build Coastguard Worker 
1287*da0073e9SAndroid Build Coastguard Worker     if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1288*da0073e9SAndroid Build Coastguard Worker     {
1289*da0073e9SAndroid Build Coastguard Worker         TDEFL_PUT_BITS(0x78, 8);
1290*da0073e9SAndroid Build Coastguard Worker         TDEFL_PUT_BITS(0x01, 8);
1291*da0073e9SAndroid Build Coastguard Worker     }
1292*da0073e9SAndroid Build Coastguard Worker 
1293*da0073e9SAndroid Build Coastguard Worker     TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1294*da0073e9SAndroid Build Coastguard Worker 
1295*da0073e9SAndroid Build Coastguard Worker     pSaved_output_buf = d->m_pOutput_buf;
1296*da0073e9SAndroid Build Coastguard Worker     saved_bit_buf = d->m_bit_buffer;
1297*da0073e9SAndroid Build Coastguard Worker     saved_bits_in = d->m_bits_in;
1298*da0073e9SAndroid Build Coastguard Worker 
1299*da0073e9SAndroid Build Coastguard Worker     if (!use_raw_block)
1300*da0073e9SAndroid Build Coastguard Worker         comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
1301*da0073e9SAndroid Build Coastguard Worker 
1302*da0073e9SAndroid Build Coastguard Worker     /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */
1303*da0073e9SAndroid Build Coastguard Worker     if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
1304*da0073e9SAndroid Build Coastguard Worker         ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size))
1305*da0073e9SAndroid Build Coastguard Worker     {
1306*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1307*da0073e9SAndroid Build Coastguard Worker         mz_uint i;
1308*da0073e9SAndroid Build Coastguard Worker         d->m_pOutput_buf = pSaved_output_buf;
1309*da0073e9SAndroid Build Coastguard Worker         d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1310*da0073e9SAndroid Build Coastguard Worker         TDEFL_PUT_BITS(0, 2);
1311*da0073e9SAndroid Build Coastguard Worker         if (d->m_bits_in)
1312*da0073e9SAndroid Build Coastguard Worker         {
1313*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1314*da0073e9SAndroid Build Coastguard Worker         }
1315*da0073e9SAndroid Build Coastguard Worker         for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1316*da0073e9SAndroid Build Coastguard Worker         {
1317*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1318*da0073e9SAndroid Build Coastguard Worker         }
1319*da0073e9SAndroid Build Coastguard Worker         for (i = 0; i < d->m_total_lz_bytes; ++i)
1320*da0073e9SAndroid Build Coastguard Worker         {
1321*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
1322*da0073e9SAndroid Build Coastguard Worker         }
1323*da0073e9SAndroid Build Coastguard Worker     }
1324*da0073e9SAndroid Build Coastguard Worker     /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */
1325*da0073e9SAndroid Build Coastguard Worker     else if (!comp_block_succeeded)
1326*da0073e9SAndroid Build Coastguard Worker     {
1327*da0073e9SAndroid Build Coastguard Worker         d->m_pOutput_buf = pSaved_output_buf;
1328*da0073e9SAndroid Build Coastguard Worker         d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1329*da0073e9SAndroid Build Coastguard Worker         tdefl_compress_block(d, MZ_TRUE);
1330*da0073e9SAndroid Build Coastguard Worker     }
1331*da0073e9SAndroid Build Coastguard Worker 
1332*da0073e9SAndroid Build Coastguard Worker     if (flush)
1333*da0073e9SAndroid Build Coastguard Worker     {
1334*da0073e9SAndroid Build Coastguard Worker         if (flush == TDEFL_FINISH)
1335*da0073e9SAndroid Build Coastguard Worker         {
1336*da0073e9SAndroid Build Coastguard Worker             if (d->m_bits_in)
1337*da0073e9SAndroid Build Coastguard Worker             {
1338*da0073e9SAndroid Build Coastguard Worker                 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1339*da0073e9SAndroid Build Coastguard Worker             }
1340*da0073e9SAndroid Build Coastguard Worker             if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)
1341*da0073e9SAndroid Build Coastguard Worker             {
1342*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1343*da0073e9SAndroid Build Coastguard Worker                 mz_uint i, a = d->m_adler32;
1344*da0073e9SAndroid Build Coastguard Worker                 for (i = 0; i < 4; i++)
1345*da0073e9SAndroid Build Coastguard Worker                 {
1346*da0073e9SAndroid Build Coastguard Worker                     TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
1347*da0073e9SAndroid Build Coastguard Worker                     a <<= 8;
1348*da0073e9SAndroid Build Coastguard Worker                 }
1349*da0073e9SAndroid Build Coastguard Worker             }
1350*da0073e9SAndroid Build Coastguard Worker         }
1351*da0073e9SAndroid Build Coastguard Worker         else
1352*da0073e9SAndroid Build Coastguard Worker         {
1353*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1354*da0073e9SAndroid Build Coastguard Worker             mz_uint i, z = 0;
1355*da0073e9SAndroid Build Coastguard Worker             TDEFL_PUT_BITS(0, 3);
1356*da0073e9SAndroid Build Coastguard Worker             if (d->m_bits_in)
1357*da0073e9SAndroid Build Coastguard Worker             {
1358*da0073e9SAndroid Build Coastguard Worker                 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1359*da0073e9SAndroid Build Coastguard Worker             }
1360*da0073e9SAndroid Build Coastguard Worker             for (i = 2; i; --i, z ^= 0xFFFF)
1361*da0073e9SAndroid Build Coastguard Worker             {
1362*da0073e9SAndroid Build Coastguard Worker                 TDEFL_PUT_BITS(z & 0xFFFF, 16);
1363*da0073e9SAndroid Build Coastguard Worker             }
1364*da0073e9SAndroid Build Coastguard Worker         }
1365*da0073e9SAndroid Build Coastguard Worker     }
1366*da0073e9SAndroid Build Coastguard Worker 
1367*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
1368*da0073e9SAndroid Build Coastguard Worker 
1369*da0073e9SAndroid Build Coastguard Worker     memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1370*da0073e9SAndroid Build Coastguard Worker     memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1371*da0073e9SAndroid Build Coastguard Worker 
1372*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1373*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_flags = d->m_lz_code_buf;
1374*da0073e9SAndroid Build Coastguard Worker     d->m_num_flags_left = 8;
1375*da0073e9SAndroid Build Coastguard Worker     d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
1376*da0073e9SAndroid Build Coastguard Worker     d->m_total_lz_bytes = 0;
1377*da0073e9SAndroid Build Coastguard Worker     d->m_block_index++;
1378*da0073e9SAndroid Build Coastguard Worker 
1379*da0073e9SAndroid Build Coastguard Worker     if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1380*da0073e9SAndroid Build Coastguard Worker     {
1381*da0073e9SAndroid Build Coastguard Worker         if (d->m_pPut_buf_func)
1382*da0073e9SAndroid Build Coastguard Worker         {
1383*da0073e9SAndroid Build Coastguard Worker             *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1384*da0073e9SAndroid Build Coastguard Worker             if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
1385*da0073e9SAndroid Build Coastguard Worker                 return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
1386*da0073e9SAndroid Build Coastguard Worker         }
1387*da0073e9SAndroid Build Coastguard Worker         else if (pOutput_buf_start == d->m_output_buf)
1388*da0073e9SAndroid Build Coastguard Worker         {
1389*da0073e9SAndroid Build Coastguard Worker             int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1390*da0073e9SAndroid Build Coastguard Worker             memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1391*da0073e9SAndroid Build Coastguard Worker             d->m_out_buf_ofs += bytes_to_copy;
1392*da0073e9SAndroid Build Coastguard Worker             if ((n -= bytes_to_copy) != 0)
1393*da0073e9SAndroid Build Coastguard Worker             {
1394*da0073e9SAndroid Build Coastguard Worker                 d->m_output_flush_ofs = bytes_to_copy;
1395*da0073e9SAndroid Build Coastguard Worker                 d->m_output_flush_remaining = n;
1396*da0073e9SAndroid Build Coastguard Worker             }
1397*da0073e9SAndroid Build Coastguard Worker         }
1398*da0073e9SAndroid Build Coastguard Worker         else
1399*da0073e9SAndroid Build Coastguard Worker         {
1400*da0073e9SAndroid Build Coastguard Worker             d->m_out_buf_ofs += n;
1401*da0073e9SAndroid Build Coastguard Worker         }
1402*da0073e9SAndroid Build Coastguard Worker     }
1403*da0073e9SAndroid Build Coastguard Worker 
1404*da0073e9SAndroid Build Coastguard Worker     return d->m_output_flush_remaining;
1405*da0073e9SAndroid Build Coastguard Worker }
1406*da0073e9SAndroid Build Coastguard Worker 
1407*da0073e9SAndroid Build Coastguard Worker #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1408*da0073e9SAndroid Build Coastguard Worker #ifdef MINIZ_UNALIGNED_USE_MEMCPY
TDEFL_READ_UNALIGNED_WORD(const mz_uint8 * p)1409*da0073e9SAndroid Build Coastguard Worker static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p)
1410*da0073e9SAndroid Build Coastguard Worker {
1411*da0073e9SAndroid Build Coastguard Worker 	mz_uint16 ret;
1412*da0073e9SAndroid Build Coastguard Worker 	memcpy(&ret, p, sizeof(mz_uint16));
1413*da0073e9SAndroid Build Coastguard Worker 	return ret;
1414*da0073e9SAndroid Build Coastguard Worker }
TDEFL_READ_UNALIGNED_WORD2(const mz_uint16 * p)1415*da0073e9SAndroid Build Coastguard Worker static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p)
1416*da0073e9SAndroid Build Coastguard Worker {
1417*da0073e9SAndroid Build Coastguard Worker 	mz_uint16 ret;
1418*da0073e9SAndroid Build Coastguard Worker 	memcpy(&ret, p, sizeof(mz_uint16));
1419*da0073e9SAndroid Build Coastguard Worker 	return ret;
1420*da0073e9SAndroid Build Coastguard Worker }
1421*da0073e9SAndroid Build Coastguard Worker #else
1422*da0073e9SAndroid Build Coastguard Worker #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
1423*da0073e9SAndroid Build Coastguard Worker #define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
1424*da0073e9SAndroid Build Coastguard Worker #endif
tdefl_find_match(tdefl_compressor * d,mz_uint lookahead_pos,mz_uint max_dist,mz_uint max_match_len,mz_uint * pMatch_dist,mz_uint * pMatch_len)1425*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1426*da0073e9SAndroid Build Coastguard Worker {
1427*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1428*da0073e9SAndroid Build Coastguard Worker     mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1429*da0073e9SAndroid Build Coastguard Worker     mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1430*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1431*da0073e9SAndroid Build Coastguard Worker     const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
1432*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1433*da0073e9SAndroid Build Coastguard Worker     mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s);
1434*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1435*da0073e9SAndroid Build Coastguard Worker     if (max_match_len <= match_len)
1436*da0073e9SAndroid Build Coastguard Worker         return;
1437*da0073e9SAndroid Build Coastguard Worker     for (;;)
1438*da0073e9SAndroid Build Coastguard Worker     {
1439*da0073e9SAndroid Build Coastguard Worker         for (;;)
1440*da0073e9SAndroid Build Coastguard Worker         {
1441*da0073e9SAndroid Build Coastguard Worker             if (--num_probes_left == 0)
1442*da0073e9SAndroid Build Coastguard Worker                 return;
1443*da0073e9SAndroid Build Coastguard Worker #define TDEFL_PROBE                                                                             \
1444*da0073e9SAndroid Build Coastguard Worker     next_probe_pos = d->m_next[probe_pos];                                                      \
1445*da0073e9SAndroid Build Coastguard Worker     if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1446*da0073e9SAndroid Build Coastguard Worker         return;                                                                                 \
1447*da0073e9SAndroid Build Coastguard Worker     probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                       \
1448*da0073e9SAndroid Build Coastguard Worker     if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01)                \
1449*da0073e9SAndroid Build Coastguard Worker         break;
1450*da0073e9SAndroid Build Coastguard Worker             TDEFL_PROBE;
1451*da0073e9SAndroid Build Coastguard Worker             TDEFL_PROBE;
1452*da0073e9SAndroid Build Coastguard Worker             TDEFL_PROBE;
1453*da0073e9SAndroid Build Coastguard Worker         }
1454*da0073e9SAndroid Build Coastguard Worker         if (!dist)
1455*da0073e9SAndroid Build Coastguard Worker             break;
1456*da0073e9SAndroid Build Coastguard Worker         q = (const mz_uint16 *)(d->m_dict + probe_pos);
1457*da0073e9SAndroid Build Coastguard Worker         if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)
1458*da0073e9SAndroid Build Coastguard Worker             continue;
1459*da0073e9SAndroid Build Coastguard Worker         p = s;
1460*da0073e9SAndroid Build Coastguard Worker         probe_len = 32;
1461*da0073e9SAndroid Build Coastguard Worker         do
1462*da0073e9SAndroid Build Coastguard Worker         {
1463*da0073e9SAndroid Build Coastguard Worker         } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1464*da0073e9SAndroid Build Coastguard Worker                  (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1465*da0073e9SAndroid Build Coastguard Worker         if (!probe_len)
1466*da0073e9SAndroid Build Coastguard Worker         {
1467*da0073e9SAndroid Build Coastguard Worker             *pMatch_dist = dist;
1468*da0073e9SAndroid Build Coastguard Worker             *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
1469*da0073e9SAndroid Build Coastguard Worker             break;
1470*da0073e9SAndroid Build Coastguard Worker         }
1471*da0073e9SAndroid Build Coastguard Worker         else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len)
1472*da0073e9SAndroid Build Coastguard Worker         {
1473*da0073e9SAndroid Build Coastguard Worker             *pMatch_dist = dist;
1474*da0073e9SAndroid Build Coastguard Worker             if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)
1475*da0073e9SAndroid Build Coastguard Worker                 break;
1476*da0073e9SAndroid Build Coastguard Worker             c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
1477*da0073e9SAndroid Build Coastguard Worker         }
1478*da0073e9SAndroid Build Coastguard Worker     }
1479*da0073e9SAndroid Build Coastguard Worker }
1480*da0073e9SAndroid Build Coastguard Worker #else
tdefl_find_match(tdefl_compressor * d,mz_uint lookahead_pos,mz_uint max_dist,mz_uint max_match_len,mz_uint * pMatch_dist,mz_uint * pMatch_len)1481*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1482*da0073e9SAndroid Build Coastguard Worker {
1483*da0073e9SAndroid Build Coastguard Worker     mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1484*da0073e9SAndroid Build Coastguard Worker     mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1485*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *s = d->m_dict + pos, *p, *q;
1486*da0073e9SAndroid Build Coastguard Worker     mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1487*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1488*da0073e9SAndroid Build Coastguard Worker     if (max_match_len <= match_len)
1489*da0073e9SAndroid Build Coastguard Worker         return;
1490*da0073e9SAndroid Build Coastguard Worker     for (;;)
1491*da0073e9SAndroid Build Coastguard Worker     {
1492*da0073e9SAndroid Build Coastguard Worker         for (;;)
1493*da0073e9SAndroid Build Coastguard Worker         {
1494*da0073e9SAndroid Build Coastguard Worker             if (--num_probes_left == 0)
1495*da0073e9SAndroid Build Coastguard Worker                 return;
1496*da0073e9SAndroid Build Coastguard Worker #define TDEFL_PROBE                                                                               \
1497*da0073e9SAndroid Build Coastguard Worker     next_probe_pos = d->m_next[probe_pos];                                                        \
1498*da0073e9SAndroid Build Coastguard Worker     if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))   \
1499*da0073e9SAndroid Build Coastguard Worker         return;                                                                                   \
1500*da0073e9SAndroid Build Coastguard Worker     probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                         \
1501*da0073e9SAndroid Build Coastguard Worker     if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
1502*da0073e9SAndroid Build Coastguard Worker         break;
1503*da0073e9SAndroid Build Coastguard Worker             TDEFL_PROBE;
1504*da0073e9SAndroid Build Coastguard Worker             TDEFL_PROBE;
1505*da0073e9SAndroid Build Coastguard Worker             TDEFL_PROBE;
1506*da0073e9SAndroid Build Coastguard Worker         }
1507*da0073e9SAndroid Build Coastguard Worker         if (!dist)
1508*da0073e9SAndroid Build Coastguard Worker             break;
1509*da0073e9SAndroid Build Coastguard Worker         p = s;
1510*da0073e9SAndroid Build Coastguard Worker         q = d->m_dict + probe_pos;
1511*da0073e9SAndroid Build Coastguard Worker         for (probe_len = 0; probe_len < max_match_len; probe_len++)
1512*da0073e9SAndroid Build Coastguard Worker             if (*p++ != *q++)
1513*da0073e9SAndroid Build Coastguard Worker                 break;
1514*da0073e9SAndroid Build Coastguard Worker         if (probe_len > match_len)
1515*da0073e9SAndroid Build Coastguard Worker         {
1516*da0073e9SAndroid Build Coastguard Worker             *pMatch_dist = dist;
1517*da0073e9SAndroid Build Coastguard Worker             if ((*pMatch_len = match_len = probe_len) == max_match_len)
1518*da0073e9SAndroid Build Coastguard Worker                 return;
1519*da0073e9SAndroid Build Coastguard Worker             c0 = d->m_dict[pos + match_len];
1520*da0073e9SAndroid Build Coastguard Worker             c1 = d->m_dict[pos + match_len - 1];
1521*da0073e9SAndroid Build Coastguard Worker         }
1522*da0073e9SAndroid Build Coastguard Worker     }
1523*da0073e9SAndroid Build Coastguard Worker }
1524*da0073e9SAndroid Build Coastguard Worker #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
1525*da0073e9SAndroid Build Coastguard Worker 
1526*da0073e9SAndroid Build Coastguard Worker #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1527*da0073e9SAndroid Build Coastguard Worker #ifdef MINIZ_UNALIGNED_USE_MEMCPY
TDEFL_READ_UNALIGNED_WORD32(const mz_uint8 * p)1528*da0073e9SAndroid Build Coastguard Worker static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p)
1529*da0073e9SAndroid Build Coastguard Worker {
1530*da0073e9SAndroid Build Coastguard Worker 	mz_uint32 ret;
1531*da0073e9SAndroid Build Coastguard Worker 	memcpy(&ret, p, sizeof(mz_uint32));
1532*da0073e9SAndroid Build Coastguard Worker 	return ret;
1533*da0073e9SAndroid Build Coastguard Worker }
1534*da0073e9SAndroid Build Coastguard Worker #else
1535*da0073e9SAndroid Build Coastguard Worker #define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p)
1536*da0073e9SAndroid Build Coastguard Worker #endif
tdefl_compress_fast(tdefl_compressor * d)1537*da0073e9SAndroid Build Coastguard Worker static mz_bool tdefl_compress_fast(tdefl_compressor *d)
1538*da0073e9SAndroid Build Coastguard Worker {
1539*da0073e9SAndroid Build Coastguard Worker     /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */
1540*da0073e9SAndroid Build Coastguard Worker     mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
1541*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
1542*da0073e9SAndroid Build Coastguard Worker     mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1543*da0073e9SAndroid Build Coastguard Worker 
1544*da0073e9SAndroid Build Coastguard Worker     while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
1545*da0073e9SAndroid Build Coastguard Worker     {
1546*da0073e9SAndroid Build Coastguard Worker         const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
1547*da0073e9SAndroid Build Coastguard Worker         mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1548*da0073e9SAndroid Build Coastguard Worker         mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
1549*da0073e9SAndroid Build Coastguard Worker         d->m_src_buf_left -= num_bytes_to_process;
1550*da0073e9SAndroid Build Coastguard Worker         lookahead_size += num_bytes_to_process;
1551*da0073e9SAndroid Build Coastguard Worker 
1552*da0073e9SAndroid Build Coastguard Worker         while (num_bytes_to_process)
1553*da0073e9SAndroid Build Coastguard Worker         {
1554*da0073e9SAndroid Build Coastguard Worker             mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
1555*da0073e9SAndroid Build Coastguard Worker             memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
1556*da0073e9SAndroid Build Coastguard Worker             if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1557*da0073e9SAndroid Build Coastguard Worker                 memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
1558*da0073e9SAndroid Build Coastguard Worker             d->m_pSrc += n;
1559*da0073e9SAndroid Build Coastguard Worker             dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
1560*da0073e9SAndroid Build Coastguard Worker             num_bytes_to_process -= n;
1561*da0073e9SAndroid Build Coastguard Worker         }
1562*da0073e9SAndroid Build Coastguard Worker 
1563*da0073e9SAndroid Build Coastguard Worker         dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
1564*da0073e9SAndroid Build Coastguard Worker         if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
1565*da0073e9SAndroid Build Coastguard Worker             break;
1566*da0073e9SAndroid Build Coastguard Worker 
1567*da0073e9SAndroid Build Coastguard Worker         while (lookahead_size >= 4)
1568*da0073e9SAndroid Build Coastguard Worker         {
1569*da0073e9SAndroid Build Coastguard Worker             mz_uint cur_match_dist, cur_match_len = 1;
1570*da0073e9SAndroid Build Coastguard Worker             mz_uint8 *pCur_dict = d->m_dict + cur_pos;
1571*da0073e9SAndroid Build Coastguard Worker             mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF;
1572*da0073e9SAndroid Build Coastguard Worker             mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
1573*da0073e9SAndroid Build Coastguard Worker             mz_uint probe_pos = d->m_hash[hash];
1574*da0073e9SAndroid Build Coastguard Worker             d->m_hash[hash] = (mz_uint16)lookahead_pos;
1575*da0073e9SAndroid Build Coastguard Worker 
1576*da0073e9SAndroid Build Coastguard Worker             if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((TDEFL_READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
1577*da0073e9SAndroid Build Coastguard Worker             {
1578*da0073e9SAndroid Build Coastguard Worker                 const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
1579*da0073e9SAndroid Build Coastguard Worker                 const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
1580*da0073e9SAndroid Build Coastguard Worker                 mz_uint32 probe_len = 32;
1581*da0073e9SAndroid Build Coastguard Worker                 do
1582*da0073e9SAndroid Build Coastguard Worker                 {
1583*da0073e9SAndroid Build Coastguard Worker                 } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1584*da0073e9SAndroid Build Coastguard Worker                          (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1585*da0073e9SAndroid Build Coastguard Worker                 cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
1586*da0073e9SAndroid Build Coastguard Worker                 if (!probe_len)
1587*da0073e9SAndroid Build Coastguard Worker                     cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
1588*da0073e9SAndroid Build Coastguard Worker 
1589*da0073e9SAndroid Build Coastguard Worker                 if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))
1590*da0073e9SAndroid Build Coastguard Worker                 {
1591*da0073e9SAndroid Build Coastguard Worker                     cur_match_len = 1;
1592*da0073e9SAndroid Build Coastguard Worker                     *pLZ_code_buf++ = (mz_uint8)first_trigram;
1593*da0073e9SAndroid Build Coastguard Worker                     *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1594*da0073e9SAndroid Build Coastguard Worker                     d->m_huff_count[0][(mz_uint8)first_trigram]++;
1595*da0073e9SAndroid Build Coastguard Worker                 }
1596*da0073e9SAndroid Build Coastguard Worker                 else
1597*da0073e9SAndroid Build Coastguard Worker                 {
1598*da0073e9SAndroid Build Coastguard Worker                     mz_uint32 s0, s1;
1599*da0073e9SAndroid Build Coastguard Worker                     cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
1600*da0073e9SAndroid Build Coastguard Worker 
1601*da0073e9SAndroid Build Coastguard Worker                     MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
1602*da0073e9SAndroid Build Coastguard Worker 
1603*da0073e9SAndroid Build Coastguard Worker                     cur_match_dist--;
1604*da0073e9SAndroid Build Coastguard Worker 
1605*da0073e9SAndroid Build Coastguard Worker                     pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
1606*da0073e9SAndroid Build Coastguard Worker #ifdef MINIZ_UNALIGNED_USE_MEMCPY
1607*da0073e9SAndroid Build Coastguard Worker 					memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist));
1608*da0073e9SAndroid Build Coastguard Worker #else
1609*da0073e9SAndroid Build Coastguard Worker                     *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
1610*da0073e9SAndroid Build Coastguard Worker #endif
1611*da0073e9SAndroid Build Coastguard Worker                     pLZ_code_buf += 3;
1612*da0073e9SAndroid Build Coastguard Worker                     *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
1613*da0073e9SAndroid Build Coastguard Worker 
1614*da0073e9SAndroid Build Coastguard Worker                     s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
1615*da0073e9SAndroid Build Coastguard Worker                     s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
1616*da0073e9SAndroid Build Coastguard Worker                     d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
1617*da0073e9SAndroid Build Coastguard Worker 
1618*da0073e9SAndroid Build Coastguard Worker                     d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
1619*da0073e9SAndroid Build Coastguard Worker                 }
1620*da0073e9SAndroid Build Coastguard Worker             }
1621*da0073e9SAndroid Build Coastguard Worker             else
1622*da0073e9SAndroid Build Coastguard Worker             {
1623*da0073e9SAndroid Build Coastguard Worker                 *pLZ_code_buf++ = (mz_uint8)first_trigram;
1624*da0073e9SAndroid Build Coastguard Worker                 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1625*da0073e9SAndroid Build Coastguard Worker                 d->m_huff_count[0][(mz_uint8)first_trigram]++;
1626*da0073e9SAndroid Build Coastguard Worker             }
1627*da0073e9SAndroid Build Coastguard Worker 
1628*da0073e9SAndroid Build Coastguard Worker             if (--num_flags_left == 0)
1629*da0073e9SAndroid Build Coastguard Worker             {
1630*da0073e9SAndroid Build Coastguard Worker                 num_flags_left = 8;
1631*da0073e9SAndroid Build Coastguard Worker                 pLZ_flags = pLZ_code_buf++;
1632*da0073e9SAndroid Build Coastguard Worker             }
1633*da0073e9SAndroid Build Coastguard Worker 
1634*da0073e9SAndroid Build Coastguard Worker             total_lz_bytes += cur_match_len;
1635*da0073e9SAndroid Build Coastguard Worker             lookahead_pos += cur_match_len;
1636*da0073e9SAndroid Build Coastguard Worker             dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
1637*da0073e9SAndroid Build Coastguard Worker             cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
1638*da0073e9SAndroid Build Coastguard Worker             MZ_ASSERT(lookahead_size >= cur_match_len);
1639*da0073e9SAndroid Build Coastguard Worker             lookahead_size -= cur_match_len;
1640*da0073e9SAndroid Build Coastguard Worker 
1641*da0073e9SAndroid Build Coastguard Worker             if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1642*da0073e9SAndroid Build Coastguard Worker             {
1643*da0073e9SAndroid Build Coastguard Worker                 int n;
1644*da0073e9SAndroid Build Coastguard Worker                 d->m_lookahead_pos = lookahead_pos;
1645*da0073e9SAndroid Build Coastguard Worker                 d->m_lookahead_size = lookahead_size;
1646*da0073e9SAndroid Build Coastguard Worker                 d->m_dict_size = dict_size;
1647*da0073e9SAndroid Build Coastguard Worker                 d->m_total_lz_bytes = total_lz_bytes;
1648*da0073e9SAndroid Build Coastguard Worker                 d->m_pLZ_code_buf = pLZ_code_buf;
1649*da0073e9SAndroid Build Coastguard Worker                 d->m_pLZ_flags = pLZ_flags;
1650*da0073e9SAndroid Build Coastguard Worker                 d->m_num_flags_left = num_flags_left;
1651*da0073e9SAndroid Build Coastguard Worker                 if ((n = tdefl_flush_block(d, 0)) != 0)
1652*da0073e9SAndroid Build Coastguard Worker                     return (n < 0) ? MZ_FALSE : MZ_TRUE;
1653*da0073e9SAndroid Build Coastguard Worker                 total_lz_bytes = d->m_total_lz_bytes;
1654*da0073e9SAndroid Build Coastguard Worker                 pLZ_code_buf = d->m_pLZ_code_buf;
1655*da0073e9SAndroid Build Coastguard Worker                 pLZ_flags = d->m_pLZ_flags;
1656*da0073e9SAndroid Build Coastguard Worker                 num_flags_left = d->m_num_flags_left;
1657*da0073e9SAndroid Build Coastguard Worker             }
1658*da0073e9SAndroid Build Coastguard Worker         }
1659*da0073e9SAndroid Build Coastguard Worker 
1660*da0073e9SAndroid Build Coastguard Worker         while (lookahead_size)
1661*da0073e9SAndroid Build Coastguard Worker         {
1662*da0073e9SAndroid Build Coastguard Worker             mz_uint8 lit = d->m_dict[cur_pos];
1663*da0073e9SAndroid Build Coastguard Worker 
1664*da0073e9SAndroid Build Coastguard Worker             total_lz_bytes++;
1665*da0073e9SAndroid Build Coastguard Worker             *pLZ_code_buf++ = lit;
1666*da0073e9SAndroid Build Coastguard Worker             *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1667*da0073e9SAndroid Build Coastguard Worker             if (--num_flags_left == 0)
1668*da0073e9SAndroid Build Coastguard Worker             {
1669*da0073e9SAndroid Build Coastguard Worker                 num_flags_left = 8;
1670*da0073e9SAndroid Build Coastguard Worker                 pLZ_flags = pLZ_code_buf++;
1671*da0073e9SAndroid Build Coastguard Worker             }
1672*da0073e9SAndroid Build Coastguard Worker 
1673*da0073e9SAndroid Build Coastguard Worker             d->m_huff_count[0][lit]++;
1674*da0073e9SAndroid Build Coastguard Worker 
1675*da0073e9SAndroid Build Coastguard Worker             lookahead_pos++;
1676*da0073e9SAndroid Build Coastguard Worker             dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
1677*da0073e9SAndroid Build Coastguard Worker             cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1678*da0073e9SAndroid Build Coastguard Worker             lookahead_size--;
1679*da0073e9SAndroid Build Coastguard Worker 
1680*da0073e9SAndroid Build Coastguard Worker             if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1681*da0073e9SAndroid Build Coastguard Worker             {
1682*da0073e9SAndroid Build Coastguard Worker                 int n;
1683*da0073e9SAndroid Build Coastguard Worker                 d->m_lookahead_pos = lookahead_pos;
1684*da0073e9SAndroid Build Coastguard Worker                 d->m_lookahead_size = lookahead_size;
1685*da0073e9SAndroid Build Coastguard Worker                 d->m_dict_size = dict_size;
1686*da0073e9SAndroid Build Coastguard Worker                 d->m_total_lz_bytes = total_lz_bytes;
1687*da0073e9SAndroid Build Coastguard Worker                 d->m_pLZ_code_buf = pLZ_code_buf;
1688*da0073e9SAndroid Build Coastguard Worker                 d->m_pLZ_flags = pLZ_flags;
1689*da0073e9SAndroid Build Coastguard Worker                 d->m_num_flags_left = num_flags_left;
1690*da0073e9SAndroid Build Coastguard Worker                 if ((n = tdefl_flush_block(d, 0)) != 0)
1691*da0073e9SAndroid Build Coastguard Worker                     return (n < 0) ? MZ_FALSE : MZ_TRUE;
1692*da0073e9SAndroid Build Coastguard Worker                 total_lz_bytes = d->m_total_lz_bytes;
1693*da0073e9SAndroid Build Coastguard Worker                 pLZ_code_buf = d->m_pLZ_code_buf;
1694*da0073e9SAndroid Build Coastguard Worker                 pLZ_flags = d->m_pLZ_flags;
1695*da0073e9SAndroid Build Coastguard Worker                 num_flags_left = d->m_num_flags_left;
1696*da0073e9SAndroid Build Coastguard Worker             }
1697*da0073e9SAndroid Build Coastguard Worker         }
1698*da0073e9SAndroid Build Coastguard Worker     }
1699*da0073e9SAndroid Build Coastguard Worker 
1700*da0073e9SAndroid Build Coastguard Worker     d->m_lookahead_pos = lookahead_pos;
1701*da0073e9SAndroid Build Coastguard Worker     d->m_lookahead_size = lookahead_size;
1702*da0073e9SAndroid Build Coastguard Worker     d->m_dict_size = dict_size;
1703*da0073e9SAndroid Build Coastguard Worker     d->m_total_lz_bytes = total_lz_bytes;
1704*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_code_buf = pLZ_code_buf;
1705*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_flags = pLZ_flags;
1706*da0073e9SAndroid Build Coastguard Worker     d->m_num_flags_left = num_flags_left;
1707*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
1708*da0073e9SAndroid Build Coastguard Worker }
1709*da0073e9SAndroid Build Coastguard Worker #endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1710*da0073e9SAndroid Build Coastguard Worker 
tdefl_record_literal(tdefl_compressor * d,mz_uint8 lit)1711*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
1712*da0073e9SAndroid Build Coastguard Worker {
1713*da0073e9SAndroid Build Coastguard Worker     d->m_total_lz_bytes++;
1714*da0073e9SAndroid Build Coastguard Worker     *d->m_pLZ_code_buf++ = lit;
1715*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
1716*da0073e9SAndroid Build Coastguard Worker     *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
1717*da0073e9SAndroid Build Coastguard Worker     if (--d->m_num_flags_left == 0)
1718*da0073e9SAndroid Build Coastguard Worker     {
1719*da0073e9SAndroid Build Coastguard Worker         d->m_num_flags_left = 8;
1720*da0073e9SAndroid Build Coastguard Worker         d->m_pLZ_flags = d->m_pLZ_code_buf++;
1721*da0073e9SAndroid Build Coastguard Worker     }
1722*da0073e9SAndroid Build Coastguard Worker     d->m_huff_count[0][lit]++;
1723*da0073e9SAndroid Build Coastguard Worker }
1724*da0073e9SAndroid Build Coastguard Worker 
tdefl_record_match(tdefl_compressor * d,mz_uint match_len,mz_uint match_dist)1725*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
1726*da0073e9SAndroid Build Coastguard Worker {
1727*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1728*da0073e9SAndroid Build Coastguard Worker     mz_uint32 s0, s1;
1729*da0073e9SAndroid Build Coastguard Worker 
1730*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1731*da0073e9SAndroid Build Coastguard Worker 
1732*da0073e9SAndroid Build Coastguard Worker     d->m_total_lz_bytes += match_len;
1733*da0073e9SAndroid Build Coastguard Worker 
1734*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1735*da0073e9SAndroid Build Coastguard Worker 
1736*da0073e9SAndroid Build Coastguard Worker     match_dist -= 1;
1737*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1738*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
1739*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_code_buf += 3;
1740*da0073e9SAndroid Build Coastguard Worker 
1741*da0073e9SAndroid Build Coastguard Worker     *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
1742*da0073e9SAndroid Build Coastguard Worker     if (--d->m_num_flags_left == 0)
1743*da0073e9SAndroid Build Coastguard Worker     {
1744*da0073e9SAndroid Build Coastguard Worker         d->m_num_flags_left = 8;
1745*da0073e9SAndroid Build Coastguard Worker         d->m_pLZ_flags = d->m_pLZ_code_buf++;
1746*da0073e9SAndroid Build Coastguard Worker     }
1747*da0073e9SAndroid Build Coastguard Worker 
1748*da0073e9SAndroid Build Coastguard Worker     s0 = s_tdefl_small_dist_sym[match_dist & 511];
1749*da0073e9SAndroid Build Coastguard Worker     s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1750*da0073e9SAndroid Build Coastguard Worker     d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1751*da0073e9SAndroid Build Coastguard Worker 
1752*da0073e9SAndroid Build Coastguard Worker     if (match_len >= TDEFL_MIN_MATCH_LEN)
1753*da0073e9SAndroid Build Coastguard Worker         d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1754*da0073e9SAndroid Build Coastguard Worker }
1755*da0073e9SAndroid Build Coastguard Worker 
tdefl_compress_normal(tdefl_compressor * d)1756*da0073e9SAndroid Build Coastguard Worker static mz_bool tdefl_compress_normal(tdefl_compressor *d)
1757*da0073e9SAndroid Build Coastguard Worker {
1758*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *pSrc = d->m_pSrc;
1759*da0073e9SAndroid Build Coastguard Worker     size_t src_buf_left = d->m_src_buf_left;
1760*da0073e9SAndroid Build Coastguard Worker     tdefl_flush flush = d->m_flush;
1761*da0073e9SAndroid Build Coastguard Worker 
1762*da0073e9SAndroid Build Coastguard Worker     while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1763*da0073e9SAndroid Build Coastguard Worker     {
1764*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1765*da0073e9SAndroid Build Coastguard Worker         mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
1766*da0073e9SAndroid Build Coastguard Worker         /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */
1767*da0073e9SAndroid Build Coastguard Worker         if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1768*da0073e9SAndroid Build Coastguard Worker         {
1769*da0073e9SAndroid Build Coastguard Worker             mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
1770*da0073e9SAndroid Build Coastguard Worker             mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
1771*da0073e9SAndroid Build Coastguard Worker             mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1772*da0073e9SAndroid Build Coastguard Worker             const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
1773*da0073e9SAndroid Build Coastguard Worker             src_buf_left -= num_bytes_to_process;
1774*da0073e9SAndroid Build Coastguard Worker             d->m_lookahead_size += num_bytes_to_process;
1775*da0073e9SAndroid Build Coastguard Worker             while (pSrc != pSrc_end)
1776*da0073e9SAndroid Build Coastguard Worker             {
1777*da0073e9SAndroid Build Coastguard Worker                 mz_uint8 c = *pSrc++;
1778*da0073e9SAndroid Build Coastguard Worker                 d->m_dict[dst_pos] = c;
1779*da0073e9SAndroid Build Coastguard Worker                 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1780*da0073e9SAndroid Build Coastguard Worker                     d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1781*da0073e9SAndroid Build Coastguard Worker                 hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1782*da0073e9SAndroid Build Coastguard Worker                 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1783*da0073e9SAndroid Build Coastguard Worker                 d->m_hash[hash] = (mz_uint16)(ins_pos);
1784*da0073e9SAndroid Build Coastguard Worker                 dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1785*da0073e9SAndroid Build Coastguard Worker                 ins_pos++;
1786*da0073e9SAndroid Build Coastguard Worker             }
1787*da0073e9SAndroid Build Coastguard Worker         }
1788*da0073e9SAndroid Build Coastguard Worker         else
1789*da0073e9SAndroid Build Coastguard Worker         {
1790*da0073e9SAndroid Build Coastguard Worker             while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1791*da0073e9SAndroid Build Coastguard Worker             {
1792*da0073e9SAndroid Build Coastguard Worker                 mz_uint8 c = *pSrc++;
1793*da0073e9SAndroid Build Coastguard Worker                 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1794*da0073e9SAndroid Build Coastguard Worker                 src_buf_left--;
1795*da0073e9SAndroid Build Coastguard Worker                 d->m_dict[dst_pos] = c;
1796*da0073e9SAndroid Build Coastguard Worker                 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1797*da0073e9SAndroid Build Coastguard Worker                     d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1798*da0073e9SAndroid Build Coastguard Worker                 if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
1799*da0073e9SAndroid Build Coastguard Worker                 {
1800*da0073e9SAndroid Build Coastguard Worker                     mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1801*da0073e9SAndroid Build Coastguard Worker                     mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1802*da0073e9SAndroid Build Coastguard Worker                     d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1803*da0073e9SAndroid Build Coastguard Worker                     d->m_hash[hash] = (mz_uint16)(ins_pos);
1804*da0073e9SAndroid Build Coastguard Worker                 }
1805*da0073e9SAndroid Build Coastguard Worker             }
1806*da0073e9SAndroid Build Coastguard Worker         }
1807*da0073e9SAndroid Build Coastguard Worker         d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
1808*da0073e9SAndroid Build Coastguard Worker         if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1809*da0073e9SAndroid Build Coastguard Worker             break;
1810*da0073e9SAndroid Build Coastguard Worker 
1811*da0073e9SAndroid Build Coastguard Worker         /* Simple lazy/greedy parsing state machine. */
1812*da0073e9SAndroid Build Coastguard Worker         len_to_move = 1;
1813*da0073e9SAndroid Build Coastguard Worker         cur_match_dist = 0;
1814*da0073e9SAndroid Build Coastguard Worker         cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
1815*da0073e9SAndroid Build Coastguard Worker         cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1816*da0073e9SAndroid Build Coastguard Worker         if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
1817*da0073e9SAndroid Build Coastguard Worker         {
1818*da0073e9SAndroid Build Coastguard Worker             if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1819*da0073e9SAndroid Build Coastguard Worker             {
1820*da0073e9SAndroid Build Coastguard Worker                 mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1821*da0073e9SAndroid Build Coastguard Worker                 cur_match_len = 0;
1822*da0073e9SAndroid Build Coastguard Worker                 while (cur_match_len < d->m_lookahead_size)
1823*da0073e9SAndroid Build Coastguard Worker                 {
1824*da0073e9SAndroid Build Coastguard Worker                     if (d->m_dict[cur_pos + cur_match_len] != c)
1825*da0073e9SAndroid Build Coastguard Worker                         break;
1826*da0073e9SAndroid Build Coastguard Worker                     cur_match_len++;
1827*da0073e9SAndroid Build Coastguard Worker                 }
1828*da0073e9SAndroid Build Coastguard Worker                 if (cur_match_len < TDEFL_MIN_MATCH_LEN)
1829*da0073e9SAndroid Build Coastguard Worker                     cur_match_len = 0;
1830*da0073e9SAndroid Build Coastguard Worker                 else
1831*da0073e9SAndroid Build Coastguard Worker                     cur_match_dist = 1;
1832*da0073e9SAndroid Build Coastguard Worker             }
1833*da0073e9SAndroid Build Coastguard Worker         }
1834*da0073e9SAndroid Build Coastguard Worker         else
1835*da0073e9SAndroid Build Coastguard Worker         {
1836*da0073e9SAndroid Build Coastguard Worker             tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1837*da0073e9SAndroid Build Coastguard Worker         }
1838*da0073e9SAndroid Build Coastguard Worker         if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
1839*da0073e9SAndroid Build Coastguard Worker         {
1840*da0073e9SAndroid Build Coastguard Worker             cur_match_dist = cur_match_len = 0;
1841*da0073e9SAndroid Build Coastguard Worker         }
1842*da0073e9SAndroid Build Coastguard Worker         if (d->m_saved_match_len)
1843*da0073e9SAndroid Build Coastguard Worker         {
1844*da0073e9SAndroid Build Coastguard Worker             if (cur_match_len > d->m_saved_match_len)
1845*da0073e9SAndroid Build Coastguard Worker             {
1846*da0073e9SAndroid Build Coastguard Worker                 tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
1847*da0073e9SAndroid Build Coastguard Worker                 if (cur_match_len >= 128)
1848*da0073e9SAndroid Build Coastguard Worker                 {
1849*da0073e9SAndroid Build Coastguard Worker                     tdefl_record_match(d, cur_match_len, cur_match_dist);
1850*da0073e9SAndroid Build Coastguard Worker                     d->m_saved_match_len = 0;
1851*da0073e9SAndroid Build Coastguard Worker                     len_to_move = cur_match_len;
1852*da0073e9SAndroid Build Coastguard Worker                 }
1853*da0073e9SAndroid Build Coastguard Worker                 else
1854*da0073e9SAndroid Build Coastguard Worker                 {
1855*da0073e9SAndroid Build Coastguard Worker                     d->m_saved_lit = d->m_dict[cur_pos];
1856*da0073e9SAndroid Build Coastguard Worker                     d->m_saved_match_dist = cur_match_dist;
1857*da0073e9SAndroid Build Coastguard Worker                     d->m_saved_match_len = cur_match_len;
1858*da0073e9SAndroid Build Coastguard Worker                 }
1859*da0073e9SAndroid Build Coastguard Worker             }
1860*da0073e9SAndroid Build Coastguard Worker             else
1861*da0073e9SAndroid Build Coastguard Worker             {
1862*da0073e9SAndroid Build Coastguard Worker                 tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
1863*da0073e9SAndroid Build Coastguard Worker                 len_to_move = d->m_saved_match_len - 1;
1864*da0073e9SAndroid Build Coastguard Worker                 d->m_saved_match_len = 0;
1865*da0073e9SAndroid Build Coastguard Worker             }
1866*da0073e9SAndroid Build Coastguard Worker         }
1867*da0073e9SAndroid Build Coastguard Worker         else if (!cur_match_dist)
1868*da0073e9SAndroid Build Coastguard Worker             tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
1869*da0073e9SAndroid Build Coastguard Worker         else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1870*da0073e9SAndroid Build Coastguard Worker         {
1871*da0073e9SAndroid Build Coastguard Worker             tdefl_record_match(d, cur_match_len, cur_match_dist);
1872*da0073e9SAndroid Build Coastguard Worker             len_to_move = cur_match_len;
1873*da0073e9SAndroid Build Coastguard Worker         }
1874*da0073e9SAndroid Build Coastguard Worker         else
1875*da0073e9SAndroid Build Coastguard Worker         {
1876*da0073e9SAndroid Build Coastguard Worker             d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
1877*da0073e9SAndroid Build Coastguard Worker             d->m_saved_match_dist = cur_match_dist;
1878*da0073e9SAndroid Build Coastguard Worker             d->m_saved_match_len = cur_match_len;
1879*da0073e9SAndroid Build Coastguard Worker         }
1880*da0073e9SAndroid Build Coastguard Worker         /* Move the lookahead forward by len_to_move bytes. */
1881*da0073e9SAndroid Build Coastguard Worker         d->m_lookahead_pos += len_to_move;
1882*da0073e9SAndroid Build Coastguard Worker         MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1883*da0073e9SAndroid Build Coastguard Worker         d->m_lookahead_size -= len_to_move;
1884*da0073e9SAndroid Build Coastguard Worker         d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
1885*da0073e9SAndroid Build Coastguard Worker         /* Check if it's time to flush the current LZ codes to the internal output buffer. */
1886*da0073e9SAndroid Build Coastguard Worker         if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
1887*da0073e9SAndroid Build Coastguard Worker             ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))))
1888*da0073e9SAndroid Build Coastguard Worker         {
1889*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1890*da0073e9SAndroid Build Coastguard Worker             int n;
1891*da0073e9SAndroid Build Coastguard Worker             d->m_pSrc = pSrc;
1892*da0073e9SAndroid Build Coastguard Worker             d->m_src_buf_left = src_buf_left;
1893*da0073e9SAndroid Build Coastguard Worker             if ((n = tdefl_flush_block(d, 0)) != 0)
1894*da0073e9SAndroid Build Coastguard Worker                 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1895*da0073e9SAndroid Build Coastguard Worker         }
1896*da0073e9SAndroid Build Coastguard Worker     }
1897*da0073e9SAndroid Build Coastguard Worker 
1898*da0073e9SAndroid Build Coastguard Worker     d->m_pSrc = pSrc;
1899*da0073e9SAndroid Build Coastguard Worker     d->m_src_buf_left = src_buf_left;
1900*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
1901*da0073e9SAndroid Build Coastguard Worker }
1902*da0073e9SAndroid Build Coastguard Worker 
tdefl_flush_output_buffer(tdefl_compressor * d)1903*da0073e9SAndroid Build Coastguard Worker static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
1904*da0073e9SAndroid Build Coastguard Worker {
1905*da0073e9SAndroid Build Coastguard Worker     if (d->m_pIn_buf_size)
1906*da0073e9SAndroid Build Coastguard Worker     {
1907*da0073e9SAndroid Build Coastguard Worker         *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1908*da0073e9SAndroid Build Coastguard Worker     }
1909*da0073e9SAndroid Build Coastguard Worker 
1910*da0073e9SAndroid Build Coastguard Worker     if (d->m_pOut_buf_size)
1911*da0073e9SAndroid Build Coastguard Worker     {
1912*da0073e9SAndroid Build Coastguard Worker         size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
1913*da0073e9SAndroid Build Coastguard Worker         memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1914*da0073e9SAndroid Build Coastguard Worker         d->m_output_flush_ofs += (mz_uint)n;
1915*da0073e9SAndroid Build Coastguard Worker         d->m_output_flush_remaining -= (mz_uint)n;
1916*da0073e9SAndroid Build Coastguard Worker         d->m_out_buf_ofs += n;
1917*da0073e9SAndroid Build Coastguard Worker 
1918*da0073e9SAndroid Build Coastguard Worker         *d->m_pOut_buf_size = d->m_out_buf_ofs;
1919*da0073e9SAndroid Build Coastguard Worker     }
1920*da0073e9SAndroid Build Coastguard Worker 
1921*da0073e9SAndroid Build Coastguard Worker     return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
1922*da0073e9SAndroid Build Coastguard Worker }
1923*da0073e9SAndroid Build Coastguard Worker 
tdefl_compress(tdefl_compressor * d,const void * pIn_buf,size_t * pIn_buf_size,void * pOut_buf,size_t * pOut_buf_size,tdefl_flush flush)1924*da0073e9SAndroid Build Coastguard Worker tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
1925*da0073e9SAndroid Build Coastguard Worker {
1926*da0073e9SAndroid Build Coastguard Worker     if (!d)
1927*da0073e9SAndroid Build Coastguard Worker     {
1928*da0073e9SAndroid Build Coastguard Worker         if (pIn_buf_size)
1929*da0073e9SAndroid Build Coastguard Worker             *pIn_buf_size = 0;
1930*da0073e9SAndroid Build Coastguard Worker         if (pOut_buf_size)
1931*da0073e9SAndroid Build Coastguard Worker             *pOut_buf_size = 0;
1932*da0073e9SAndroid Build Coastguard Worker         return TDEFL_STATUS_BAD_PARAM;
1933*da0073e9SAndroid Build Coastguard Worker     }
1934*da0073e9SAndroid Build Coastguard Worker 
1935*da0073e9SAndroid Build Coastguard Worker     d->m_pIn_buf = pIn_buf;
1936*da0073e9SAndroid Build Coastguard Worker     d->m_pIn_buf_size = pIn_buf_size;
1937*da0073e9SAndroid Build Coastguard Worker     d->m_pOut_buf = pOut_buf;
1938*da0073e9SAndroid Build Coastguard Worker     d->m_pOut_buf_size = pOut_buf_size;
1939*da0073e9SAndroid Build Coastguard Worker     d->m_pSrc = (const mz_uint8 *)(pIn_buf);
1940*da0073e9SAndroid Build Coastguard Worker     d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1941*da0073e9SAndroid Build Coastguard Worker     d->m_out_buf_ofs = 0;
1942*da0073e9SAndroid Build Coastguard Worker     d->m_flush = flush;
1943*da0073e9SAndroid Build Coastguard Worker 
1944*da0073e9SAndroid Build Coastguard Worker     if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1945*da0073e9SAndroid Build Coastguard Worker         (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
1946*da0073e9SAndroid Build Coastguard Worker     {
1947*da0073e9SAndroid Build Coastguard Worker         if (pIn_buf_size)
1948*da0073e9SAndroid Build Coastguard Worker             *pIn_buf_size = 0;
1949*da0073e9SAndroid Build Coastguard Worker         if (pOut_buf_size)
1950*da0073e9SAndroid Build Coastguard Worker             *pOut_buf_size = 0;
1951*da0073e9SAndroid Build Coastguard Worker         return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
1952*da0073e9SAndroid Build Coastguard Worker     }
1953*da0073e9SAndroid Build Coastguard Worker     d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1954*da0073e9SAndroid Build Coastguard Worker 
1955*da0073e9SAndroid Build Coastguard Worker     if ((d->m_output_flush_remaining) || (d->m_finished))
1956*da0073e9SAndroid Build Coastguard Worker         return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1957*da0073e9SAndroid Build Coastguard Worker 
1958*da0073e9SAndroid Build Coastguard Worker #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1959*da0073e9SAndroid Build Coastguard Worker     if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
1960*da0073e9SAndroid Build Coastguard Worker         ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
1961*da0073e9SAndroid Build Coastguard Worker         ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
1962*da0073e9SAndroid Build Coastguard Worker     {
1963*da0073e9SAndroid Build Coastguard Worker         if (!tdefl_compress_fast(d))
1964*da0073e9SAndroid Build Coastguard Worker             return d->m_prev_return_status;
1965*da0073e9SAndroid Build Coastguard Worker     }
1966*da0073e9SAndroid Build Coastguard Worker     else
1967*da0073e9SAndroid Build Coastguard Worker #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1968*da0073e9SAndroid Build Coastguard Worker     {
1969*da0073e9SAndroid Build Coastguard Worker         if (!tdefl_compress_normal(d))
1970*da0073e9SAndroid Build Coastguard Worker             return d->m_prev_return_status;
1971*da0073e9SAndroid Build Coastguard Worker     }
1972*da0073e9SAndroid Build Coastguard Worker 
1973*da0073e9SAndroid Build Coastguard Worker     if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1974*da0073e9SAndroid Build Coastguard Worker         d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
1975*da0073e9SAndroid Build Coastguard Worker 
1976*da0073e9SAndroid Build Coastguard Worker     if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1977*da0073e9SAndroid Build Coastguard Worker     {
1978*da0073e9SAndroid Build Coastguard Worker         if (tdefl_flush_block(d, flush) < 0)
1979*da0073e9SAndroid Build Coastguard Worker             return d->m_prev_return_status;
1980*da0073e9SAndroid Build Coastguard Worker         d->m_finished = (flush == TDEFL_FINISH);
1981*da0073e9SAndroid Build Coastguard Worker         if (flush == TDEFL_FULL_FLUSH)
1982*da0073e9SAndroid Build Coastguard Worker         {
1983*da0073e9SAndroid Build Coastguard Worker             MZ_CLEAR_OBJ(d->m_hash);
1984*da0073e9SAndroid Build Coastguard Worker             MZ_CLEAR_OBJ(d->m_next);
1985*da0073e9SAndroid Build Coastguard Worker             d->m_dict_size = 0;
1986*da0073e9SAndroid Build Coastguard Worker         }
1987*da0073e9SAndroid Build Coastguard Worker     }
1988*da0073e9SAndroid Build Coastguard Worker 
1989*da0073e9SAndroid Build Coastguard Worker     return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1990*da0073e9SAndroid Build Coastguard Worker }
1991*da0073e9SAndroid Build Coastguard Worker 
tdefl_compress_buffer(tdefl_compressor * d,const void * pIn_buf,size_t in_buf_size,tdefl_flush flush)1992*da0073e9SAndroid Build Coastguard Worker tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
1993*da0073e9SAndroid Build Coastguard Worker {
1994*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT(d->m_pPut_buf_func);
1995*da0073e9SAndroid Build Coastguard Worker     return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1996*da0073e9SAndroid Build Coastguard Worker }
1997*da0073e9SAndroid Build Coastguard Worker 
tdefl_init(tdefl_compressor * d,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)1998*da0073e9SAndroid Build Coastguard Worker tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1999*da0073e9SAndroid Build Coastguard Worker {
2000*da0073e9SAndroid Build Coastguard Worker     d->m_pPut_buf_func = pPut_buf_func;
2001*da0073e9SAndroid Build Coastguard Worker     d->m_pPut_buf_user = pPut_buf_user;
2002*da0073e9SAndroid Build Coastguard Worker     d->m_flags = (mz_uint)(flags);
2003*da0073e9SAndroid Build Coastguard Worker     d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
2004*da0073e9SAndroid Build Coastguard Worker     d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
2005*da0073e9SAndroid Build Coastguard Worker     d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
2006*da0073e9SAndroid Build Coastguard Worker     if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
2007*da0073e9SAndroid Build Coastguard Worker         MZ_CLEAR_OBJ(d->m_hash);
2008*da0073e9SAndroid Build Coastguard Worker     d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
2009*da0073e9SAndroid Build Coastguard Worker     d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
2010*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
2011*da0073e9SAndroid Build Coastguard Worker     d->m_pLZ_flags = d->m_lz_code_buf;
2012*da0073e9SAndroid Build Coastguard Worker     d->m_num_flags_left = 8;
2013*da0073e9SAndroid Build Coastguard Worker     d->m_pOutput_buf = d->m_output_buf;
2014*da0073e9SAndroid Build Coastguard Worker     d->m_pOutput_buf_end = d->m_output_buf;
2015*da0073e9SAndroid Build Coastguard Worker     d->m_prev_return_status = TDEFL_STATUS_OKAY;
2016*da0073e9SAndroid Build Coastguard Worker     d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
2017*da0073e9SAndroid Build Coastguard Worker     d->m_adler32 = 1;
2018*da0073e9SAndroid Build Coastguard Worker     d->m_pIn_buf = NULL;
2019*da0073e9SAndroid Build Coastguard Worker     d->m_pOut_buf = NULL;
2020*da0073e9SAndroid Build Coastguard Worker     d->m_pIn_buf_size = NULL;
2021*da0073e9SAndroid Build Coastguard Worker     d->m_pOut_buf_size = NULL;
2022*da0073e9SAndroid Build Coastguard Worker     d->m_flush = TDEFL_NO_FLUSH;
2023*da0073e9SAndroid Build Coastguard Worker     d->m_pSrc = NULL;
2024*da0073e9SAndroid Build Coastguard Worker     d->m_src_buf_left = 0;
2025*da0073e9SAndroid Build Coastguard Worker     d->m_out_buf_ofs = 0;
2026*da0073e9SAndroid Build Coastguard Worker     if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
2027*da0073e9SAndroid Build Coastguard Worker         MZ_CLEAR_OBJ(d->m_dict);
2028*da0073e9SAndroid Build Coastguard Worker     memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
2029*da0073e9SAndroid Build Coastguard Worker     memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
2030*da0073e9SAndroid Build Coastguard Worker     return TDEFL_STATUS_OKAY;
2031*da0073e9SAndroid Build Coastguard Worker }
2032*da0073e9SAndroid Build Coastguard Worker 
tdefl_get_prev_return_status(tdefl_compressor * d)2033*da0073e9SAndroid Build Coastguard Worker tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
2034*da0073e9SAndroid Build Coastguard Worker {
2035*da0073e9SAndroid Build Coastguard Worker     return d->m_prev_return_status;
2036*da0073e9SAndroid Build Coastguard Worker }
2037*da0073e9SAndroid Build Coastguard Worker 
tdefl_get_adler32(tdefl_compressor * d)2038*da0073e9SAndroid Build Coastguard Worker mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
2039*da0073e9SAndroid Build Coastguard Worker {
2040*da0073e9SAndroid Build Coastguard Worker     return d->m_adler32;
2041*da0073e9SAndroid Build Coastguard Worker }
2042*da0073e9SAndroid Build Coastguard Worker 
tdefl_compress_mem_to_output(const void * pBuf,size_t buf_len,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)2043*da0073e9SAndroid Build Coastguard Worker mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2044*da0073e9SAndroid Build Coastguard Worker {
2045*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2046*da0073e9SAndroid Build Coastguard Worker     tdefl_compressor *pComp;
2047*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2048*da0073e9SAndroid Build Coastguard Worker     mz_bool succeeded;
2049*da0073e9SAndroid Build Coastguard Worker     if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
2050*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
2051*da0073e9SAndroid Build Coastguard Worker     pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2052*da0073e9SAndroid Build Coastguard Worker     if (!pComp)
2053*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
2054*da0073e9SAndroid Build Coastguard Worker     succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
2055*da0073e9SAndroid Build Coastguard Worker     succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
2056*da0073e9SAndroid Build Coastguard Worker     MZ_FREE(pComp);
2057*da0073e9SAndroid Build Coastguard Worker     return succeeded;
2058*da0073e9SAndroid Build Coastguard Worker }
2059*da0073e9SAndroid Build Coastguard Worker 
2060*da0073e9SAndroid Build Coastguard Worker typedef struct
2061*da0073e9SAndroid Build Coastguard Worker {
2062*da0073e9SAndroid Build Coastguard Worker     size_t m_size, m_capacity;
2063*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *m_pBuf;
2064*da0073e9SAndroid Build Coastguard Worker     mz_bool m_expandable;
2065*da0073e9SAndroid Build Coastguard Worker } tdefl_output_buffer;
2066*da0073e9SAndroid Build Coastguard Worker 
tdefl_output_buffer_putter(const void * pBuf,int len,void * pUser)2067*da0073e9SAndroid Build Coastguard Worker static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
2068*da0073e9SAndroid Build Coastguard Worker {
2069*da0073e9SAndroid Build Coastguard Worker     tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
2070*da0073e9SAndroid Build Coastguard Worker     size_t new_size = p->m_size + len;
2071*da0073e9SAndroid Build Coastguard Worker     if (new_size > p->m_capacity)
2072*da0073e9SAndroid Build Coastguard Worker     {
2073*da0073e9SAndroid Build Coastguard Worker         size_t new_capacity = p->m_capacity;
2074*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2075*da0073e9SAndroid Build Coastguard Worker         mz_uint8 *pNew_buf;
2076*da0073e9SAndroid Build Coastguard Worker         if (!p->m_expandable)
2077*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
2078*da0073e9SAndroid Build Coastguard Worker         do
2079*da0073e9SAndroid Build Coastguard Worker         {
2080*da0073e9SAndroid Build Coastguard Worker             new_capacity = MZ_MAX(128U, new_capacity << 1U);
2081*da0073e9SAndroid Build Coastguard Worker         } while (new_size > new_capacity);
2082*da0073e9SAndroid Build Coastguard Worker         pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
2083*da0073e9SAndroid Build Coastguard Worker         if (!pNew_buf)
2084*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
2085*da0073e9SAndroid Build Coastguard Worker         p->m_pBuf = pNew_buf;
2086*da0073e9SAndroid Build Coastguard Worker         p->m_capacity = new_capacity;
2087*da0073e9SAndroid Build Coastguard Worker     }
2088*da0073e9SAndroid Build Coastguard Worker     memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
2089*da0073e9SAndroid Build Coastguard Worker     p->m_size = new_size;
2090*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
2091*da0073e9SAndroid Build Coastguard Worker }
2092*da0073e9SAndroid Build Coastguard Worker 
tdefl_compress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)2093*da0073e9SAndroid Build Coastguard Worker void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2094*da0073e9SAndroid Build Coastguard Worker {
2095*da0073e9SAndroid Build Coastguard Worker     tdefl_output_buffer out_buf;
2096*da0073e9SAndroid Build Coastguard Worker     MZ_CLEAR_OBJ(out_buf);
2097*da0073e9SAndroid Build Coastguard Worker     if (!pOut_len)
2098*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
2099*da0073e9SAndroid Build Coastguard Worker     else
2100*da0073e9SAndroid Build Coastguard Worker         *pOut_len = 0;
2101*da0073e9SAndroid Build Coastguard Worker     out_buf.m_expandable = MZ_TRUE;
2102*da0073e9SAndroid Build Coastguard Worker     if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2103*da0073e9SAndroid Build Coastguard Worker         return NULL;
2104*da0073e9SAndroid Build Coastguard Worker     *pOut_len = out_buf.m_size;
2105*da0073e9SAndroid Build Coastguard Worker     return out_buf.m_pBuf;
2106*da0073e9SAndroid Build Coastguard Worker }
2107*da0073e9SAndroid Build Coastguard Worker 
tdefl_compress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)2108*da0073e9SAndroid Build Coastguard Worker size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2109*da0073e9SAndroid Build Coastguard Worker {
2110*da0073e9SAndroid Build Coastguard Worker     tdefl_output_buffer out_buf;
2111*da0073e9SAndroid Build Coastguard Worker     MZ_CLEAR_OBJ(out_buf);
2112*da0073e9SAndroid Build Coastguard Worker     if (!pOut_buf)
2113*da0073e9SAndroid Build Coastguard Worker         return 0;
2114*da0073e9SAndroid Build Coastguard Worker     out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
2115*da0073e9SAndroid Build Coastguard Worker     out_buf.m_capacity = out_buf_len;
2116*da0073e9SAndroid Build Coastguard Worker     if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2117*da0073e9SAndroid Build Coastguard Worker         return 0;
2118*da0073e9SAndroid Build Coastguard Worker     return out_buf.m_size;
2119*da0073e9SAndroid Build Coastguard Worker }
2120*da0073e9SAndroid Build Coastguard Worker 
2121*da0073e9SAndroid Build Coastguard Worker static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2122*da0073e9SAndroid Build Coastguard Worker 
2123*da0073e9SAndroid Build Coastguard Worker /* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */
tdefl_create_comp_flags_from_zip_params(int level,int window_bits,int strategy)2124*da0073e9SAndroid Build Coastguard Worker mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
2125*da0073e9SAndroid Build Coastguard Worker {
2126*da0073e9SAndroid Build Coastguard Worker     mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2127*da0073e9SAndroid Build Coastguard Worker     if (window_bits > 0)
2128*da0073e9SAndroid Build Coastguard Worker         comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2129*da0073e9SAndroid Build Coastguard Worker 
2130*da0073e9SAndroid Build Coastguard Worker     if (!level)
2131*da0073e9SAndroid Build Coastguard Worker         comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2132*da0073e9SAndroid Build Coastguard Worker     else if (strategy == MZ_FILTERED)
2133*da0073e9SAndroid Build Coastguard Worker         comp_flags |= TDEFL_FILTER_MATCHES;
2134*da0073e9SAndroid Build Coastguard Worker     else if (strategy == MZ_HUFFMAN_ONLY)
2135*da0073e9SAndroid Build Coastguard Worker         comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2136*da0073e9SAndroid Build Coastguard Worker     else if (strategy == MZ_FIXED)
2137*da0073e9SAndroid Build Coastguard Worker         comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2138*da0073e9SAndroid Build Coastguard Worker     else if (strategy == MZ_RLE)
2139*da0073e9SAndroid Build Coastguard Worker         comp_flags |= TDEFL_RLE_MATCHES;
2140*da0073e9SAndroid Build Coastguard Worker 
2141*da0073e9SAndroid Build Coastguard Worker     return comp_flags;
2142*da0073e9SAndroid Build Coastguard Worker }
2143*da0073e9SAndroid Build Coastguard Worker 
2144*da0073e9SAndroid Build Coastguard Worker #ifdef _MSC_VER
2145*da0073e9SAndroid Build Coastguard Worker #pragma warning(push)
2146*da0073e9SAndroid Build Coastguard Worker #pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */
2147*da0073e9SAndroid Build Coastguard Worker #endif
2148*da0073e9SAndroid Build Coastguard Worker 
2149*da0073e9SAndroid Build Coastguard Worker /* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
2150*da0073e9SAndroid Build Coastguard Worker  http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
2151*da0073e9SAndroid Build Coastguard Worker  This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */
tdefl_write_image_to_png_file_in_memory_ex(const void * pImage,int w,int h,int num_chans,size_t * pLen_out,mz_uint level,mz_bool flip)2152*da0073e9SAndroid Build Coastguard Worker void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
2153*da0073e9SAndroid Build Coastguard Worker {
2154*da0073e9SAndroid Build Coastguard Worker     /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */
2155*da0073e9SAndroid Build Coastguard Worker     static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2156*da0073e9SAndroid Build Coastguard Worker     tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2157*da0073e9SAndroid Build Coastguard Worker     tdefl_output_buffer out_buf;
2158*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2159*da0073e9SAndroid Build Coastguard Worker     int i, bpl = w * num_chans, y, z;
2160*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2161*da0073e9SAndroid Build Coastguard Worker     mz_uint32 c;
2162*da0073e9SAndroid Build Coastguard Worker     *pLen_out = 0;
2163*da0073e9SAndroid Build Coastguard Worker     if (!pComp)
2164*da0073e9SAndroid Build Coastguard Worker         return NULL;
2165*da0073e9SAndroid Build Coastguard Worker     MZ_CLEAR_OBJ(out_buf);
2166*da0073e9SAndroid Build Coastguard Worker     out_buf.m_expandable = MZ_TRUE;
2167*da0073e9SAndroid Build Coastguard Worker     out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
2168*da0073e9SAndroid Build Coastguard Worker     if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
2169*da0073e9SAndroid Build Coastguard Worker     {
2170*da0073e9SAndroid Build Coastguard Worker         MZ_FREE(pComp);
2171*da0073e9SAndroid Build Coastguard Worker         return NULL;
2172*da0073e9SAndroid Build Coastguard Worker     }
2173*da0073e9SAndroid Build Coastguard Worker     /* write dummy header */
2174*da0073e9SAndroid Build Coastguard Worker     for (z = 41; z; --z)
2175*da0073e9SAndroid Build Coastguard Worker         tdefl_output_buffer_putter(&z, 1, &out_buf);
2176*da0073e9SAndroid Build Coastguard Worker     /* compress image data */
2177*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
2178*da0073e9SAndroid Build Coastguard Worker     tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2179*da0073e9SAndroid Build Coastguard Worker     for (y = 0; y < h; ++y)
2180*da0073e9SAndroid Build Coastguard Worker     {
2181*da0073e9SAndroid Build Coastguard Worker         tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
2182*da0073e9SAndroid Build Coastguard Worker         tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
2183*da0073e9SAndroid Build Coastguard Worker     }
2184*da0073e9SAndroid Build Coastguard Worker     if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)
2185*da0073e9SAndroid Build Coastguard Worker     {
2186*da0073e9SAndroid Build Coastguard Worker         MZ_FREE(pComp);
2187*da0073e9SAndroid Build Coastguard Worker         MZ_FREE(out_buf.m_pBuf);
2188*da0073e9SAndroid Build Coastguard Worker         return NULL;
2189*da0073e9SAndroid Build Coastguard Worker     }
2190*da0073e9SAndroid Build Coastguard Worker     /* write real header */
2191*da0073e9SAndroid Build Coastguard Worker     *pLen_out = out_buf.m_size - 41;
2192*da0073e9SAndroid Build Coastguard Worker     {
2193*da0073e9SAndroid Build Coastguard Worker         static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
2194*da0073e9SAndroid Build Coastguard Worker         mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
2195*da0073e9SAndroid Build Coastguard Worker                                 0x0a, 0x1a, 0x0a, 0x00, 0x00,
2196*da0073e9SAndroid Build Coastguard Worker                                 0x00, 0x0d, 0x49, 0x48, 0x44,
2197*da0073e9SAndroid Build Coastguard Worker                                 0x52, 0x00, 0x00, 0x00, 0x00,
2198*da0073e9SAndroid Build Coastguard Worker                                 0x00, 0x00, 0x00, 0x00, 0x08,
2199*da0073e9SAndroid Build Coastguard Worker                                 0x00, 0x00, 0x00, 0x00, 0x00,
2200*da0073e9SAndroid Build Coastguard Worker                                 0x00, 0x00, 0x00, 0x00, 0x00,
2201*da0073e9SAndroid Build Coastguard Worker                                 0x00, 0x00, 0x49, 0x44, 0x41,
2202*da0073e9SAndroid Build Coastguard Worker                                 0x54 };
2203*da0073e9SAndroid Build Coastguard Worker         pnghdr[18] = (mz_uint8)(w >> 8);
2204*da0073e9SAndroid Build Coastguard Worker         pnghdr[19] = (mz_uint8)w;
2205*da0073e9SAndroid Build Coastguard Worker         pnghdr[22] = (mz_uint8)(h >> 8);
2206*da0073e9SAndroid Build Coastguard Worker         pnghdr[23] = (mz_uint8)h;
2207*da0073e9SAndroid Build Coastguard Worker         pnghdr[25] = chans[num_chans];
2208*da0073e9SAndroid Build Coastguard Worker         pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
2209*da0073e9SAndroid Build Coastguard Worker         pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
2210*da0073e9SAndroid Build Coastguard Worker         pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
2211*da0073e9SAndroid Build Coastguard Worker         pnghdr[36] = (mz_uint8)*pLen_out;
2212*da0073e9SAndroid Build Coastguard Worker         c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
2213*da0073e9SAndroid Build Coastguard Worker         for (i = 0; i < 4; ++i, c <<= 8)
2214*da0073e9SAndroid Build Coastguard Worker             ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
2215*da0073e9SAndroid Build Coastguard Worker         memcpy(out_buf.m_pBuf, pnghdr, 41);
2216*da0073e9SAndroid Build Coastguard Worker     }
2217*da0073e9SAndroid Build Coastguard Worker     /* write footer (IDAT CRC-32, followed by IEND chunk) */
2218*da0073e9SAndroid Build Coastguard Worker     if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf))
2219*da0073e9SAndroid Build Coastguard Worker     {
2220*da0073e9SAndroid Build Coastguard Worker         *pLen_out = 0;
2221*da0073e9SAndroid Build Coastguard Worker         MZ_FREE(pComp);
2222*da0073e9SAndroid Build Coastguard Worker         MZ_FREE(out_buf.m_pBuf);
2223*da0073e9SAndroid Build Coastguard Worker         return NULL;
2224*da0073e9SAndroid Build Coastguard Worker     }
2225*da0073e9SAndroid Build Coastguard Worker     c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
2226*da0073e9SAndroid Build Coastguard Worker     for (i = 0; i < 4; ++i, c <<= 8)
2227*da0073e9SAndroid Build Coastguard Worker         (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
2228*da0073e9SAndroid Build Coastguard Worker     /* compute final size of file, grab compressed data buffer and return */
2229*da0073e9SAndroid Build Coastguard Worker     *pLen_out += 57;
2230*da0073e9SAndroid Build Coastguard Worker     MZ_FREE(pComp);
2231*da0073e9SAndroid Build Coastguard Worker     return out_buf.m_pBuf;
2232*da0073e9SAndroid Build Coastguard Worker }
tdefl_write_image_to_png_file_in_memory(const void * pImage,int w,int h,int num_chans,size_t * pLen_out)2233*da0073e9SAndroid Build Coastguard Worker void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
2234*da0073e9SAndroid Build Coastguard Worker {
2235*da0073e9SAndroid Build Coastguard Worker     /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */
2236*da0073e9SAndroid Build Coastguard Worker     return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2237*da0073e9SAndroid Build Coastguard Worker }
2238*da0073e9SAndroid Build Coastguard Worker 
2239*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_MALLOC
2240*da0073e9SAndroid Build Coastguard Worker /* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */
2241*da0073e9SAndroid Build Coastguard Worker /* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
2242*da0073e9SAndroid Build Coastguard Worker /* structure size and allocation mechanism. */
tdefl_compressor_alloc(void)2243*da0073e9SAndroid Build Coastguard Worker tdefl_compressor *tdefl_compressor_alloc(void)
2244*da0073e9SAndroid Build Coastguard Worker {
2245*da0073e9SAndroid Build Coastguard Worker     return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2246*da0073e9SAndroid Build Coastguard Worker }
2247*da0073e9SAndroid Build Coastguard Worker 
tdefl_compressor_free(tdefl_compressor * pComp)2248*da0073e9SAndroid Build Coastguard Worker void tdefl_compressor_free(tdefl_compressor *pComp)
2249*da0073e9SAndroid Build Coastguard Worker {
2250*da0073e9SAndroid Build Coastguard Worker     MZ_FREE(pComp);
2251*da0073e9SAndroid Build Coastguard Worker }
2252*da0073e9SAndroid Build Coastguard Worker #endif
2253*da0073e9SAndroid Build Coastguard Worker 
2254*da0073e9SAndroid Build Coastguard Worker #ifdef _MSC_VER
2255*da0073e9SAndroid Build Coastguard Worker #pragma warning(pop)
2256*da0073e9SAndroid Build Coastguard Worker #endif
2257*da0073e9SAndroid Build Coastguard Worker 
2258*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
2259*da0073e9SAndroid Build Coastguard Worker }
2260*da0073e9SAndroid Build Coastguard Worker #endif
2261*da0073e9SAndroid Build Coastguard Worker /**************************************************************************
2262*da0073e9SAndroid Build Coastguard Worker  *
2263*da0073e9SAndroid Build Coastguard Worker  * Copyright 2013-2014 RAD Game Tools and Valve Software
2264*da0073e9SAndroid Build Coastguard Worker  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2265*da0073e9SAndroid Build Coastguard Worker  * All Rights Reserved.
2266*da0073e9SAndroid Build Coastguard Worker  *
2267*da0073e9SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
2268*da0073e9SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
2269*da0073e9SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
2270*da0073e9SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2271*da0073e9SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
2272*da0073e9SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
2273*da0073e9SAndroid Build Coastguard Worker  *
2274*da0073e9SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
2275*da0073e9SAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
2276*da0073e9SAndroid Build Coastguard Worker  *
2277*da0073e9SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2278*da0073e9SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2279*da0073e9SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2280*da0073e9SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2281*da0073e9SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2282*da0073e9SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2283*da0073e9SAndroid Build Coastguard Worker  * THE SOFTWARE.
2284*da0073e9SAndroid Build Coastguard Worker  *
2285*da0073e9SAndroid Build Coastguard Worker  **************************************************************************/
2286*da0073e9SAndroid Build Coastguard Worker 
2287*da0073e9SAndroid Build Coastguard Worker 
2288*da0073e9SAndroid Build Coastguard Worker 
2289*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
2290*da0073e9SAndroid Build Coastguard Worker extern "C" {
2291*da0073e9SAndroid Build Coastguard Worker #endif
2292*da0073e9SAndroid Build Coastguard Worker 
2293*da0073e9SAndroid Build Coastguard Worker /* ------------------- Low-level Decompression (completely independent from all compression API's) */
2294*da0073e9SAndroid Build Coastguard Worker 
2295*da0073e9SAndroid Build Coastguard Worker #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2296*da0073e9SAndroid Build Coastguard Worker #define TINFL_MEMSET(p, c, l) memset(p, c, l)
2297*da0073e9SAndroid Build Coastguard Worker 
2298*da0073e9SAndroid Build Coastguard Worker #define TINFL_CR_BEGIN  \
2299*da0073e9SAndroid Build Coastguard Worker     switch (r->m_state) \
2300*da0073e9SAndroid Build Coastguard Worker     {                   \
2301*da0073e9SAndroid Build Coastguard Worker         case 0:
2302*da0073e9SAndroid Build Coastguard Worker #define TINFL_CR_RETURN(state_index, result) \
2303*da0073e9SAndroid Build Coastguard Worker     do                                       \
2304*da0073e9SAndroid Build Coastguard Worker     {                                        \
2305*da0073e9SAndroid Build Coastguard Worker         status = result;                     \
2306*da0073e9SAndroid Build Coastguard Worker         r->m_state = state_index;            \
2307*da0073e9SAndroid Build Coastguard Worker         goto common_exit;                    \
2308*da0073e9SAndroid Build Coastguard Worker         case state_index:;                   \
2309*da0073e9SAndroid Build Coastguard Worker     }                                        \
2310*da0073e9SAndroid Build Coastguard Worker     MZ_MACRO_END
2311*da0073e9SAndroid Build Coastguard Worker #define TINFL_CR_RETURN_FOREVER(state_index, result) \
2312*da0073e9SAndroid Build Coastguard Worker     do                                               \
2313*da0073e9SAndroid Build Coastguard Worker     {                                                \
2314*da0073e9SAndroid Build Coastguard Worker         for (;;)                                     \
2315*da0073e9SAndroid Build Coastguard Worker         {                                            \
2316*da0073e9SAndroid Build Coastguard Worker             TINFL_CR_RETURN(state_index, result);    \
2317*da0073e9SAndroid Build Coastguard Worker         }                                            \
2318*da0073e9SAndroid Build Coastguard Worker     }                                                \
2319*da0073e9SAndroid Build Coastguard Worker     MZ_MACRO_END
2320*da0073e9SAndroid Build Coastguard Worker #define TINFL_CR_FINISH }
2321*da0073e9SAndroid Build Coastguard Worker 
2322*da0073e9SAndroid Build Coastguard Worker #define TINFL_GET_BYTE(state_index, c)                                                                                                                           \
2323*da0073e9SAndroid Build Coastguard Worker     do                                                                                                                                                           \
2324*da0073e9SAndroid Build Coastguard Worker     {                                                                                                                                                            \
2325*da0073e9SAndroid Build Coastguard Worker         while (pIn_buf_cur >= pIn_buf_end)                                                                                                                       \
2326*da0073e9SAndroid Build Coastguard Worker         {                                                                                                                                                        \
2327*da0073e9SAndroid Build Coastguard Worker             TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
2328*da0073e9SAndroid Build Coastguard Worker         }                                                                                                                                                        \
2329*da0073e9SAndroid Build Coastguard Worker         c = *pIn_buf_cur++;                                                                                                                                      \
2330*da0073e9SAndroid Build Coastguard Worker     }                                                                                                                                                            \
2331*da0073e9SAndroid Build Coastguard Worker     MZ_MACRO_END
2332*da0073e9SAndroid Build Coastguard Worker 
2333*da0073e9SAndroid Build Coastguard Worker #define TINFL_NEED_BITS(state_index, n)                \
2334*da0073e9SAndroid Build Coastguard Worker     do                                                 \
2335*da0073e9SAndroid Build Coastguard Worker     {                                                  \
2336*da0073e9SAndroid Build Coastguard Worker         mz_uint c;                                     \
2337*da0073e9SAndroid Build Coastguard Worker         TINFL_GET_BYTE(state_index, c);                \
2338*da0073e9SAndroid Build Coastguard Worker         bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2339*da0073e9SAndroid Build Coastguard Worker         num_bits += 8;                                 \
2340*da0073e9SAndroid Build Coastguard Worker     } while (num_bits < (mz_uint)(n))
2341*da0073e9SAndroid Build Coastguard Worker #define TINFL_SKIP_BITS(state_index, n)      \
2342*da0073e9SAndroid Build Coastguard Worker     do                                       \
2343*da0073e9SAndroid Build Coastguard Worker     {                                        \
2344*da0073e9SAndroid Build Coastguard Worker         if (num_bits < (mz_uint)(n))         \
2345*da0073e9SAndroid Build Coastguard Worker         {                                    \
2346*da0073e9SAndroid Build Coastguard Worker             TINFL_NEED_BITS(state_index, n); \
2347*da0073e9SAndroid Build Coastguard Worker         }                                    \
2348*da0073e9SAndroid Build Coastguard Worker         bit_buf >>= (n);                     \
2349*da0073e9SAndroid Build Coastguard Worker         num_bits -= (n);                     \
2350*da0073e9SAndroid Build Coastguard Worker     }                                        \
2351*da0073e9SAndroid Build Coastguard Worker     MZ_MACRO_END
2352*da0073e9SAndroid Build Coastguard Worker #define TINFL_GET_BITS(state_index, b, n)    \
2353*da0073e9SAndroid Build Coastguard Worker     do                                       \
2354*da0073e9SAndroid Build Coastguard Worker     {                                        \
2355*da0073e9SAndroid Build Coastguard Worker         if (num_bits < (mz_uint)(n))         \
2356*da0073e9SAndroid Build Coastguard Worker         {                                    \
2357*da0073e9SAndroid Build Coastguard Worker             TINFL_NEED_BITS(state_index, n); \
2358*da0073e9SAndroid Build Coastguard Worker         }                                    \
2359*da0073e9SAndroid Build Coastguard Worker         b = bit_buf & ((1 << (n)) - 1);      \
2360*da0073e9SAndroid Build Coastguard Worker         bit_buf >>= (n);                     \
2361*da0073e9SAndroid Build Coastguard Worker         num_bits -= (n);                     \
2362*da0073e9SAndroid Build Coastguard Worker     }                                        \
2363*da0073e9SAndroid Build Coastguard Worker     MZ_MACRO_END
2364*da0073e9SAndroid Build Coastguard Worker 
2365*da0073e9SAndroid Build Coastguard Worker /* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
2366*da0073e9SAndroid Build Coastguard Worker /* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */
2367*da0073e9SAndroid Build Coastguard Worker /* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */
2368*da0073e9SAndroid Build Coastguard Worker /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
2369*da0073e9SAndroid Build Coastguard Worker #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                             \
2370*da0073e9SAndroid Build Coastguard Worker     do                                                                         \
2371*da0073e9SAndroid Build Coastguard Worker     {                                                                          \
2372*da0073e9SAndroid Build Coastguard Worker         temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];     \
2373*da0073e9SAndroid Build Coastguard Worker         if (temp >= 0)                                                         \
2374*da0073e9SAndroid Build Coastguard Worker         {                                                                      \
2375*da0073e9SAndroid Build Coastguard Worker             code_len = temp >> 9;                                              \
2376*da0073e9SAndroid Build Coastguard Worker             if ((code_len) && (num_bits >= code_len))                          \
2377*da0073e9SAndroid Build Coastguard Worker                 break;                                                         \
2378*da0073e9SAndroid Build Coastguard Worker         }                                                                      \
2379*da0073e9SAndroid Build Coastguard Worker         else if (num_bits > TINFL_FAST_LOOKUP_BITS)                            \
2380*da0073e9SAndroid Build Coastguard Worker         {                                                                      \
2381*da0073e9SAndroid Build Coastguard Worker             code_len = TINFL_FAST_LOOKUP_BITS;                                 \
2382*da0073e9SAndroid Build Coastguard Worker             do                                                                 \
2383*da0073e9SAndroid Build Coastguard Worker             {                                                                  \
2384*da0073e9SAndroid Build Coastguard Worker                 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2385*da0073e9SAndroid Build Coastguard Worker             } while ((temp < 0) && (num_bits >= (code_len + 1)));              \
2386*da0073e9SAndroid Build Coastguard Worker             if (temp >= 0)                                                     \
2387*da0073e9SAndroid Build Coastguard Worker                 break;                                                         \
2388*da0073e9SAndroid Build Coastguard Worker         }                                                                      \
2389*da0073e9SAndroid Build Coastguard Worker         TINFL_GET_BYTE(state_index, c);                                        \
2390*da0073e9SAndroid Build Coastguard Worker         bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                         \
2391*da0073e9SAndroid Build Coastguard Worker         num_bits += 8;                                                         \
2392*da0073e9SAndroid Build Coastguard Worker     } while (num_bits < 15);
2393*da0073e9SAndroid Build Coastguard Worker 
2394*da0073e9SAndroid Build Coastguard Worker /* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */
2395*da0073e9SAndroid Build Coastguard Worker /* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */
2396*da0073e9SAndroid Build Coastguard Worker /* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */
2397*da0073e9SAndroid Build Coastguard Worker /* The slow path is only executed at the very end of the input buffer. */
2398*da0073e9SAndroid Build Coastguard Worker /* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */
2399*da0073e9SAndroid Build Coastguard Worker /* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
2400*da0073e9SAndroid Build Coastguard Worker #define TINFL_HUFF_DECODE(state_index, sym, pHuff)                                                                                  \
2401*da0073e9SAndroid Build Coastguard Worker     do                                                                                                                              \
2402*da0073e9SAndroid Build Coastguard Worker     {                                                                                                                               \
2403*da0073e9SAndroid Build Coastguard Worker         int temp;                                                                                                                   \
2404*da0073e9SAndroid Build Coastguard Worker         mz_uint code_len, c;                                                                                                        \
2405*da0073e9SAndroid Build Coastguard Worker         if (num_bits < 15)                                                                                                          \
2406*da0073e9SAndroid Build Coastguard Worker         {                                                                                                                           \
2407*da0073e9SAndroid Build Coastguard Worker             if ((pIn_buf_end - pIn_buf_cur) < 2)                                                                                    \
2408*da0073e9SAndroid Build Coastguard Worker             {                                                                                                                       \
2409*da0073e9SAndroid Build Coastguard Worker                 TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                                                                         \
2410*da0073e9SAndroid Build Coastguard Worker             }                                                                                                                       \
2411*da0073e9SAndroid Build Coastguard Worker             else                                                                                                                    \
2412*da0073e9SAndroid Build Coastguard Worker             {                                                                                                                       \
2413*da0073e9SAndroid Build Coastguard Worker                 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
2414*da0073e9SAndroid Build Coastguard Worker                 pIn_buf_cur += 2;                                                                                                   \
2415*da0073e9SAndroid Build Coastguard Worker                 num_bits += 16;                                                                                                     \
2416*da0073e9SAndroid Build Coastguard Worker             }                                                                                                                       \
2417*da0073e9SAndroid Build Coastguard Worker         }                                                                                                                           \
2418*da0073e9SAndroid Build Coastguard Worker         if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)                                               \
2419*da0073e9SAndroid Build Coastguard Worker             code_len = temp >> 9, temp &= 511;                                                                                      \
2420*da0073e9SAndroid Build Coastguard Worker         else                                                                                                                        \
2421*da0073e9SAndroid Build Coastguard Worker         {                                                                                                                           \
2422*da0073e9SAndroid Build Coastguard Worker             code_len = TINFL_FAST_LOOKUP_BITS;                                                                                      \
2423*da0073e9SAndroid Build Coastguard Worker             do                                                                                                                      \
2424*da0073e9SAndroid Build Coastguard Worker             {                                                                                                                       \
2425*da0073e9SAndroid Build Coastguard Worker                 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];                                                      \
2426*da0073e9SAndroid Build Coastguard Worker             } while (temp < 0);                                                                                                     \
2427*da0073e9SAndroid Build Coastguard Worker         }                                                                                                                           \
2428*da0073e9SAndroid Build Coastguard Worker         sym = temp;                                                                                                                 \
2429*da0073e9SAndroid Build Coastguard Worker         bit_buf >>= code_len;                                                                                                       \
2430*da0073e9SAndroid Build Coastguard Worker         num_bits -= code_len;                                                                                                       \
2431*da0073e9SAndroid Build Coastguard Worker     }                                                                                                                               \
2432*da0073e9SAndroid Build Coastguard Worker     MZ_MACRO_END
2433*da0073e9SAndroid Build Coastguard Worker 
tinfl_decompress(tinfl_decompressor * r,const mz_uint8 * pIn_buf_next,size_t * pIn_buf_size,mz_uint8 * pOut_buf_start,mz_uint8 * pOut_buf_next,size_t * pOut_buf_size,const mz_uint32 decomp_flags)2434*da0073e9SAndroid Build Coastguard Worker tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
2435*da0073e9SAndroid Build Coastguard Worker {
2436*da0073e9SAndroid Build Coastguard Worker     static const int s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };
2437*da0073e9SAndroid Build Coastguard Worker     static const int s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };
2438*da0073e9SAndroid Build Coastguard Worker     static const int s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };
2439*da0073e9SAndroid Build Coastguard Worker     static const int s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
2440*da0073e9SAndroid Build Coastguard Worker     static const mz_uint8 s_length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
2441*da0073e9SAndroid Build Coastguard Worker     static const int s_min_table_sizes[3] = { 257, 1, 4 };
2442*da0073e9SAndroid Build Coastguard Worker 
2443*da0073e9SAndroid Build Coastguard Worker     tinfl_status status = TINFL_STATUS_FAILED;
2444*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2445*da0073e9SAndroid Build Coastguard Worker     mz_uint32 num_bits, dist, counter, num_extra;
2446*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2447*da0073e9SAndroid Build Coastguard Worker     tinfl_bit_buf_t bit_buf;
2448*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
2449*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
2450*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2451*da0073e9SAndroid Build Coastguard Worker     size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
2452*da0073e9SAndroid Build Coastguard Worker 
2453*da0073e9SAndroid Build Coastguard Worker     /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */
2454*da0073e9SAndroid Build Coastguard Worker     if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
2455*da0073e9SAndroid Build Coastguard Worker     {
2456*da0073e9SAndroid Build Coastguard Worker         *pIn_buf_size = *pOut_buf_size = 0;
2457*da0073e9SAndroid Build Coastguard Worker         return TINFL_STATUS_BAD_PARAM;
2458*da0073e9SAndroid Build Coastguard Worker     }
2459*da0073e9SAndroid Build Coastguard Worker 
2460*da0073e9SAndroid Build Coastguard Worker     num_bits = r->m_num_bits;
2461*da0073e9SAndroid Build Coastguard Worker     bit_buf = r->m_bit_buf;
2462*da0073e9SAndroid Build Coastguard Worker     dist = r->m_dist;
2463*da0073e9SAndroid Build Coastguard Worker     counter = r->m_counter;
2464*da0073e9SAndroid Build Coastguard Worker     num_extra = r->m_num_extra;
2465*da0073e9SAndroid Build Coastguard Worker     dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2466*da0073e9SAndroid Build Coastguard Worker     TINFL_CR_BEGIN
2467*da0073e9SAndroid Build Coastguard Worker 
2468*da0073e9SAndroid Build Coastguard Worker     bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2469*da0073e9SAndroid Build Coastguard Worker     r->m_z_adler32 = r->m_check_adler32 = 1;
2470*da0073e9SAndroid Build Coastguard Worker     if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2471*da0073e9SAndroid Build Coastguard Worker     {
2472*da0073e9SAndroid Build Coastguard Worker         TINFL_GET_BYTE(1, r->m_zhdr0);
2473*da0073e9SAndroid Build Coastguard Worker         TINFL_GET_BYTE(2, r->m_zhdr1);
2474*da0073e9SAndroid Build Coastguard Worker         counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2475*da0073e9SAndroid Build Coastguard Worker         if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2476*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(bugprone-misplaced-widening-cast,cppcoreguidelines-avoid-magic-numbers)
2477*da0073e9SAndroid Build Coastguard Worker             counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
2478*da0073e9SAndroid Build Coastguard Worker         if (counter)
2479*da0073e9SAndroid Build Coastguard Worker         {
2480*da0073e9SAndroid Build Coastguard Worker             TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2481*da0073e9SAndroid Build Coastguard Worker         }
2482*da0073e9SAndroid Build Coastguard Worker     }
2483*da0073e9SAndroid Build Coastguard Worker 
2484*da0073e9SAndroid Build Coastguard Worker     do
2485*da0073e9SAndroid Build Coastguard Worker     {
2486*da0073e9SAndroid Build Coastguard Worker         TINFL_GET_BITS(3, r->m_final, 3);
2487*da0073e9SAndroid Build Coastguard Worker         r->m_type = r->m_final >> 1;
2488*da0073e9SAndroid Build Coastguard Worker         if (r->m_type == 0)
2489*da0073e9SAndroid Build Coastguard Worker         {
2490*da0073e9SAndroid Build Coastguard Worker             TINFL_SKIP_BITS(5, num_bits & 7);
2491*da0073e9SAndroid Build Coastguard Worker             for (counter = 0; counter < 4; ++counter)
2492*da0073e9SAndroid Build Coastguard Worker             {
2493*da0073e9SAndroid Build Coastguard Worker                 if (num_bits)
2494*da0073e9SAndroid Build Coastguard Worker                     TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2495*da0073e9SAndroid Build Coastguard Worker                 else
2496*da0073e9SAndroid Build Coastguard Worker                     TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2497*da0073e9SAndroid Build Coastguard Worker             }
2498*da0073e9SAndroid Build Coastguard Worker             if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8))))
2499*da0073e9SAndroid Build Coastguard Worker             {
2500*da0073e9SAndroid Build Coastguard Worker                 TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2501*da0073e9SAndroid Build Coastguard Worker             }
2502*da0073e9SAndroid Build Coastguard Worker             while ((counter) && (num_bits))
2503*da0073e9SAndroid Build Coastguard Worker             {
2504*da0073e9SAndroid Build Coastguard Worker                 TINFL_GET_BITS(51, dist, 8);
2505*da0073e9SAndroid Build Coastguard Worker                 while (pOut_buf_cur >= pOut_buf_end)
2506*da0073e9SAndroid Build Coastguard Worker                 {
2507*da0073e9SAndroid Build Coastguard Worker                     TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2508*da0073e9SAndroid Build Coastguard Worker                 }
2509*da0073e9SAndroid Build Coastguard Worker                 *pOut_buf_cur++ = (mz_uint8)dist;
2510*da0073e9SAndroid Build Coastguard Worker                 counter--;
2511*da0073e9SAndroid Build Coastguard Worker             }
2512*da0073e9SAndroid Build Coastguard Worker             while (counter)
2513*da0073e9SAndroid Build Coastguard Worker             {
2514*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2515*da0073e9SAndroid Build Coastguard Worker                 size_t n;
2516*da0073e9SAndroid Build Coastguard Worker                 while (pOut_buf_cur >= pOut_buf_end)
2517*da0073e9SAndroid Build Coastguard Worker                 {
2518*da0073e9SAndroid Build Coastguard Worker                     TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2519*da0073e9SAndroid Build Coastguard Worker                 }
2520*da0073e9SAndroid Build Coastguard Worker                 while (pIn_buf_cur >= pIn_buf_end)
2521*da0073e9SAndroid Build Coastguard Worker                 {
2522*da0073e9SAndroid Build Coastguard Worker                     TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
2523*da0073e9SAndroid Build Coastguard Worker                 }
2524*da0073e9SAndroid Build Coastguard Worker                 n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
2525*da0073e9SAndroid Build Coastguard Worker                 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2526*da0073e9SAndroid Build Coastguard Worker                 pIn_buf_cur += n;
2527*da0073e9SAndroid Build Coastguard Worker                 pOut_buf_cur += n;
2528*da0073e9SAndroid Build Coastguard Worker                 counter -= (mz_uint)n;
2529*da0073e9SAndroid Build Coastguard Worker             }
2530*da0073e9SAndroid Build Coastguard Worker         }
2531*da0073e9SAndroid Build Coastguard Worker         else if (r->m_type == 3)
2532*da0073e9SAndroid Build Coastguard Worker         {
2533*da0073e9SAndroid Build Coastguard Worker             TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2534*da0073e9SAndroid Build Coastguard Worker         }
2535*da0073e9SAndroid Build Coastguard Worker         else
2536*da0073e9SAndroid Build Coastguard Worker         {
2537*da0073e9SAndroid Build Coastguard Worker             if (r->m_type == 1)
2538*da0073e9SAndroid Build Coastguard Worker             {
2539*da0073e9SAndroid Build Coastguard Worker                 mz_uint8 *p = r->m_tables[0].m_code_size;
2540*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2541*da0073e9SAndroid Build Coastguard Worker                 mz_uint i;
2542*da0073e9SAndroid Build Coastguard Worker                 r->m_table_sizes[0] = 288;
2543*da0073e9SAndroid Build Coastguard Worker                 r->m_table_sizes[1] = 32;
2544*da0073e9SAndroid Build Coastguard Worker                 TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2545*da0073e9SAndroid Build Coastguard Worker                 for (i = 0; i <= 143; ++i)
2546*da0073e9SAndroid Build Coastguard Worker                     *p++ = 8;
2547*da0073e9SAndroid Build Coastguard Worker                 for (; i <= 255; ++i)
2548*da0073e9SAndroid Build Coastguard Worker                     *p++ = 9;
2549*da0073e9SAndroid Build Coastguard Worker                 for (; i <= 279; ++i)
2550*da0073e9SAndroid Build Coastguard Worker                     *p++ = 7;
2551*da0073e9SAndroid Build Coastguard Worker                 for (; i <= 287; ++i)
2552*da0073e9SAndroid Build Coastguard Worker                     *p++ = 8;
2553*da0073e9SAndroid Build Coastguard Worker             }
2554*da0073e9SAndroid Build Coastguard Worker             else
2555*da0073e9SAndroid Build Coastguard Worker             {
2556*da0073e9SAndroid Build Coastguard Worker                 for (counter = 0; counter < 3; counter++)
2557*da0073e9SAndroid Build Coastguard Worker                 {
2558*da0073e9SAndroid Build Coastguard Worker                     TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2559*da0073e9SAndroid Build Coastguard Worker                     r->m_table_sizes[counter] += s_min_table_sizes[counter];
2560*da0073e9SAndroid Build Coastguard Worker                 }
2561*da0073e9SAndroid Build Coastguard Worker                 MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2562*da0073e9SAndroid Build Coastguard Worker                 for (counter = 0; counter < r->m_table_sizes[2]; counter++)
2563*da0073e9SAndroid Build Coastguard Worker                 {
2564*da0073e9SAndroid Build Coastguard Worker                     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2565*da0073e9SAndroid Build Coastguard Worker                     mz_uint s;
2566*da0073e9SAndroid Build Coastguard Worker                     TINFL_GET_BITS(14, s, 3);
2567*da0073e9SAndroid Build Coastguard Worker                     r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2568*da0073e9SAndroid Build Coastguard Worker                 }
2569*da0073e9SAndroid Build Coastguard Worker                 r->m_table_sizes[2] = 19;
2570*da0073e9SAndroid Build Coastguard Worker             }
2571*da0073e9SAndroid Build Coastguard Worker             for (; (int)r->m_type >= 0; r->m_type--)
2572*da0073e9SAndroid Build Coastguard Worker             {
2573*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2574*da0073e9SAndroid Build Coastguard Worker                 int tree_next, tree_cur;
2575*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2576*da0073e9SAndroid Build Coastguard Worker                 tinfl_huff_table *pTable;
2577*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,cppcoreguidelines-init-variables)
2578*da0073e9SAndroid Build Coastguard Worker                 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
2579*da0073e9SAndroid Build Coastguard Worker                 pTable = &r->m_tables[r->m_type];
2580*da0073e9SAndroid Build Coastguard Worker                 MZ_CLEAR_OBJ(total_syms);
2581*da0073e9SAndroid Build Coastguard Worker                 MZ_CLEAR_OBJ(pTable->m_look_up);
2582*da0073e9SAndroid Build Coastguard Worker                 MZ_CLEAR_OBJ(pTable->m_tree);
2583*da0073e9SAndroid Build Coastguard Worker                 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2584*da0073e9SAndroid Build Coastguard Worker                     total_syms[pTable->m_code_size[i]]++;
2585*da0073e9SAndroid Build Coastguard Worker                 used_syms = 0, total = 0;
2586*da0073e9SAndroid Build Coastguard Worker                 next_code[0] = next_code[1] = 0;
2587*da0073e9SAndroid Build Coastguard Worker                 for (i = 1; i <= 15; ++i)
2588*da0073e9SAndroid Build Coastguard Worker                 {
2589*da0073e9SAndroid Build Coastguard Worker                     used_syms += total_syms[i];
2590*da0073e9SAndroid Build Coastguard Worker                     next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2591*da0073e9SAndroid Build Coastguard Worker                 }
2592*da0073e9SAndroid Build Coastguard Worker                 if ((65536 != total) && (used_syms > 1))
2593*da0073e9SAndroid Build Coastguard Worker                 {
2594*da0073e9SAndroid Build Coastguard Worker                     TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2595*da0073e9SAndroid Build Coastguard Worker                 }
2596*da0073e9SAndroid Build Coastguard Worker                 for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
2597*da0073e9SAndroid Build Coastguard Worker                 {
2598*da0073e9SAndroid Build Coastguard Worker                     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2599*da0073e9SAndroid Build Coastguard Worker                     mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
2600*da0073e9SAndroid Build Coastguard Worker                     if (!code_size)
2601*da0073e9SAndroid Build Coastguard Worker                         continue;
2602*da0073e9SAndroid Build Coastguard Worker                     cur_code = next_code[code_size]++;
2603*da0073e9SAndroid Build Coastguard Worker                     for (l = code_size; l > 0; l--, cur_code >>= 1)
2604*da0073e9SAndroid Build Coastguard Worker                         rev_code = (rev_code << 1) | (cur_code & 1);
2605*da0073e9SAndroid Build Coastguard Worker                     if (code_size <= TINFL_FAST_LOOKUP_BITS)
2606*da0073e9SAndroid Build Coastguard Worker                     {
2607*da0073e9SAndroid Build Coastguard Worker                         mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2608*da0073e9SAndroid Build Coastguard Worker                         while (rev_code < TINFL_FAST_LOOKUP_SIZE)
2609*da0073e9SAndroid Build Coastguard Worker                         {
2610*da0073e9SAndroid Build Coastguard Worker                             pTable->m_look_up[rev_code] = k;
2611*da0073e9SAndroid Build Coastguard Worker                             rev_code += (1 << code_size);
2612*da0073e9SAndroid Build Coastguard Worker                         }
2613*da0073e9SAndroid Build Coastguard Worker                         continue;
2614*da0073e9SAndroid Build Coastguard Worker                     }
2615*da0073e9SAndroid Build Coastguard Worker                     if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
2616*da0073e9SAndroid Build Coastguard Worker                     {
2617*da0073e9SAndroid Build Coastguard Worker                         pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
2618*da0073e9SAndroid Build Coastguard Worker                         tree_cur = tree_next;
2619*da0073e9SAndroid Build Coastguard Worker                         tree_next -= 2;
2620*da0073e9SAndroid Build Coastguard Worker                     }
2621*da0073e9SAndroid Build Coastguard Worker                     rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2622*da0073e9SAndroid Build Coastguard Worker                     for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
2623*da0073e9SAndroid Build Coastguard Worker                     {
2624*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
2625*da0073e9SAndroid Build Coastguard Worker                         tree_cur -= ((rev_code >>= 1) & 1);
2626*da0073e9SAndroid Build Coastguard Worker                         if (!pTable->m_tree[-tree_cur - 1])
2627*da0073e9SAndroid Build Coastguard Worker                         {
2628*da0073e9SAndroid Build Coastguard Worker                             pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2629*da0073e9SAndroid Build Coastguard Worker                             tree_cur = tree_next;
2630*da0073e9SAndroid Build Coastguard Worker                             tree_next -= 2;
2631*da0073e9SAndroid Build Coastguard Worker                         }
2632*da0073e9SAndroid Build Coastguard Worker                         else
2633*da0073e9SAndroid Build Coastguard Worker                             tree_cur = pTable->m_tree[-tree_cur - 1];
2634*da0073e9SAndroid Build Coastguard Worker                     }
2635*da0073e9SAndroid Build Coastguard Worker                     // NOLINTNEXTLINE(bugprone-narrowing-conversions,clang-analyzer-deadcode.DeadStores,cppcoreguidelines-narrowing-conversions)
2636*da0073e9SAndroid Build Coastguard Worker                     tree_cur -= ((rev_code >>= 1) & 1);
2637*da0073e9SAndroid Build Coastguard Worker                     pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2638*da0073e9SAndroid Build Coastguard Worker                 }
2639*da0073e9SAndroid Build Coastguard Worker                 if (r->m_type == 2)
2640*da0073e9SAndroid Build Coastguard Worker                 {
2641*da0073e9SAndroid Build Coastguard Worker                     for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
2642*da0073e9SAndroid Build Coastguard Worker                     {
2643*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2644*da0073e9SAndroid Build Coastguard Worker                         mz_uint s;
2645*da0073e9SAndroid Build Coastguard Worker                         TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2646*da0073e9SAndroid Build Coastguard Worker                         if (dist < 16)
2647*da0073e9SAndroid Build Coastguard Worker                         {
2648*da0073e9SAndroid Build Coastguard Worker                             r->m_len_codes[counter++] = (mz_uint8)dist;
2649*da0073e9SAndroid Build Coastguard Worker                             continue;
2650*da0073e9SAndroid Build Coastguard Worker                         }
2651*da0073e9SAndroid Build Coastguard Worker                         if ((dist == 16) && (!counter))
2652*da0073e9SAndroid Build Coastguard Worker                         {
2653*da0073e9SAndroid Build Coastguard Worker                             TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2654*da0073e9SAndroid Build Coastguard Worker                         }
2655*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,bugprone-signed-char-misuse)
2656*da0073e9SAndroid Build Coastguard Worker                         num_extra = "\02\03\07"[dist - 16];
2657*da0073e9SAndroid Build Coastguard Worker                         TINFL_GET_BITS(18, s, num_extra);
2658*da0073e9SAndroid Build Coastguard Worker                         s += "\03\03\013"[dist - 16];
2659*da0073e9SAndroid Build Coastguard Worker                         TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2660*da0073e9SAndroid Build Coastguard Worker                         counter += s;
2661*da0073e9SAndroid Build Coastguard Worker                     }
2662*da0073e9SAndroid Build Coastguard Worker                     if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
2663*da0073e9SAndroid Build Coastguard Worker                     {
2664*da0073e9SAndroid Build Coastguard Worker                         TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2665*da0073e9SAndroid Build Coastguard Worker                     }
2666*da0073e9SAndroid Build Coastguard Worker                     TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
2667*da0073e9SAndroid Build Coastguard Worker                     TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
2668*da0073e9SAndroid Build Coastguard Worker                 }
2669*da0073e9SAndroid Build Coastguard Worker             }
2670*da0073e9SAndroid Build Coastguard Worker             for (;;)
2671*da0073e9SAndroid Build Coastguard Worker             {
2672*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2673*da0073e9SAndroid Build Coastguard Worker                 mz_uint8 *pSrc;
2674*da0073e9SAndroid Build Coastguard Worker                 for (;;)
2675*da0073e9SAndroid Build Coastguard Worker                 {
2676*da0073e9SAndroid Build Coastguard Worker                     if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
2677*da0073e9SAndroid Build Coastguard Worker                     {
2678*da0073e9SAndroid Build Coastguard Worker                         TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2679*da0073e9SAndroid Build Coastguard Worker                         if (counter >= 256)
2680*da0073e9SAndroid Build Coastguard Worker                             break;
2681*da0073e9SAndroid Build Coastguard Worker                         while (pOut_buf_cur >= pOut_buf_end)
2682*da0073e9SAndroid Build Coastguard Worker                         {
2683*da0073e9SAndroid Build Coastguard Worker                             TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2684*da0073e9SAndroid Build Coastguard Worker                         }
2685*da0073e9SAndroid Build Coastguard Worker                         *pOut_buf_cur++ = (mz_uint8)counter;
2686*da0073e9SAndroid Build Coastguard Worker                     }
2687*da0073e9SAndroid Build Coastguard Worker                     else
2688*da0073e9SAndroid Build Coastguard Worker                     {
2689*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2690*da0073e9SAndroid Build Coastguard Worker                         int sym2;
2691*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2692*da0073e9SAndroid Build Coastguard Worker                         mz_uint code_len;
2693*da0073e9SAndroid Build Coastguard Worker #if TINFL_USE_64BIT_BITBUF
2694*da0073e9SAndroid Build Coastguard Worker                         if (num_bits < 30)
2695*da0073e9SAndroid Build Coastguard Worker                         {
2696*da0073e9SAndroid Build Coastguard Worker                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2697*da0073e9SAndroid Build Coastguard Worker                             pIn_buf_cur += 4;
2698*da0073e9SAndroid Build Coastguard Worker                             num_bits += 32;
2699*da0073e9SAndroid Build Coastguard Worker                         }
2700*da0073e9SAndroid Build Coastguard Worker #else
2701*da0073e9SAndroid Build Coastguard Worker                         if (num_bits < 15)
2702*da0073e9SAndroid Build Coastguard Worker                         {
2703*da0073e9SAndroid Build Coastguard Worker                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2704*da0073e9SAndroid Build Coastguard Worker                             pIn_buf_cur += 2;
2705*da0073e9SAndroid Build Coastguard Worker                             num_bits += 16;
2706*da0073e9SAndroid Build Coastguard Worker                         }
2707*da0073e9SAndroid Build Coastguard Worker #endif
2708*da0073e9SAndroid Build Coastguard Worker                         if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2709*da0073e9SAndroid Build Coastguard Worker                             code_len = sym2 >> 9;
2710*da0073e9SAndroid Build Coastguard Worker                         else
2711*da0073e9SAndroid Build Coastguard Worker                         {
2712*da0073e9SAndroid Build Coastguard Worker                             code_len = TINFL_FAST_LOOKUP_BITS;
2713*da0073e9SAndroid Build Coastguard Worker                             do
2714*da0073e9SAndroid Build Coastguard Worker                             {
2715*da0073e9SAndroid Build Coastguard Worker                                 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2716*da0073e9SAndroid Build Coastguard Worker                             } while (sym2 < 0);
2717*da0073e9SAndroid Build Coastguard Worker                         }
2718*da0073e9SAndroid Build Coastguard Worker                         counter = sym2;
2719*da0073e9SAndroid Build Coastguard Worker                         bit_buf >>= code_len;
2720*da0073e9SAndroid Build Coastguard Worker                         num_bits -= code_len;
2721*da0073e9SAndroid Build Coastguard Worker                         if (counter & 256)
2722*da0073e9SAndroid Build Coastguard Worker                             break;
2723*da0073e9SAndroid Build Coastguard Worker 
2724*da0073e9SAndroid Build Coastguard Worker #if !TINFL_USE_64BIT_BITBUF
2725*da0073e9SAndroid Build Coastguard Worker                         if (num_bits < 15)
2726*da0073e9SAndroid Build Coastguard Worker                         {
2727*da0073e9SAndroid Build Coastguard Worker                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2728*da0073e9SAndroid Build Coastguard Worker                             pIn_buf_cur += 2;
2729*da0073e9SAndroid Build Coastguard Worker                             num_bits += 16;
2730*da0073e9SAndroid Build Coastguard Worker                         }
2731*da0073e9SAndroid Build Coastguard Worker #endif
2732*da0073e9SAndroid Build Coastguard Worker                         if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2733*da0073e9SAndroid Build Coastguard Worker                             code_len = sym2 >> 9;
2734*da0073e9SAndroid Build Coastguard Worker                         else
2735*da0073e9SAndroid Build Coastguard Worker                         {
2736*da0073e9SAndroid Build Coastguard Worker                             code_len = TINFL_FAST_LOOKUP_BITS;
2737*da0073e9SAndroid Build Coastguard Worker                             do
2738*da0073e9SAndroid Build Coastguard Worker                             {
2739*da0073e9SAndroid Build Coastguard Worker                                 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2740*da0073e9SAndroid Build Coastguard Worker                             } while (sym2 < 0);
2741*da0073e9SAndroid Build Coastguard Worker                         }
2742*da0073e9SAndroid Build Coastguard Worker                         bit_buf >>= code_len;
2743*da0073e9SAndroid Build Coastguard Worker                         num_bits -= code_len;
2744*da0073e9SAndroid Build Coastguard Worker 
2745*da0073e9SAndroid Build Coastguard Worker                         pOut_buf_cur[0] = (mz_uint8)counter;
2746*da0073e9SAndroid Build Coastguard Worker                         if (sym2 & 256)
2747*da0073e9SAndroid Build Coastguard Worker                         {
2748*da0073e9SAndroid Build Coastguard Worker                             pOut_buf_cur++;
2749*da0073e9SAndroid Build Coastguard Worker                             counter = sym2;
2750*da0073e9SAndroid Build Coastguard Worker                             break;
2751*da0073e9SAndroid Build Coastguard Worker                         }
2752*da0073e9SAndroid Build Coastguard Worker                         pOut_buf_cur[1] = (mz_uint8)sym2;
2753*da0073e9SAndroid Build Coastguard Worker                         pOut_buf_cur += 2;
2754*da0073e9SAndroid Build Coastguard Worker                     }
2755*da0073e9SAndroid Build Coastguard Worker                 }
2756*da0073e9SAndroid Build Coastguard Worker                 if ((counter &= 511) == 256)
2757*da0073e9SAndroid Build Coastguard Worker                     break;
2758*da0073e9SAndroid Build Coastguard Worker 
2759*da0073e9SAndroid Build Coastguard Worker                 num_extra = s_length_extra[counter - 257];
2760*da0073e9SAndroid Build Coastguard Worker                 counter = s_length_base[counter - 257];
2761*da0073e9SAndroid Build Coastguard Worker                 if (num_extra)
2762*da0073e9SAndroid Build Coastguard Worker                 {
2763*da0073e9SAndroid Build Coastguard Worker                     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2764*da0073e9SAndroid Build Coastguard Worker                     mz_uint extra_bits;
2765*da0073e9SAndroid Build Coastguard Worker                     TINFL_GET_BITS(25, extra_bits, num_extra);
2766*da0073e9SAndroid Build Coastguard Worker                     counter += extra_bits;
2767*da0073e9SAndroid Build Coastguard Worker                 }
2768*da0073e9SAndroid Build Coastguard Worker 
2769*da0073e9SAndroid Build Coastguard Worker                 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2770*da0073e9SAndroid Build Coastguard Worker                 num_extra = s_dist_extra[dist];
2771*da0073e9SAndroid Build Coastguard Worker                 dist = s_dist_base[dist];
2772*da0073e9SAndroid Build Coastguard Worker                 if (num_extra)
2773*da0073e9SAndroid Build Coastguard Worker                 {
2774*da0073e9SAndroid Build Coastguard Worker                     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2775*da0073e9SAndroid Build Coastguard Worker                     mz_uint extra_bits;
2776*da0073e9SAndroid Build Coastguard Worker                     TINFL_GET_BITS(27, extra_bits, num_extra);
2777*da0073e9SAndroid Build Coastguard Worker                     dist += extra_bits;
2778*da0073e9SAndroid Build Coastguard Worker                 }
2779*da0073e9SAndroid Build Coastguard Worker 
2780*da0073e9SAndroid Build Coastguard Worker                 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2781*da0073e9SAndroid Build Coastguard Worker                 if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2782*da0073e9SAndroid Build Coastguard Worker                 {
2783*da0073e9SAndroid Build Coastguard Worker                     TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2784*da0073e9SAndroid Build Coastguard Worker                 }
2785*da0073e9SAndroid Build Coastguard Worker 
2786*da0073e9SAndroid Build Coastguard Worker                 pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2787*da0073e9SAndroid Build Coastguard Worker 
2788*da0073e9SAndroid Build Coastguard Worker                 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
2789*da0073e9SAndroid Build Coastguard Worker                 {
2790*da0073e9SAndroid Build Coastguard Worker                     while (counter--)
2791*da0073e9SAndroid Build Coastguard Worker                     {
2792*da0073e9SAndroid Build Coastguard Worker                         while (pOut_buf_cur >= pOut_buf_end)
2793*da0073e9SAndroid Build Coastguard Worker                         {
2794*da0073e9SAndroid Build Coastguard Worker                             TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2795*da0073e9SAndroid Build Coastguard Worker                         }
2796*da0073e9SAndroid Build Coastguard Worker                         *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
2797*da0073e9SAndroid Build Coastguard Worker                     }
2798*da0073e9SAndroid Build Coastguard Worker                     continue;
2799*da0073e9SAndroid Build Coastguard Worker                 }
2800*da0073e9SAndroid Build Coastguard Worker #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2801*da0073e9SAndroid Build Coastguard Worker                 else if ((counter >= 9) && (counter <= dist))
2802*da0073e9SAndroid Build Coastguard Worker                 {
2803*da0073e9SAndroid Build Coastguard Worker                     const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2804*da0073e9SAndroid Build Coastguard Worker                     do
2805*da0073e9SAndroid Build Coastguard Worker                     {
2806*da0073e9SAndroid Build Coastguard Worker #ifdef MINIZ_UNALIGNED_USE_MEMCPY
2807*da0073e9SAndroid Build Coastguard Worker 						memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2);
2808*da0073e9SAndroid Build Coastguard Worker #else
2809*da0073e9SAndroid Build Coastguard Worker                         ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2810*da0073e9SAndroid Build Coastguard Worker                         ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2811*da0073e9SAndroid Build Coastguard Worker #endif
2812*da0073e9SAndroid Build Coastguard Worker                         pOut_buf_cur += 8;
2813*da0073e9SAndroid Build Coastguard Worker                     } while ((pSrc += 8) < pSrc_end);
2814*da0073e9SAndroid Build Coastguard Worker                     if ((counter &= 7) < 3)
2815*da0073e9SAndroid Build Coastguard Worker                     {
2816*da0073e9SAndroid Build Coastguard Worker                         if (counter)
2817*da0073e9SAndroid Build Coastguard Worker                         {
2818*da0073e9SAndroid Build Coastguard Worker                             pOut_buf_cur[0] = pSrc[0];
2819*da0073e9SAndroid Build Coastguard Worker                             if (counter > 1)
2820*da0073e9SAndroid Build Coastguard Worker                                 pOut_buf_cur[1] = pSrc[1];
2821*da0073e9SAndroid Build Coastguard Worker                             pOut_buf_cur += counter;
2822*da0073e9SAndroid Build Coastguard Worker                         }
2823*da0073e9SAndroid Build Coastguard Worker                         continue;
2824*da0073e9SAndroid Build Coastguard Worker                     }
2825*da0073e9SAndroid Build Coastguard Worker                 }
2826*da0073e9SAndroid Build Coastguard Worker #endif
2827*da0073e9SAndroid Build Coastguard Worker                 while(counter>2)
2828*da0073e9SAndroid Build Coastguard Worker                 {
2829*da0073e9SAndroid Build Coastguard Worker                     pOut_buf_cur[0] = pSrc[0];
2830*da0073e9SAndroid Build Coastguard Worker                     pOut_buf_cur[1] = pSrc[1];
2831*da0073e9SAndroid Build Coastguard Worker                     pOut_buf_cur[2] = pSrc[2];
2832*da0073e9SAndroid Build Coastguard Worker                     pOut_buf_cur += 3;
2833*da0073e9SAndroid Build Coastguard Worker                     pSrc += 3;
2834*da0073e9SAndroid Build Coastguard Worker 					counter -= 3;
2835*da0073e9SAndroid Build Coastguard Worker                 }
2836*da0073e9SAndroid Build Coastguard Worker                 if (counter > 0)
2837*da0073e9SAndroid Build Coastguard Worker                 {
2838*da0073e9SAndroid Build Coastguard Worker                     pOut_buf_cur[0] = pSrc[0];
2839*da0073e9SAndroid Build Coastguard Worker                     if (counter > 1)
2840*da0073e9SAndroid Build Coastguard Worker                         pOut_buf_cur[1] = pSrc[1];
2841*da0073e9SAndroid Build Coastguard Worker                     pOut_buf_cur += counter;
2842*da0073e9SAndroid Build Coastguard Worker                 }
2843*da0073e9SAndroid Build Coastguard Worker             }
2844*da0073e9SAndroid Build Coastguard Worker         }
2845*da0073e9SAndroid Build Coastguard Worker     } while (!(r->m_final & 1));
2846*da0073e9SAndroid Build Coastguard Worker 
2847*da0073e9SAndroid Build Coastguard Worker     /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
2848*da0073e9SAndroid Build Coastguard Worker     /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */
2849*da0073e9SAndroid Build Coastguard Worker     TINFL_SKIP_BITS(32, num_bits & 7);
2850*da0073e9SAndroid Build Coastguard Worker     while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2851*da0073e9SAndroid Build Coastguard Worker     {
2852*da0073e9SAndroid Build Coastguard Worker         --pIn_buf_cur;
2853*da0073e9SAndroid Build Coastguard Worker         num_bits -= 8;
2854*da0073e9SAndroid Build Coastguard Worker     }
2855*da0073e9SAndroid Build Coastguard Worker     bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2856*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */
2857*da0073e9SAndroid Build Coastguard Worker 
2858*da0073e9SAndroid Build Coastguard Worker     if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2859*da0073e9SAndroid Build Coastguard Worker     {
2860*da0073e9SAndroid Build Coastguard Worker         for (counter = 0; counter < 4; ++counter)
2861*da0073e9SAndroid Build Coastguard Worker         {
2862*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2863*da0073e9SAndroid Build Coastguard Worker             mz_uint s;
2864*da0073e9SAndroid Build Coastguard Worker             if (num_bits)
2865*da0073e9SAndroid Build Coastguard Worker                 TINFL_GET_BITS(41, s, 8);
2866*da0073e9SAndroid Build Coastguard Worker             else
2867*da0073e9SAndroid Build Coastguard Worker                 TINFL_GET_BYTE(42, s);
2868*da0073e9SAndroid Build Coastguard Worker             r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2869*da0073e9SAndroid Build Coastguard Worker         }
2870*da0073e9SAndroid Build Coastguard Worker     }
2871*da0073e9SAndroid Build Coastguard Worker     TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2872*da0073e9SAndroid Build Coastguard Worker 
2873*da0073e9SAndroid Build Coastguard Worker     TINFL_CR_FINISH
2874*da0073e9SAndroid Build Coastguard Worker 
2875*da0073e9SAndroid Build Coastguard Worker common_exit:
2876*da0073e9SAndroid Build Coastguard Worker     /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
2877*da0073e9SAndroid Build Coastguard Worker     /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
2878*da0073e9SAndroid Build Coastguard Worker     /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */
2879*da0073e9SAndroid Build Coastguard Worker     if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
2880*da0073e9SAndroid Build Coastguard Worker     {
2881*da0073e9SAndroid Build Coastguard Worker         while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2882*da0073e9SAndroid Build Coastguard Worker         {
2883*da0073e9SAndroid Build Coastguard Worker             --pIn_buf_cur;
2884*da0073e9SAndroid Build Coastguard Worker             num_bits -= 8;
2885*da0073e9SAndroid Build Coastguard Worker         }
2886*da0073e9SAndroid Build Coastguard Worker     }
2887*da0073e9SAndroid Build Coastguard Worker     r->m_num_bits = num_bits;
2888*da0073e9SAndroid Build Coastguard Worker     r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2889*da0073e9SAndroid Build Coastguard Worker     r->m_dist = dist;
2890*da0073e9SAndroid Build Coastguard Worker     r->m_counter = counter;
2891*da0073e9SAndroid Build Coastguard Worker     r->m_num_extra = num_extra;
2892*da0073e9SAndroid Build Coastguard Worker     r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2893*da0073e9SAndroid Build Coastguard Worker     *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2894*da0073e9SAndroid Build Coastguard Worker     *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2895*da0073e9SAndroid Build Coastguard Worker     if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
2896*da0073e9SAndroid Build Coastguard Worker     {
2897*da0073e9SAndroid Build Coastguard Worker         const mz_uint8 *ptr = pOut_buf_next;
2898*da0073e9SAndroid Build Coastguard Worker         size_t buf_len = *pOut_buf_size;
2899*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,cppcoreguidelines-init-variables)
2900*da0073e9SAndroid Build Coastguard Worker         mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
2901*da0073e9SAndroid Build Coastguard Worker         size_t block_len = buf_len % 5552;
2902*da0073e9SAndroid Build Coastguard Worker         while (buf_len)
2903*da0073e9SAndroid Build Coastguard Worker         {
2904*da0073e9SAndroid Build Coastguard Worker             for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
2905*da0073e9SAndroid Build Coastguard Worker             {
2906*da0073e9SAndroid Build Coastguard Worker                 s1 += ptr[0], s2 += s1;
2907*da0073e9SAndroid Build Coastguard Worker                 s1 += ptr[1], s2 += s1;
2908*da0073e9SAndroid Build Coastguard Worker                 s1 += ptr[2], s2 += s1;
2909*da0073e9SAndroid Build Coastguard Worker                 s1 += ptr[3], s2 += s1;
2910*da0073e9SAndroid Build Coastguard Worker                 s1 += ptr[4], s2 += s1;
2911*da0073e9SAndroid Build Coastguard Worker                 s1 += ptr[5], s2 += s1;
2912*da0073e9SAndroid Build Coastguard Worker                 s1 += ptr[6], s2 += s1;
2913*da0073e9SAndroid Build Coastguard Worker                 s1 += ptr[7], s2 += s1;
2914*da0073e9SAndroid Build Coastguard Worker             }
2915*da0073e9SAndroid Build Coastguard Worker             for (; i < block_len; ++i)
2916*da0073e9SAndroid Build Coastguard Worker                 s1 += *ptr++, s2 += s1;
2917*da0073e9SAndroid Build Coastguard Worker             s1 %= 65521U, s2 %= 65521U;
2918*da0073e9SAndroid Build Coastguard Worker             buf_len -= block_len;
2919*da0073e9SAndroid Build Coastguard Worker             block_len = 5552;
2920*da0073e9SAndroid Build Coastguard Worker         }
2921*da0073e9SAndroid Build Coastguard Worker         r->m_check_adler32 = (s2 << 16) + s1;
2922*da0073e9SAndroid Build Coastguard Worker         if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
2923*da0073e9SAndroid Build Coastguard Worker             status = TINFL_STATUS_ADLER32_MISMATCH;
2924*da0073e9SAndroid Build Coastguard Worker     }
2925*da0073e9SAndroid Build Coastguard Worker     return status;
2926*da0073e9SAndroid Build Coastguard Worker }
2927*da0073e9SAndroid Build Coastguard Worker 
2928*da0073e9SAndroid Build Coastguard Worker /* Higher level helper functions. */
tinfl_decompress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)2929*da0073e9SAndroid Build Coastguard Worker void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2930*da0073e9SAndroid Build Coastguard Worker {
2931*da0073e9SAndroid Build Coastguard Worker     tinfl_decompressor decomp;
2932*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2933*da0073e9SAndroid Build Coastguard Worker     void *pBuf = NULL, *pNew_buf;
2934*da0073e9SAndroid Build Coastguard Worker     size_t src_buf_ofs = 0, out_buf_capacity = 0;
2935*da0073e9SAndroid Build Coastguard Worker     *pOut_len = 0;
2936*da0073e9SAndroid Build Coastguard Worker     tinfl_init(&decomp);
2937*da0073e9SAndroid Build Coastguard Worker     for (;;)
2938*da0073e9SAndroid Build Coastguard Worker     {
2939*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2940*da0073e9SAndroid Build Coastguard Worker         size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2941*da0073e9SAndroid Build Coastguard Worker         tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size,
2942*da0073e9SAndroid Build Coastguard Worker                                                (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2943*da0073e9SAndroid Build Coastguard Worker         if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
2944*da0073e9SAndroid Build Coastguard Worker         {
2945*da0073e9SAndroid Build Coastguard Worker             MZ_FREE(pBuf);
2946*da0073e9SAndroid Build Coastguard Worker             *pOut_len = 0;
2947*da0073e9SAndroid Build Coastguard Worker             return NULL;
2948*da0073e9SAndroid Build Coastguard Worker         }
2949*da0073e9SAndroid Build Coastguard Worker         src_buf_ofs += src_buf_size;
2950*da0073e9SAndroid Build Coastguard Worker         *pOut_len += dst_buf_size;
2951*da0073e9SAndroid Build Coastguard Worker         if (status == TINFL_STATUS_DONE)
2952*da0073e9SAndroid Build Coastguard Worker             break;
2953*da0073e9SAndroid Build Coastguard Worker         new_out_buf_capacity = out_buf_capacity * 2;
2954*da0073e9SAndroid Build Coastguard Worker         if (new_out_buf_capacity < 128)
2955*da0073e9SAndroid Build Coastguard Worker             new_out_buf_capacity = 128;
2956*da0073e9SAndroid Build Coastguard Worker         pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2957*da0073e9SAndroid Build Coastguard Worker         if (!pNew_buf)
2958*da0073e9SAndroid Build Coastguard Worker         {
2959*da0073e9SAndroid Build Coastguard Worker             MZ_FREE(pBuf);
2960*da0073e9SAndroid Build Coastguard Worker             *pOut_len = 0;
2961*da0073e9SAndroid Build Coastguard Worker             return NULL;
2962*da0073e9SAndroid Build Coastguard Worker         }
2963*da0073e9SAndroid Build Coastguard Worker         pBuf = pNew_buf;
2964*da0073e9SAndroid Build Coastguard Worker         out_buf_capacity = new_out_buf_capacity;
2965*da0073e9SAndroid Build Coastguard Worker     }
2966*da0073e9SAndroid Build Coastguard Worker     return pBuf;
2967*da0073e9SAndroid Build Coastguard Worker }
2968*da0073e9SAndroid Build Coastguard Worker 
tinfl_decompress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)2969*da0073e9SAndroid Build Coastguard Worker size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2970*da0073e9SAndroid Build Coastguard Worker {
2971*da0073e9SAndroid Build Coastguard Worker     tinfl_decompressor decomp;
2972*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2973*da0073e9SAndroid Build Coastguard Worker     tinfl_status status;
2974*da0073e9SAndroid Build Coastguard Worker     tinfl_init(&decomp);
2975*da0073e9SAndroid Build Coastguard Worker     status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2976*da0073e9SAndroid Build Coastguard Worker     return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
2977*da0073e9SAndroid Build Coastguard Worker }
2978*da0073e9SAndroid Build Coastguard Worker 
tinfl_decompress_mem_to_callback(const void * pIn_buf,size_t * pIn_buf_size,tinfl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)2979*da0073e9SAndroid Build Coastguard Worker int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2980*da0073e9SAndroid Build Coastguard Worker {
2981*da0073e9SAndroid Build Coastguard Worker     int result = 0;
2982*da0073e9SAndroid Build Coastguard Worker     tinfl_decompressor decomp;
2983*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2984*da0073e9SAndroid Build Coastguard Worker     size_t in_buf_ofs = 0, dict_ofs = 0;
2985*da0073e9SAndroid Build Coastguard Worker     if (!pDict)
2986*da0073e9SAndroid Build Coastguard Worker         return TINFL_STATUS_FAILED;
2987*da0073e9SAndroid Build Coastguard Worker     tinfl_init(&decomp);
2988*da0073e9SAndroid Build Coastguard Worker     for (;;)
2989*da0073e9SAndroid Build Coastguard Worker     {
2990*da0073e9SAndroid Build Coastguard Worker         size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2991*da0073e9SAndroid Build Coastguard Worker         tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2992*da0073e9SAndroid Build Coastguard Worker                                                (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2993*da0073e9SAndroid Build Coastguard Worker         in_buf_ofs += in_buf_size;
2994*da0073e9SAndroid Build Coastguard Worker         if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2995*da0073e9SAndroid Build Coastguard Worker             break;
2996*da0073e9SAndroid Build Coastguard Worker         if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
2997*da0073e9SAndroid Build Coastguard Worker         {
2998*da0073e9SAndroid Build Coastguard Worker             result = (status == TINFL_STATUS_DONE);
2999*da0073e9SAndroid Build Coastguard Worker             break;
3000*da0073e9SAndroid Build Coastguard Worker         }
3001*da0073e9SAndroid Build Coastguard Worker         dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
3002*da0073e9SAndroid Build Coastguard Worker     }
3003*da0073e9SAndroid Build Coastguard Worker     MZ_FREE(pDict);
3004*da0073e9SAndroid Build Coastguard Worker     *pIn_buf_size = in_buf_ofs;
3005*da0073e9SAndroid Build Coastguard Worker     return result;
3006*da0073e9SAndroid Build Coastguard Worker }
3007*da0073e9SAndroid Build Coastguard Worker 
3008*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_MALLOC
tinfl_decompressor_alloc(void)3009*da0073e9SAndroid Build Coastguard Worker tinfl_decompressor *tinfl_decompressor_alloc(void)
3010*da0073e9SAndroid Build Coastguard Worker {
3011*da0073e9SAndroid Build Coastguard Worker     tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor));
3012*da0073e9SAndroid Build Coastguard Worker     if (pDecomp)
3013*da0073e9SAndroid Build Coastguard Worker         tinfl_init(pDecomp);
3014*da0073e9SAndroid Build Coastguard Worker     return pDecomp;
3015*da0073e9SAndroid Build Coastguard Worker }
3016*da0073e9SAndroid Build Coastguard Worker 
tinfl_decompressor_free(tinfl_decompressor * pDecomp)3017*da0073e9SAndroid Build Coastguard Worker void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
3018*da0073e9SAndroid Build Coastguard Worker {
3019*da0073e9SAndroid Build Coastguard Worker     MZ_FREE(pDecomp);
3020*da0073e9SAndroid Build Coastguard Worker }
3021*da0073e9SAndroid Build Coastguard Worker #endif
3022*da0073e9SAndroid Build Coastguard Worker 
3023*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
3024*da0073e9SAndroid Build Coastguard Worker }
3025*da0073e9SAndroid Build Coastguard Worker #endif
3026*da0073e9SAndroid Build Coastguard Worker /**************************************************************************
3027*da0073e9SAndroid Build Coastguard Worker  *
3028*da0073e9SAndroid Build Coastguard Worker  * Copyright 2013-2014 RAD Game Tools and Valve Software
3029*da0073e9SAndroid Build Coastguard Worker  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
3030*da0073e9SAndroid Build Coastguard Worker  * Copyright 2016 Martin Raiber
3031*da0073e9SAndroid Build Coastguard Worker  * All Rights Reserved.
3032*da0073e9SAndroid Build Coastguard Worker  *
3033*da0073e9SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
3034*da0073e9SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
3035*da0073e9SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
3036*da0073e9SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3037*da0073e9SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
3038*da0073e9SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
3039*da0073e9SAndroid Build Coastguard Worker  *
3040*da0073e9SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
3041*da0073e9SAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
3042*da0073e9SAndroid Build Coastguard Worker  *
3043*da0073e9SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3044*da0073e9SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3045*da0073e9SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3046*da0073e9SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3047*da0073e9SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3048*da0073e9SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3049*da0073e9SAndroid Build Coastguard Worker  * THE SOFTWARE.
3050*da0073e9SAndroid Build Coastguard Worker  *
3051*da0073e9SAndroid Build Coastguard Worker  **************************************************************************/
3052*da0073e9SAndroid Build Coastguard Worker 
3053*da0073e9SAndroid Build Coastguard Worker 
3054*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_ARCHIVE_APIS
3055*da0073e9SAndroid Build Coastguard Worker 
3056*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
3057*da0073e9SAndroid Build Coastguard Worker extern "C" {
3058*da0073e9SAndroid Build Coastguard Worker #endif
3059*da0073e9SAndroid Build Coastguard Worker 
3060*da0073e9SAndroid Build Coastguard Worker /* ------------------- .ZIP archive reading */
3061*da0073e9SAndroid Build Coastguard Worker 
3062*da0073e9SAndroid Build Coastguard Worker #ifdef MINIZ_NO_STDIO
3063*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE void *
3064*da0073e9SAndroid Build Coastguard Worker #else
3065*da0073e9SAndroid Build Coastguard Worker #include <sys/stat.h>
3066*da0073e9SAndroid Build Coastguard Worker 
3067*da0073e9SAndroid Build Coastguard Worker #if defined(_MSC_VER) || defined(__MINGW64__)
3068*da0073e9SAndroid Build Coastguard Worker static FILE *mz_fopen(const char *pFilename, const char *pMode)
3069*da0073e9SAndroid Build Coastguard Worker {
3070*da0073e9SAndroid Build Coastguard Worker     FILE *pFile = NULL;
3071*da0073e9SAndroid Build Coastguard Worker     fopen_s(&pFile, pFilename, pMode);
3072*da0073e9SAndroid Build Coastguard Worker     return pFile;
3073*da0073e9SAndroid Build Coastguard Worker }
3074*da0073e9SAndroid Build Coastguard Worker static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
3075*da0073e9SAndroid Build Coastguard Worker {
3076*da0073e9SAndroid Build Coastguard Worker     FILE *pFile = NULL;
3077*da0073e9SAndroid Build Coastguard Worker     if (freopen_s(&pFile, pPath, pMode, pStream))
3078*da0073e9SAndroid Build Coastguard Worker         return NULL;
3079*da0073e9SAndroid Build Coastguard Worker     return pFile;
3080*da0073e9SAndroid Build Coastguard Worker }
3081*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
3082*da0073e9SAndroid Build Coastguard Worker #include <sys/utime.h>
3083*da0073e9SAndroid Build Coastguard Worker #endif
3084*da0073e9SAndroid Build Coastguard Worker #define MZ_FOPEN mz_fopen
3085*da0073e9SAndroid Build Coastguard Worker #define MZ_FCLOSE fclose
3086*da0073e9SAndroid Build Coastguard Worker #define MZ_FREAD fread
3087*da0073e9SAndroid Build Coastguard Worker #define MZ_FWRITE fwrite
3088*da0073e9SAndroid Build Coastguard Worker #define MZ_FTELL64 _ftelli64
3089*da0073e9SAndroid Build Coastguard Worker #define MZ_FSEEK64 _fseeki64
3090*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT_STRUCT _stat64
3091*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT _stat64
3092*da0073e9SAndroid Build Coastguard Worker #define MZ_FFLUSH fflush
3093*da0073e9SAndroid Build Coastguard Worker #define MZ_FREOPEN mz_freopen
3094*da0073e9SAndroid Build Coastguard Worker #define MZ_DELETE_FILE remove
3095*da0073e9SAndroid Build Coastguard Worker #elif defined(__MINGW32__)
3096*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
3097*da0073e9SAndroid Build Coastguard Worker #include <sys/utime.h>
3098*da0073e9SAndroid Build Coastguard Worker #endif
3099*da0073e9SAndroid Build Coastguard Worker #define MZ_FOPEN(f, m) fopen(f, m)
3100*da0073e9SAndroid Build Coastguard Worker #define MZ_FCLOSE fclose
3101*da0073e9SAndroid Build Coastguard Worker #define MZ_FREAD fread
3102*da0073e9SAndroid Build Coastguard Worker #define MZ_FWRITE fwrite
3103*da0073e9SAndroid Build Coastguard Worker #define MZ_FTELL64 ftello64
3104*da0073e9SAndroid Build Coastguard Worker #define MZ_FSEEK64 fseeko64
3105*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT_STRUCT _stat
3106*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT _stat
3107*da0073e9SAndroid Build Coastguard Worker #define MZ_FFLUSH fflush
3108*da0073e9SAndroid Build Coastguard Worker #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3109*da0073e9SAndroid Build Coastguard Worker #define MZ_DELETE_FILE remove
3110*da0073e9SAndroid Build Coastguard Worker #elif defined(__TINYC__)
3111*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
3112*da0073e9SAndroid Build Coastguard Worker #include <sys/utime.h>
3113*da0073e9SAndroid Build Coastguard Worker #endif
3114*da0073e9SAndroid Build Coastguard Worker #define MZ_FOPEN(f, m) fopen(f, m)
3115*da0073e9SAndroid Build Coastguard Worker #define MZ_FCLOSE fclose
3116*da0073e9SAndroid Build Coastguard Worker #define MZ_FREAD fread
3117*da0073e9SAndroid Build Coastguard Worker #define MZ_FWRITE fwrite
3118*da0073e9SAndroid Build Coastguard Worker #define MZ_FTELL64 ftell
3119*da0073e9SAndroid Build Coastguard Worker #define MZ_FSEEK64 fseek
3120*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT_STRUCT stat
3121*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT stat
3122*da0073e9SAndroid Build Coastguard Worker #define MZ_FFLUSH fflush
3123*da0073e9SAndroid Build Coastguard Worker #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3124*da0073e9SAndroid Build Coastguard Worker #define MZ_DELETE_FILE remove
3125*da0073e9SAndroid Build Coastguard Worker #elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE)
3126*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
3127*da0073e9SAndroid Build Coastguard Worker #include <utime.h>
3128*da0073e9SAndroid Build Coastguard Worker #endif
3129*da0073e9SAndroid Build Coastguard Worker #define MZ_FOPEN(f, m) fopen64(f, m)
3130*da0073e9SAndroid Build Coastguard Worker #define MZ_FCLOSE fclose
3131*da0073e9SAndroid Build Coastguard Worker #define MZ_FREAD fread
3132*da0073e9SAndroid Build Coastguard Worker #define MZ_FWRITE fwrite
3133*da0073e9SAndroid Build Coastguard Worker #define MZ_FTELL64 ftello64
3134*da0073e9SAndroid Build Coastguard Worker #define MZ_FSEEK64 fseeko64
3135*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT_STRUCT stat64
3136*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT stat64
3137*da0073e9SAndroid Build Coastguard Worker #define MZ_FFLUSH fflush
3138*da0073e9SAndroid Build Coastguard Worker #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
3139*da0073e9SAndroid Build Coastguard Worker #define MZ_DELETE_FILE remove
3140*da0073e9SAndroid Build Coastguard Worker #elif defined(__APPLE__)
3141*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
3142*da0073e9SAndroid Build Coastguard Worker #include <utime.h>
3143*da0073e9SAndroid Build Coastguard Worker #endif
3144*da0073e9SAndroid Build Coastguard Worker #define MZ_FOPEN(f, m) fopen(f, m)
3145*da0073e9SAndroid Build Coastguard Worker #define MZ_FCLOSE fclose
3146*da0073e9SAndroid Build Coastguard Worker #define MZ_FREAD fread
3147*da0073e9SAndroid Build Coastguard Worker #define MZ_FWRITE fwrite
3148*da0073e9SAndroid Build Coastguard Worker #define MZ_FTELL64 ftello
3149*da0073e9SAndroid Build Coastguard Worker #define MZ_FSEEK64 fseeko
3150*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT_STRUCT stat
3151*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT stat
3152*da0073e9SAndroid Build Coastguard Worker #define MZ_FFLUSH fflush
3153*da0073e9SAndroid Build Coastguard Worker #define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3154*da0073e9SAndroid Build Coastguard Worker #define MZ_DELETE_FILE remove
3155*da0073e9SAndroid Build Coastguard Worker 
3156*da0073e9SAndroid Build Coastguard Worker #else
3157*da0073e9SAndroid Build Coastguard Worker #pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
3158*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
3159*da0073e9SAndroid Build Coastguard Worker #include <utime.h>
3160*da0073e9SAndroid Build Coastguard Worker #endif
3161*da0073e9SAndroid Build Coastguard Worker #define MZ_FOPEN(f, m) fopen(f, m)
3162*da0073e9SAndroid Build Coastguard Worker #define MZ_FCLOSE fclose
3163*da0073e9SAndroid Build Coastguard Worker #define MZ_FREAD fread
3164*da0073e9SAndroid Build Coastguard Worker #define MZ_FWRITE fwrite
3165*da0073e9SAndroid Build Coastguard Worker #ifdef __STRICT_ANSI__
3166*da0073e9SAndroid Build Coastguard Worker #define MZ_FTELL64 ftell
3167*da0073e9SAndroid Build Coastguard Worker #define MZ_FSEEK64 fseek
3168*da0073e9SAndroid Build Coastguard Worker #else
3169*da0073e9SAndroid Build Coastguard Worker #define MZ_FTELL64 ftello
3170*da0073e9SAndroid Build Coastguard Worker #define MZ_FSEEK64 fseeko
3171*da0073e9SAndroid Build Coastguard Worker #endif
3172*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT_STRUCT stat
3173*da0073e9SAndroid Build Coastguard Worker #define MZ_FILE_STAT stat
3174*da0073e9SAndroid Build Coastguard Worker #define MZ_FFLUSH fflush
3175*da0073e9SAndroid Build Coastguard Worker #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3176*da0073e9SAndroid Build Coastguard Worker #define MZ_DELETE_FILE remove
3177*da0073e9SAndroid Build Coastguard Worker #endif /* #ifdef _MSC_VER */
3178*da0073e9SAndroid Build Coastguard Worker #endif /* #ifdef MINIZ_NO_STDIO */
3179*da0073e9SAndroid Build Coastguard Worker 
3180*da0073e9SAndroid Build Coastguard Worker #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
3181*da0073e9SAndroid Build Coastguard Worker 
3182*da0073e9SAndroid Build Coastguard Worker /* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */
3183*da0073e9SAndroid Build Coastguard Worker enum
3184*da0073e9SAndroid Build Coastguard Worker {
3185*da0073e9SAndroid Build Coastguard Worker     /* ZIP archive identifiers and record sizes */
3186*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
3187*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
3188*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
3189*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
3190*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
3191*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
3192*da0073e9SAndroid Build Coastguard Worker 
3193*da0073e9SAndroid Build Coastguard Worker     /* ZIP64 archive identifier and record sizes */
3194*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
3195*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
3196*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
3197*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
3198*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
3199*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
3200*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
3201*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
3202*da0073e9SAndroid Build Coastguard Worker 
3203*da0073e9SAndroid Build Coastguard Worker     /* Central directory header record offsets */
3204*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_SIG_OFS = 0,
3205*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
3206*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
3207*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
3208*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_METHOD_OFS = 10,
3209*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_FILE_TIME_OFS = 12,
3210*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_FILE_DATE_OFS = 14,
3211*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_CRC32_OFS = 16,
3212*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
3213*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
3214*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
3215*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
3216*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
3217*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_DISK_START_OFS = 34,
3218*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
3219*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
3220*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
3221*da0073e9SAndroid Build Coastguard Worker 
3222*da0073e9SAndroid Build Coastguard Worker     /* Local directory header offsets */
3223*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_SIG_OFS = 0,
3224*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
3225*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
3226*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_METHOD_OFS = 8,
3227*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_FILE_TIME_OFS = 10,
3228*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_FILE_DATE_OFS = 12,
3229*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_CRC32_OFS = 14,
3230*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
3231*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
3232*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
3233*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
3234*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
3235*da0073e9SAndroid Build Coastguard Worker 
3236*da0073e9SAndroid Build Coastguard Worker     /* End of central directory offsets */
3237*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ECDH_SIG_OFS = 0,
3238*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
3239*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
3240*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
3241*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
3242*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
3243*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
3244*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
3245*da0073e9SAndroid Build Coastguard Worker 
3246*da0073e9SAndroid Build Coastguard Worker     /* ZIP64 End of central directory locator offsets */
3247*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDL_SIG_OFS = 0,                    /* 4 bytes */
3248*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,          /* 4 bytes */
3249*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,  /* 8 bytes */
3250*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
3251*da0073e9SAndroid Build Coastguard Worker 
3252*da0073e9SAndroid Build Coastguard Worker     /* ZIP64 End of central directory header offsets */
3253*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_SIG_OFS = 0,                       /* 4 bytes */
3254*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,            /* 8 bytes */
3255*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,          /* 2 bytes */
3256*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,           /* 2 bytes */
3257*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,            /* 4 bytes */
3258*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,            /* 4 bytes */
3259*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
3260*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,       /* 8 bytes */
3261*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,                /* 8 bytes */
3262*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,                 /* 8 bytes */
3263*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
3264*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
3265*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
3266*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
3267*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
3268*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
3269*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
3270*da0073e9SAndroid Build Coastguard Worker };
3271*da0073e9SAndroid Build Coastguard Worker 
3272*da0073e9SAndroid Build Coastguard Worker typedef struct
3273*da0073e9SAndroid Build Coastguard Worker {
3274*da0073e9SAndroid Build Coastguard Worker     void *m_p;
3275*da0073e9SAndroid Build Coastguard Worker     size_t m_size, m_capacity;
3276*da0073e9SAndroid Build Coastguard Worker     mz_uint m_element_size;
3277*da0073e9SAndroid Build Coastguard Worker } mz_zip_array;
3278*da0073e9SAndroid Build Coastguard Worker 
3279*da0073e9SAndroid Build Coastguard Worker struct mz_zip_internal_state_tag
3280*da0073e9SAndroid Build Coastguard Worker {
3281*da0073e9SAndroid Build Coastguard Worker     mz_zip_array m_central_dir;
3282*da0073e9SAndroid Build Coastguard Worker     mz_zip_array m_central_dir_offsets;
3283*da0073e9SAndroid Build Coastguard Worker     mz_zip_array m_sorted_central_dir_offsets;
3284*da0073e9SAndroid Build Coastguard Worker 
3285*da0073e9SAndroid Build Coastguard Worker     /* The flags passed in when the archive is initially opened. */
3286*da0073e9SAndroid Build Coastguard Worker     uint32_t m_init_flags;
3287*da0073e9SAndroid Build Coastguard Worker 
3288*da0073e9SAndroid Build Coastguard Worker     /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
3289*da0073e9SAndroid Build Coastguard Worker     mz_bool m_zip64;
3290*da0073e9SAndroid Build Coastguard Worker 
3291*da0073e9SAndroid Build Coastguard Worker     /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */
3292*da0073e9SAndroid Build Coastguard Worker     mz_bool m_zip64_has_extended_info_fields;
3293*da0073e9SAndroid Build Coastguard Worker 
3294*da0073e9SAndroid Build Coastguard Worker     /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */
3295*da0073e9SAndroid Build Coastguard Worker     MZ_FILE *m_pFile;
3296*da0073e9SAndroid Build Coastguard Worker     mz_uint64 m_file_archive_start_ofs;
3297*da0073e9SAndroid Build Coastguard Worker 
3298*da0073e9SAndroid Build Coastguard Worker     void *m_pMem;
3299*da0073e9SAndroid Build Coastguard Worker     size_t m_mem_size;
3300*da0073e9SAndroid Build Coastguard Worker     size_t m_mem_capacity;
3301*da0073e9SAndroid Build Coastguard Worker };
3302*da0073e9SAndroid Build Coastguard Worker 
3303*da0073e9SAndroid Build Coastguard Worker #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
3304*da0073e9SAndroid Build Coastguard Worker 
3305*da0073e9SAndroid Build Coastguard Worker #if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG)
mz_zip_array_range_check(const mz_zip_array * pArray,mz_uint index)3306*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
3307*da0073e9SAndroid Build Coastguard Worker {
3308*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT(index < pArray->m_size);
3309*da0073e9SAndroid Build Coastguard Worker     return index;
3310*da0073e9SAndroid Build Coastguard Worker }
3311*da0073e9SAndroid Build Coastguard Worker #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
3312*da0073e9SAndroid Build Coastguard Worker #else
3313*da0073e9SAndroid Build Coastguard Worker #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
3314*da0073e9SAndroid Build Coastguard Worker #endif
3315*da0073e9SAndroid Build Coastguard Worker 
mz_zip_array_init(mz_zip_array * pArray,mz_uint32 element_size)3316*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
3317*da0073e9SAndroid Build Coastguard Worker {
3318*da0073e9SAndroid Build Coastguard Worker     memset(pArray, 0, sizeof(mz_zip_array));
3319*da0073e9SAndroid Build Coastguard Worker     pArray->m_element_size = element_size;
3320*da0073e9SAndroid Build Coastguard Worker }
3321*da0073e9SAndroid Build Coastguard Worker 
mz_zip_array_clear(mz_zip_archive * pZip,mz_zip_array * pArray)3322*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
3323*da0073e9SAndroid Build Coastguard Worker {
3324*da0073e9SAndroid Build Coastguard Worker     pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3325*da0073e9SAndroid Build Coastguard Worker     memset(pArray, 0, sizeof(mz_zip_array));
3326*da0073e9SAndroid Build Coastguard Worker }
3327*da0073e9SAndroid Build Coastguard Worker 
mz_zip_array_ensure_capacity(mz_zip_archive * pZip,mz_zip_array * pArray,size_t min_new_capacity,mz_uint growing)3328*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
3329*da0073e9SAndroid Build Coastguard Worker {
3330*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3331*da0073e9SAndroid Build Coastguard Worker     void *pNew_p;
3332*da0073e9SAndroid Build Coastguard Worker     size_t new_capacity = min_new_capacity;
3333*da0073e9SAndroid Build Coastguard Worker     MZ_ASSERT(pArray->m_element_size);
3334*da0073e9SAndroid Build Coastguard Worker     if (pArray->m_capacity >= min_new_capacity)
3335*da0073e9SAndroid Build Coastguard Worker         return MZ_TRUE;
3336*da0073e9SAndroid Build Coastguard Worker     if (growing)
3337*da0073e9SAndroid Build Coastguard Worker     {
3338*da0073e9SAndroid Build Coastguard Worker         new_capacity = MZ_MAX(1, pArray->m_capacity);
3339*da0073e9SAndroid Build Coastguard Worker         while (new_capacity < min_new_capacity)
3340*da0073e9SAndroid Build Coastguard Worker             new_capacity *= 2;
3341*da0073e9SAndroid Build Coastguard Worker     }
3342*da0073e9SAndroid Build Coastguard Worker     if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3343*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3344*da0073e9SAndroid Build Coastguard Worker     pArray->m_p = pNew_p;
3345*da0073e9SAndroid Build Coastguard Worker     pArray->m_capacity = new_capacity;
3346*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3347*da0073e9SAndroid Build Coastguard Worker }
3348*da0073e9SAndroid Build Coastguard Worker 
mz_zip_array_reserve(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_capacity,mz_uint growing)3349*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3350*da0073e9SAndroid Build Coastguard Worker {
3351*da0073e9SAndroid Build Coastguard Worker     if (new_capacity > pArray->m_capacity)
3352*da0073e9SAndroid Build Coastguard Worker     {
3353*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3354*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
3355*da0073e9SAndroid Build Coastguard Worker     }
3356*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3357*da0073e9SAndroid Build Coastguard Worker }
3358*da0073e9SAndroid Build Coastguard Worker 
mz_zip_array_resize(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_size,mz_uint growing)3359*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3360*da0073e9SAndroid Build Coastguard Worker {
3361*da0073e9SAndroid Build Coastguard Worker     if (new_size > pArray->m_capacity)
3362*da0073e9SAndroid Build Coastguard Worker     {
3363*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3364*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
3365*da0073e9SAndroid Build Coastguard Worker     }
3366*da0073e9SAndroid Build Coastguard Worker     pArray->m_size = new_size;
3367*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3368*da0073e9SAndroid Build Coastguard Worker }
3369*da0073e9SAndroid Build Coastguard Worker 
mz_zip_array_ensure_room(mz_zip_archive * pZip,mz_zip_array * pArray,size_t n)3370*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
3371*da0073e9SAndroid Build Coastguard Worker {
3372*da0073e9SAndroid Build Coastguard Worker     return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3373*da0073e9SAndroid Build Coastguard Worker }
3374*da0073e9SAndroid Build Coastguard Worker 
mz_zip_array_push_back(mz_zip_archive * pZip,mz_zip_array * pArray,const void * pElements,size_t n)3375*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3376*da0073e9SAndroid Build Coastguard Worker {
3377*da0073e9SAndroid Build Coastguard Worker     size_t orig_size = pArray->m_size;
3378*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3379*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3380*da0073e9SAndroid Build Coastguard Worker     if (n > 0)
3381*da0073e9SAndroid Build Coastguard Worker         memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3382*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3383*da0073e9SAndroid Build Coastguard Worker }
3384*da0073e9SAndroid Build Coastguard Worker 
3385*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
mz_zip_dos_to_time_t(int dos_time,int dos_date)3386*da0073e9SAndroid Build Coastguard Worker static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
3387*da0073e9SAndroid Build Coastguard Worker {
3388*da0073e9SAndroid Build Coastguard Worker     struct tm tm;
3389*da0073e9SAndroid Build Coastguard Worker     memset(&tm, 0, sizeof(tm));
3390*da0073e9SAndroid Build Coastguard Worker     tm.tm_isdst = -1;
3391*da0073e9SAndroid Build Coastguard Worker     tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3392*da0073e9SAndroid Build Coastguard Worker     tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3393*da0073e9SAndroid Build Coastguard Worker     tm.tm_mday = dos_date & 31;
3394*da0073e9SAndroid Build Coastguard Worker     tm.tm_hour = (dos_time >> 11) & 31;
3395*da0073e9SAndroid Build Coastguard Worker     tm.tm_min = (dos_time >> 5) & 63;
3396*da0073e9SAndroid Build Coastguard Worker     tm.tm_sec = (dos_time << 1) & 62;
3397*da0073e9SAndroid Build Coastguard Worker     return mktime(&tm);
3398*da0073e9SAndroid Build Coastguard Worker }
3399*da0073e9SAndroid Build Coastguard Worker 
3400*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
mz_zip_time_t_to_dos_time(MZ_TIME_T time,mz_uint16 * pDOS_time,mz_uint16 * pDOS_date)3401*da0073e9SAndroid Build Coastguard Worker static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3402*da0073e9SAndroid Build Coastguard Worker {
3403*da0073e9SAndroid Build Coastguard Worker #ifdef _MSC_VER
3404*da0073e9SAndroid Build Coastguard Worker     struct tm tm_struct;
3405*da0073e9SAndroid Build Coastguard Worker     struct tm *tm = &tm_struct;
3406*da0073e9SAndroid Build Coastguard Worker     errno_t err = localtime_s(tm, &time);
3407*da0073e9SAndroid Build Coastguard Worker     if (err)
3408*da0073e9SAndroid Build Coastguard Worker     {
3409*da0073e9SAndroid Build Coastguard Worker         *pDOS_date = 0;
3410*da0073e9SAndroid Build Coastguard Worker         *pDOS_time = 0;
3411*da0073e9SAndroid Build Coastguard Worker         return;
3412*da0073e9SAndroid Build Coastguard Worker     }
3413*da0073e9SAndroid Build Coastguard Worker #else
3414*da0073e9SAndroid Build Coastguard Worker     struct tm *tm = localtime(&time);
3415*da0073e9SAndroid Build Coastguard Worker #endif /* #ifdef _MSC_VER */
3416*da0073e9SAndroid Build Coastguard Worker 
3417*da0073e9SAndroid Build Coastguard Worker     *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3418*da0073e9SAndroid Build Coastguard Worker     *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3419*da0073e9SAndroid Build Coastguard Worker }
3420*da0073e9SAndroid Build Coastguard Worker #endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
3421*da0073e9SAndroid Build Coastguard Worker 
3422*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
3423*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
mz_zip_get_file_modified_time(const char * pFilename,MZ_TIME_T * pTime)3424*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
3425*da0073e9SAndroid Build Coastguard Worker {
3426*da0073e9SAndroid Build Coastguard Worker     struct MZ_FILE_STAT_STRUCT file_stat;
3427*da0073e9SAndroid Build Coastguard Worker 
3428*da0073e9SAndroid Build Coastguard Worker     /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
3429*da0073e9SAndroid Build Coastguard Worker     if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3430*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3431*da0073e9SAndroid Build Coastguard Worker 
3432*da0073e9SAndroid Build Coastguard Worker     *pTime = file_stat.st_mtime;
3433*da0073e9SAndroid Build Coastguard Worker 
3434*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3435*da0073e9SAndroid Build Coastguard Worker }
3436*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
3437*da0073e9SAndroid Build Coastguard Worker 
mz_zip_set_file_times(const char * pFilename,MZ_TIME_T access_time,MZ_TIME_T modified_time)3438*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
3439*da0073e9SAndroid Build Coastguard Worker {
3440*da0073e9SAndroid Build Coastguard Worker     struct utimbuf t;
3441*da0073e9SAndroid Build Coastguard Worker 
3442*da0073e9SAndroid Build Coastguard Worker     memset(&t, 0, sizeof(t));
3443*da0073e9SAndroid Build Coastguard Worker     t.actime = access_time;
3444*da0073e9SAndroid Build Coastguard Worker     t.modtime = modified_time;
3445*da0073e9SAndroid Build Coastguard Worker 
3446*da0073e9SAndroid Build Coastguard Worker     return !utime(pFilename, &t);
3447*da0073e9SAndroid Build Coastguard Worker }
3448*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
3449*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_TIME */
3450*da0073e9SAndroid Build Coastguard Worker 
mz_zip_set_error(mz_zip_archive * pZip,mz_zip_error err_num)3451*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
3452*da0073e9SAndroid Build Coastguard Worker {
3453*da0073e9SAndroid Build Coastguard Worker     if (pZip)
3454*da0073e9SAndroid Build Coastguard Worker         pZip->m_last_error = err_num;
3455*da0073e9SAndroid Build Coastguard Worker     return MZ_FALSE;
3456*da0073e9SAndroid Build Coastguard Worker }
3457*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_init_internal(mz_zip_archive * pZip,mz_uint flags)3458*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
3459*da0073e9SAndroid Build Coastguard Worker {
3460*da0073e9SAndroid Build Coastguard Worker     (void)flags;
3461*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3462*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3463*da0073e9SAndroid Build Coastguard Worker 
3464*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_pAlloc)
3465*da0073e9SAndroid Build Coastguard Worker         pZip->m_pAlloc = miniz_def_alloc_func;
3466*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_pFree)
3467*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree = miniz_def_free_func;
3468*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_pRealloc)
3469*da0073e9SAndroid Build Coastguard Worker         pZip->m_pRealloc = miniz_def_realloc_func;
3470*da0073e9SAndroid Build Coastguard Worker 
3471*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = 0;
3472*da0073e9SAndroid Build Coastguard Worker     pZip->m_central_directory_file_ofs = 0;
3473*da0073e9SAndroid Build Coastguard Worker     pZip->m_total_files = 0;
3474*da0073e9SAndroid Build Coastguard Worker     pZip->m_last_error = MZ_ZIP_NO_ERROR;
3475*da0073e9SAndroid Build Coastguard Worker 
3476*da0073e9SAndroid Build Coastguard Worker     if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3477*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3478*da0073e9SAndroid Build Coastguard Worker 
3479*da0073e9SAndroid Build Coastguard Worker     memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3480*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3481*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3482*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3483*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_init_flags = flags;
3484*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_zip64 = MZ_FALSE;
3485*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
3486*da0073e9SAndroid Build Coastguard Worker 
3487*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3488*da0073e9SAndroid Build Coastguard Worker 
3489*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3490*da0073e9SAndroid Build Coastguard Worker }
3491*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_filename_less(const mz_zip_array * pCentral_dir_array,const mz_zip_array * pCentral_dir_offsets,mz_uint l_index,mz_uint r_index)3492*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
3493*da0073e9SAndroid Build Coastguard Worker {
3494*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3495*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
3496*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3497*da0073e9SAndroid Build Coastguard Worker     mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3498*da0073e9SAndroid Build Coastguard Worker     mz_uint8 l = 0, r = 0;
3499*da0073e9SAndroid Build Coastguard Worker     pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3500*da0073e9SAndroid Build Coastguard Worker     pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3501*da0073e9SAndroid Build Coastguard Worker     pE = pL + MZ_MIN(l_len, r_len);
3502*da0073e9SAndroid Build Coastguard Worker     while (pL < pE)
3503*da0073e9SAndroid Build Coastguard Worker     {
3504*da0073e9SAndroid Build Coastguard Worker         if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3505*da0073e9SAndroid Build Coastguard Worker             break;
3506*da0073e9SAndroid Build Coastguard Worker         pL++;
3507*da0073e9SAndroid Build Coastguard Worker         pR++;
3508*da0073e9SAndroid Build Coastguard Worker     }
3509*da0073e9SAndroid Build Coastguard Worker     return (pL == pE) ? (l_len < r_len) : (l < r);
3510*da0073e9SAndroid Build Coastguard Worker }
3511*da0073e9SAndroid Build Coastguard Worker 
3512*da0073e9SAndroid Build Coastguard Worker #define MZ_SWAP_UINT32(a, b) \
3513*da0073e9SAndroid Build Coastguard Worker     do                       \
3514*da0073e9SAndroid Build Coastguard Worker     {                        \
3515*da0073e9SAndroid Build Coastguard Worker         mz_uint32 t = a;     \
3516*da0073e9SAndroid Build Coastguard Worker         a = b;               \
3517*da0073e9SAndroid Build Coastguard Worker         b = t;               \
3518*da0073e9SAndroid Build Coastguard Worker     }                        \
3519*da0073e9SAndroid Build Coastguard Worker     MZ_MACRO_END
3520*da0073e9SAndroid Build Coastguard Worker 
3521*da0073e9SAndroid Build Coastguard Worker /* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */
mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive * pZip)3522*da0073e9SAndroid Build Coastguard Worker static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
3523*da0073e9SAndroid Build Coastguard Worker {
3524*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState = pZip->m_pState;
3525*da0073e9SAndroid Build Coastguard Worker     const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3526*da0073e9SAndroid Build Coastguard Worker     const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3527*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3528*da0073e9SAndroid Build Coastguard Worker     mz_uint32 *pIndices;
3529*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3530*da0073e9SAndroid Build Coastguard Worker     mz_uint32 start, end;
3531*da0073e9SAndroid Build Coastguard Worker     const mz_uint32 size = pZip->m_total_files;
3532*da0073e9SAndroid Build Coastguard Worker 
3533*da0073e9SAndroid Build Coastguard Worker     if (size <= 1U)
3534*da0073e9SAndroid Build Coastguard Worker         return;
3535*da0073e9SAndroid Build Coastguard Worker 
3536*da0073e9SAndroid Build Coastguard Worker     pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3537*da0073e9SAndroid Build Coastguard Worker 
3538*da0073e9SAndroid Build Coastguard Worker     start = (size - 2U) >> 1U;
3539*da0073e9SAndroid Build Coastguard Worker     for (;;)
3540*da0073e9SAndroid Build Coastguard Worker     {
3541*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3542*da0073e9SAndroid Build Coastguard Worker         mz_uint64 child, root = start;
3543*da0073e9SAndroid Build Coastguard Worker         for (;;)
3544*da0073e9SAndroid Build Coastguard Worker         {
3545*da0073e9SAndroid Build Coastguard Worker             if ((child = (root << 1U) + 1U) >= size)
3546*da0073e9SAndroid Build Coastguard Worker                 break;
3547*da0073e9SAndroid Build Coastguard Worker             child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3548*da0073e9SAndroid Build Coastguard Worker             if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3549*da0073e9SAndroid Build Coastguard Worker                 break;
3550*da0073e9SAndroid Build Coastguard Worker             MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3551*da0073e9SAndroid Build Coastguard Worker             root = child;
3552*da0073e9SAndroid Build Coastguard Worker         }
3553*da0073e9SAndroid Build Coastguard Worker         if (!start)
3554*da0073e9SAndroid Build Coastguard Worker             break;
3555*da0073e9SAndroid Build Coastguard Worker         start--;
3556*da0073e9SAndroid Build Coastguard Worker     }
3557*da0073e9SAndroid Build Coastguard Worker 
3558*da0073e9SAndroid Build Coastguard Worker     end = size - 1;
3559*da0073e9SAndroid Build Coastguard Worker     while (end > 0)
3560*da0073e9SAndroid Build Coastguard Worker     {
3561*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3562*da0073e9SAndroid Build Coastguard Worker         mz_uint64 child, root = 0;
3563*da0073e9SAndroid Build Coastguard Worker         MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3564*da0073e9SAndroid Build Coastguard Worker         for (;;)
3565*da0073e9SAndroid Build Coastguard Worker         {
3566*da0073e9SAndroid Build Coastguard Worker             if ((child = (root << 1U) + 1U) >= end)
3567*da0073e9SAndroid Build Coastguard Worker                 break;
3568*da0073e9SAndroid Build Coastguard Worker             child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3569*da0073e9SAndroid Build Coastguard Worker             if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3570*da0073e9SAndroid Build Coastguard Worker                 break;
3571*da0073e9SAndroid Build Coastguard Worker             MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3572*da0073e9SAndroid Build Coastguard Worker             root = child;
3573*da0073e9SAndroid Build Coastguard Worker         }
3574*da0073e9SAndroid Build Coastguard Worker         end--;
3575*da0073e9SAndroid Build Coastguard Worker     }
3576*da0073e9SAndroid Build Coastguard Worker }
3577*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_locate_header_sig(mz_zip_archive * pZip,mz_uint32 record_sig,mz_uint32 record_size,mz_int64 * pOfs)3578*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
3579*da0073e9SAndroid Build Coastguard Worker {
3580*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3581*da0073e9SAndroid Build Coastguard Worker     mz_int64 cur_file_ofs;
3582*da0073e9SAndroid Build Coastguard Worker     mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3583*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3584*da0073e9SAndroid Build Coastguard Worker 
3585*da0073e9SAndroid Build Coastguard Worker     /* Basic sanity checks - reject files which are too small */
3586*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_archive_size < record_size)
3587*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3588*da0073e9SAndroid Build Coastguard Worker 
3589*da0073e9SAndroid Build Coastguard Worker     /* Find the record by scanning the file from the end towards the beginning. */
3590*da0073e9SAndroid Build Coastguard Worker     cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3591*da0073e9SAndroid Build Coastguard Worker     for (;;)
3592*da0073e9SAndroid Build Coastguard Worker     {
3593*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3594*da0073e9SAndroid Build Coastguard Worker         int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3595*da0073e9SAndroid Build Coastguard Worker 
3596*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3597*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
3598*da0073e9SAndroid Build Coastguard Worker 
3599*da0073e9SAndroid Build Coastguard Worker         for (i = n - 4; i >= 0; --i)
3600*da0073e9SAndroid Build Coastguard Worker         {
3601*da0073e9SAndroid Build Coastguard Worker             mz_uint s = MZ_READ_LE32(pBuf + i);
3602*da0073e9SAndroid Build Coastguard Worker             if (s == record_sig)
3603*da0073e9SAndroid Build Coastguard Worker             {
3604*da0073e9SAndroid Build Coastguard Worker                 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3605*da0073e9SAndroid Build Coastguard Worker                     break;
3606*da0073e9SAndroid Build Coastguard Worker             }
3607*da0073e9SAndroid Build Coastguard Worker         }
3608*da0073e9SAndroid Build Coastguard Worker 
3609*da0073e9SAndroid Build Coastguard Worker         if (i >= 0)
3610*da0073e9SAndroid Build Coastguard Worker         {
3611*da0073e9SAndroid Build Coastguard Worker             cur_file_ofs += i;
3612*da0073e9SAndroid Build Coastguard Worker             break;
3613*da0073e9SAndroid Build Coastguard Worker         }
3614*da0073e9SAndroid Build Coastguard Worker 
3615*da0073e9SAndroid Build Coastguard Worker         /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
3616*da0073e9SAndroid Build Coastguard Worker         if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
3617*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
3618*da0073e9SAndroid Build Coastguard Worker 
3619*da0073e9SAndroid Build Coastguard Worker         cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3620*da0073e9SAndroid Build Coastguard Worker     }
3621*da0073e9SAndroid Build Coastguard Worker 
3622*da0073e9SAndroid Build Coastguard Worker     *pOfs = cur_file_ofs;
3623*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3624*da0073e9SAndroid Build Coastguard Worker }
3625*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_read_central_dir(mz_zip_archive * pZip,mz_uint flags)3626*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
3627*da0073e9SAndroid Build Coastguard Worker {
3628*da0073e9SAndroid Build Coastguard Worker     mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3629*da0073e9SAndroid Build Coastguard Worker     mz_uint64 cdir_ofs = 0;
3630*da0073e9SAndroid Build Coastguard Worker     mz_int64 cur_file_ofs = 0;
3631*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3632*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *p;
3633*da0073e9SAndroid Build Coastguard Worker 
3634*da0073e9SAndroid Build Coastguard Worker     mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3635*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3636*da0073e9SAndroid Build Coastguard Worker     mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3637*da0073e9SAndroid Build Coastguard Worker     mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3638*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3639*da0073e9SAndroid Build Coastguard Worker 
3640*da0073e9SAndroid Build Coastguard Worker     mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3641*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3642*da0073e9SAndroid Build Coastguard Worker 
3643*da0073e9SAndroid Build Coastguard Worker     mz_uint64 zip64_end_of_central_dir_ofs = 0;
3644*da0073e9SAndroid Build Coastguard Worker 
3645*da0073e9SAndroid Build Coastguard Worker     /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */
3646*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3647*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3648*da0073e9SAndroid Build Coastguard Worker 
3649*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
3650*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
3651*da0073e9SAndroid Build Coastguard Worker 
3652*da0073e9SAndroid Build Coastguard Worker     /* Read and verify the end of central directory record. */
3653*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3654*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3655*da0073e9SAndroid Build Coastguard Worker 
3656*da0073e9SAndroid Build Coastguard Worker     if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3657*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3658*da0073e9SAndroid Build Coastguard Worker 
3659*da0073e9SAndroid Build Coastguard Worker     if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3660*da0073e9SAndroid Build Coastguard Worker     {
3661*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
3662*da0073e9SAndroid Build Coastguard Worker         {
3663*da0073e9SAndroid Build Coastguard Worker             if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
3664*da0073e9SAndroid Build Coastguard Worker             {
3665*da0073e9SAndroid Build Coastguard Worker                 zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3666*da0073e9SAndroid Build Coastguard Worker                 if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3667*da0073e9SAndroid Build Coastguard Worker                     return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3668*da0073e9SAndroid Build Coastguard Worker 
3669*da0073e9SAndroid Build Coastguard Worker                 if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
3670*da0073e9SAndroid Build Coastguard Worker                 {
3671*da0073e9SAndroid Build Coastguard Worker                     if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
3672*da0073e9SAndroid Build Coastguard Worker                     {
3673*da0073e9SAndroid Build Coastguard Worker                         pZip->m_pState->m_zip64 = MZ_TRUE;
3674*da0073e9SAndroid Build Coastguard Worker                     }
3675*da0073e9SAndroid Build Coastguard Worker                 }
3676*da0073e9SAndroid Build Coastguard Worker             }
3677*da0073e9SAndroid Build Coastguard Worker         }
3678*da0073e9SAndroid Build Coastguard Worker     }
3679*da0073e9SAndroid Build Coastguard Worker 
3680*da0073e9SAndroid Build Coastguard Worker     pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3681*da0073e9SAndroid Build Coastguard Worker     cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3682*da0073e9SAndroid Build Coastguard Worker     num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3683*da0073e9SAndroid Build Coastguard Worker     cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3684*da0073e9SAndroid Build Coastguard Worker     cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3685*da0073e9SAndroid Build Coastguard Worker     cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3686*da0073e9SAndroid Build Coastguard Worker 
3687*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pState->m_zip64)
3688*da0073e9SAndroid Build Coastguard Worker     {
3689*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
3690*da0073e9SAndroid Build Coastguard Worker         mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3691*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
3692*da0073e9SAndroid Build Coastguard Worker         mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3693*da0073e9SAndroid Build Coastguard Worker         mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3694*da0073e9SAndroid Build Coastguard Worker         mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
3695*da0073e9SAndroid Build Coastguard Worker         mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3696*da0073e9SAndroid Build Coastguard Worker 
3697*da0073e9SAndroid Build Coastguard Worker         if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3698*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3699*da0073e9SAndroid Build Coastguard Worker 
3700*da0073e9SAndroid Build Coastguard Worker         if (zip64_total_num_of_disks != 1U)
3701*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3702*da0073e9SAndroid Build Coastguard Worker 
3703*da0073e9SAndroid Build Coastguard Worker         /* Check for miniz's practical limits */
3704*da0073e9SAndroid Build Coastguard Worker         if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3705*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3706*da0073e9SAndroid Build Coastguard Worker 
3707*da0073e9SAndroid Build Coastguard Worker         pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3708*da0073e9SAndroid Build Coastguard Worker 
3709*da0073e9SAndroid Build Coastguard Worker         if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3710*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3711*da0073e9SAndroid Build Coastguard Worker 
3712*da0073e9SAndroid Build Coastguard Worker         cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
3713*da0073e9SAndroid Build Coastguard Worker 
3714*da0073e9SAndroid Build Coastguard Worker         /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
3715*da0073e9SAndroid Build Coastguard Worker         if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3716*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
3717*da0073e9SAndroid Build Coastguard Worker 
3718*da0073e9SAndroid Build Coastguard Worker         cdir_size = (mz_uint32)zip64_size_of_central_directory;
3719*da0073e9SAndroid Build Coastguard Worker 
3720*da0073e9SAndroid Build Coastguard Worker         num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3721*da0073e9SAndroid Build Coastguard Worker 
3722*da0073e9SAndroid Build Coastguard Worker         cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3723*da0073e9SAndroid Build Coastguard Worker 
3724*da0073e9SAndroid Build Coastguard Worker         cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3725*da0073e9SAndroid Build Coastguard Worker     }
3726*da0073e9SAndroid Build Coastguard Worker 
3727*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_total_files != cdir_entries_on_this_disk)
3728*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3729*da0073e9SAndroid Build Coastguard Worker 
3730*da0073e9SAndroid Build Coastguard Worker     if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3731*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3732*da0073e9SAndroid Build Coastguard Worker 
3733*da0073e9SAndroid Build Coastguard Worker     if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3734*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3735*da0073e9SAndroid Build Coastguard Worker 
3736*da0073e9SAndroid Build Coastguard Worker     if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3737*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3738*da0073e9SAndroid Build Coastguard Worker 
3739*da0073e9SAndroid Build Coastguard Worker     pZip->m_central_directory_file_ofs = cdir_ofs;
3740*da0073e9SAndroid Build Coastguard Worker 
3741*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_total_files)
3742*da0073e9SAndroid Build Coastguard Worker     {
3743*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3744*da0073e9SAndroid Build Coastguard Worker         mz_uint i, n;
3745*da0073e9SAndroid Build Coastguard Worker         /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */
3746*da0073e9SAndroid Build Coastguard Worker         if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3747*da0073e9SAndroid Build Coastguard Worker             (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3748*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3749*da0073e9SAndroid Build Coastguard Worker 
3750*da0073e9SAndroid Build Coastguard Worker         if (sort_central_dir)
3751*da0073e9SAndroid Build Coastguard Worker         {
3752*da0073e9SAndroid Build Coastguard Worker             if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3753*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3754*da0073e9SAndroid Build Coastguard Worker         }
3755*da0073e9SAndroid Build Coastguard Worker 
3756*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3757*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3758*da0073e9SAndroid Build Coastguard Worker 
3759*da0073e9SAndroid Build Coastguard Worker         /* Now create an index into the central directory file records, do some basic sanity checking on each record */
3760*da0073e9SAndroid Build Coastguard Worker         p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3761*da0073e9SAndroid Build Coastguard Worker         for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3762*da0073e9SAndroid Build Coastguard Worker         {
3763*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3764*da0073e9SAndroid Build Coastguard Worker             mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3765*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3766*da0073e9SAndroid Build Coastguard Worker             mz_uint64 comp_size, decomp_size, local_header_ofs;
3767*da0073e9SAndroid Build Coastguard Worker 
3768*da0073e9SAndroid Build Coastguard Worker             if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3769*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3770*da0073e9SAndroid Build Coastguard Worker 
3771*da0073e9SAndroid Build Coastguard Worker             MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
3772*da0073e9SAndroid Build Coastguard Worker 
3773*da0073e9SAndroid Build Coastguard Worker             if (sort_central_dir)
3774*da0073e9SAndroid Build Coastguard Worker                 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3775*da0073e9SAndroid Build Coastguard Worker 
3776*da0073e9SAndroid Build Coastguard Worker             comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3777*da0073e9SAndroid Build Coastguard Worker             decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3778*da0073e9SAndroid Build Coastguard Worker             local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3779*da0073e9SAndroid Build Coastguard Worker             filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3780*da0073e9SAndroid Build Coastguard Worker             ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3781*da0073e9SAndroid Build Coastguard Worker 
3782*da0073e9SAndroid Build Coastguard Worker             if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
3783*da0073e9SAndroid Build Coastguard Worker                 (ext_data_size) &&
3784*da0073e9SAndroid Build Coastguard Worker                 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3785*da0073e9SAndroid Build Coastguard Worker             {
3786*da0073e9SAndroid Build Coastguard Worker                 /* Attempt to find zip64 extended information field in the entry's extra data */
3787*da0073e9SAndroid Build Coastguard Worker                 mz_uint32 extra_size_remaining = ext_data_size;
3788*da0073e9SAndroid Build Coastguard Worker 
3789*da0073e9SAndroid Build Coastguard Worker                 if (extra_size_remaining)
3790*da0073e9SAndroid Build Coastguard Worker                 {
3791*da0073e9SAndroid Build Coastguard Worker 					const mz_uint8 *pExtra_data;
3792*da0073e9SAndroid Build Coastguard Worker 					void* buf = NULL;
3793*da0073e9SAndroid Build Coastguard Worker 
3794*da0073e9SAndroid Build Coastguard Worker 					if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
3795*da0073e9SAndroid Build Coastguard Worker 					{
3796*da0073e9SAndroid Build Coastguard Worker 						buf = MZ_MALLOC(ext_data_size);
3797*da0073e9SAndroid Build Coastguard Worker 						if(buf==NULL)
3798*da0073e9SAndroid Build Coastguard Worker 							return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3799*da0073e9SAndroid Build Coastguard Worker 
3800*da0073e9SAndroid Build Coastguard Worker 						if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size)
3801*da0073e9SAndroid Build Coastguard Worker 						{
3802*da0073e9SAndroid Build Coastguard Worker 							MZ_FREE(buf);
3803*da0073e9SAndroid Build Coastguard Worker 							return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3804*da0073e9SAndroid Build Coastguard Worker 						}
3805*da0073e9SAndroid Build Coastguard Worker 
3806*da0073e9SAndroid Build Coastguard Worker 						pExtra_data = (mz_uint8*)buf;
3807*da0073e9SAndroid Build Coastguard Worker 					}
3808*da0073e9SAndroid Build Coastguard Worker 					else
3809*da0073e9SAndroid Build Coastguard Worker 					{
3810*da0073e9SAndroid Build Coastguard Worker 						pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3811*da0073e9SAndroid Build Coastguard Worker 					}
3812*da0073e9SAndroid Build Coastguard Worker 
3813*da0073e9SAndroid Build Coastguard Worker                     do
3814*da0073e9SAndroid Build Coastguard Worker                     {
3815*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3816*da0073e9SAndroid Build Coastguard Worker                         mz_uint32 field_id;
3817*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3818*da0073e9SAndroid Build Coastguard Worker                         mz_uint32 field_data_size;
3819*da0073e9SAndroid Build Coastguard Worker 
3820*da0073e9SAndroid Build Coastguard Worker 						if (extra_size_remaining < (sizeof(mz_uint16) * 2))
3821*da0073e9SAndroid Build Coastguard Worker 						{
3822*da0073e9SAndroid Build Coastguard Worker 							MZ_FREE(buf);
3823*da0073e9SAndroid Build Coastguard Worker 							return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3824*da0073e9SAndroid Build Coastguard Worker 						}
3825*da0073e9SAndroid Build Coastguard Worker 
3826*da0073e9SAndroid Build Coastguard Worker                         field_id = MZ_READ_LE16(pExtra_data);
3827*da0073e9SAndroid Build Coastguard Worker                         field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
3828*da0073e9SAndroid Build Coastguard Worker 
3829*da0073e9SAndroid Build Coastguard Worker 						if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
3830*da0073e9SAndroid Build Coastguard Worker 						{
3831*da0073e9SAndroid Build Coastguard Worker 							MZ_FREE(buf);
3832*da0073e9SAndroid Build Coastguard Worker 							return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3833*da0073e9SAndroid Build Coastguard Worker 						}
3834*da0073e9SAndroid Build Coastguard Worker 
3835*da0073e9SAndroid Build Coastguard Worker                         if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
3836*da0073e9SAndroid Build Coastguard Worker                         {
3837*da0073e9SAndroid Build Coastguard Worker                             /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */
3838*da0073e9SAndroid Build Coastguard Worker                             pZip->m_pState->m_zip64 = MZ_TRUE;
3839*da0073e9SAndroid Build Coastguard Worker                             pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
3840*da0073e9SAndroid Build Coastguard Worker                             break;
3841*da0073e9SAndroid Build Coastguard Worker                         }
3842*da0073e9SAndroid Build Coastguard Worker 
3843*da0073e9SAndroid Build Coastguard Worker                         pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
3844*da0073e9SAndroid Build Coastguard Worker                         extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
3845*da0073e9SAndroid Build Coastguard Worker                     } while (extra_size_remaining);
3846*da0073e9SAndroid Build Coastguard Worker 
3847*da0073e9SAndroid Build Coastguard Worker 					MZ_FREE(buf);
3848*da0073e9SAndroid Build Coastguard Worker                 }
3849*da0073e9SAndroid Build Coastguard Worker             }
3850*da0073e9SAndroid Build Coastguard Worker 
3851*da0073e9SAndroid Build Coastguard Worker             /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
3852*da0073e9SAndroid Build Coastguard Worker             if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3853*da0073e9SAndroid Build Coastguard Worker             {
3854*da0073e9SAndroid Build Coastguard Worker                 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3855*da0073e9SAndroid Build Coastguard Worker                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3856*da0073e9SAndroid Build Coastguard Worker             }
3857*da0073e9SAndroid Build Coastguard Worker 
3858*da0073e9SAndroid Build Coastguard Worker             disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3859*da0073e9SAndroid Build Coastguard Worker             if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3860*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3861*da0073e9SAndroid Build Coastguard Worker 
3862*da0073e9SAndroid Build Coastguard Worker             if (comp_size != MZ_UINT32_MAX)
3863*da0073e9SAndroid Build Coastguard Worker             {
3864*da0073e9SAndroid Build Coastguard Worker                 if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
3865*da0073e9SAndroid Build Coastguard Worker                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3866*da0073e9SAndroid Build Coastguard Worker             }
3867*da0073e9SAndroid Build Coastguard Worker 
3868*da0073e9SAndroid Build Coastguard Worker             bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3869*da0073e9SAndroid Build Coastguard Worker             if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
3870*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
3871*da0073e9SAndroid Build Coastguard Worker 
3872*da0073e9SAndroid Build Coastguard Worker             if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
3873*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3874*da0073e9SAndroid Build Coastguard Worker 
3875*da0073e9SAndroid Build Coastguard Worker             n -= total_header_size;
3876*da0073e9SAndroid Build Coastguard Worker             p += total_header_size;
3877*da0073e9SAndroid Build Coastguard Worker         }
3878*da0073e9SAndroid Build Coastguard Worker     }
3879*da0073e9SAndroid Build Coastguard Worker 
3880*da0073e9SAndroid Build Coastguard Worker     if (sort_central_dir)
3881*da0073e9SAndroid Build Coastguard Worker         mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3882*da0073e9SAndroid Build Coastguard Worker 
3883*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3884*da0073e9SAndroid Build Coastguard Worker }
3885*da0073e9SAndroid Build Coastguard Worker 
mz_zip_zero_struct(mz_zip_archive * pZip)3886*da0073e9SAndroid Build Coastguard Worker void mz_zip_zero_struct(mz_zip_archive *pZip)
3887*da0073e9SAndroid Build Coastguard Worker {
3888*da0073e9SAndroid Build Coastguard Worker     if (pZip)
3889*da0073e9SAndroid Build Coastguard Worker         MZ_CLEAR_OBJ(*pZip);
3890*da0073e9SAndroid Build Coastguard Worker }
3891*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_end_internal(mz_zip_archive * pZip,mz_bool set_last_error)3892*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
3893*da0073e9SAndroid Build Coastguard Worker {
3894*da0073e9SAndroid Build Coastguard Worker     mz_bool status = MZ_TRUE;
3895*da0073e9SAndroid Build Coastguard Worker 
3896*da0073e9SAndroid Build Coastguard Worker     if (!pZip)
3897*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3898*da0073e9SAndroid Build Coastguard Worker 
3899*da0073e9SAndroid Build Coastguard Worker     if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3900*da0073e9SAndroid Build Coastguard Worker     {
3901*da0073e9SAndroid Build Coastguard Worker         if (set_last_error)
3902*da0073e9SAndroid Build Coastguard Worker             pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
3903*da0073e9SAndroid Build Coastguard Worker 
3904*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3905*da0073e9SAndroid Build Coastguard Worker     }
3906*da0073e9SAndroid Build Coastguard Worker 
3907*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pState)
3908*da0073e9SAndroid Build Coastguard Worker     {
3909*da0073e9SAndroid Build Coastguard Worker         mz_zip_internal_state *pState = pZip->m_pState;
3910*da0073e9SAndroid Build Coastguard Worker         pZip->m_pState = NULL;
3911*da0073e9SAndroid Build Coastguard Worker 
3912*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_clear(pZip, &pState->m_central_dir);
3913*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3914*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3915*da0073e9SAndroid Build Coastguard Worker 
3916*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
3917*da0073e9SAndroid Build Coastguard Worker         if (pState->m_pFile)
3918*da0073e9SAndroid Build Coastguard Worker         {
3919*da0073e9SAndroid Build Coastguard Worker             if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
3920*da0073e9SAndroid Build Coastguard Worker             {
3921*da0073e9SAndroid Build Coastguard Worker                 if (MZ_FCLOSE(pState->m_pFile) == EOF)
3922*da0073e9SAndroid Build Coastguard Worker                 {
3923*da0073e9SAndroid Build Coastguard Worker                     if (set_last_error)
3924*da0073e9SAndroid Build Coastguard Worker                         pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
3925*da0073e9SAndroid Build Coastguard Worker                     status = MZ_FALSE;
3926*da0073e9SAndroid Build Coastguard Worker                 }
3927*da0073e9SAndroid Build Coastguard Worker             }
3928*da0073e9SAndroid Build Coastguard Worker             pState->m_pFile = NULL;
3929*da0073e9SAndroid Build Coastguard Worker         }
3930*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
3931*da0073e9SAndroid Build Coastguard Worker 
3932*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3933*da0073e9SAndroid Build Coastguard Worker     }
3934*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3935*da0073e9SAndroid Build Coastguard Worker 
3936*da0073e9SAndroid Build Coastguard Worker     return status;
3937*da0073e9SAndroid Build Coastguard Worker }
3938*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_end(mz_zip_archive * pZip)3939*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
3940*da0073e9SAndroid Build Coastguard Worker {
3941*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_end_internal(pZip, MZ_TRUE);
3942*da0073e9SAndroid Build Coastguard Worker }
mz_zip_reader_init(mz_zip_archive * pZip,mz_uint64 size,mz_uint flags)3943*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
3944*da0073e9SAndroid Build Coastguard Worker {
3945*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pRead))
3946*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3947*da0073e9SAndroid Build Coastguard Worker 
3948*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_init_internal(pZip, flags))
3949*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3950*da0073e9SAndroid Build Coastguard Worker 
3951*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_type = MZ_ZIP_TYPE_USER;
3952*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = size;
3953*da0073e9SAndroid Build Coastguard Worker 
3954*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_read_central_dir(pZip, flags))
3955*da0073e9SAndroid Build Coastguard Worker     {
3956*da0073e9SAndroid Build Coastguard Worker         mz_zip_reader_end_internal(pZip, MZ_FALSE);
3957*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3958*da0073e9SAndroid Build Coastguard Worker     }
3959*da0073e9SAndroid Build Coastguard Worker 
3960*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
3961*da0073e9SAndroid Build Coastguard Worker }
3962*da0073e9SAndroid Build Coastguard Worker 
mz_zip_mem_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)3963*da0073e9SAndroid Build Coastguard Worker static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3964*da0073e9SAndroid Build Coastguard Worker {
3965*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3966*da0073e9SAndroid Build Coastguard Worker     size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3967*da0073e9SAndroid Build Coastguard Worker     memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3968*da0073e9SAndroid Build Coastguard Worker     return s;
3969*da0073e9SAndroid Build Coastguard Worker }
3970*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_init_mem(mz_zip_archive * pZip,const void * pMem,size_t size,mz_uint flags)3971*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
3972*da0073e9SAndroid Build Coastguard Worker {
3973*da0073e9SAndroid Build Coastguard Worker     if (!pMem)
3974*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3975*da0073e9SAndroid Build Coastguard Worker 
3976*da0073e9SAndroid Build Coastguard Worker     if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3977*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3978*da0073e9SAndroid Build Coastguard Worker 
3979*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_init_internal(pZip, flags))
3980*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
3981*da0073e9SAndroid Build Coastguard Worker 
3982*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
3983*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = size;
3984*da0073e9SAndroid Build Coastguard Worker     pZip->m_pRead = mz_zip_mem_read_func;
3985*da0073e9SAndroid Build Coastguard Worker     pZip->m_pIO_opaque = pZip;
3986*da0073e9SAndroid Build Coastguard Worker     pZip->m_pNeeds_keepalive = NULL;
3987*da0073e9SAndroid Build Coastguard Worker 
3988*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
3989*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_pMem = const_cast<void *>(pMem);
3990*da0073e9SAndroid Build Coastguard Worker #else
3991*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_pMem = (void *)pMem;
3992*da0073e9SAndroid Build Coastguard Worker #endif
3993*da0073e9SAndroid Build Coastguard Worker 
3994*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_mem_size = size;
3995*da0073e9SAndroid Build Coastguard Worker 
3996*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_read_central_dir(pZip, flags))
3997*da0073e9SAndroid Build Coastguard Worker     {
3998*da0073e9SAndroid Build Coastguard Worker         mz_zip_reader_end_internal(pZip, MZ_FALSE);
3999*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4000*da0073e9SAndroid Build Coastguard Worker     }
4001*da0073e9SAndroid Build Coastguard Worker 
4002*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
4003*da0073e9SAndroid Build Coastguard Worker }
4004*da0073e9SAndroid Build Coastguard Worker 
4005*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
mz_zip_file_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)4006*da0073e9SAndroid Build Coastguard Worker static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
4007*da0073e9SAndroid Build Coastguard Worker {
4008*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4009*da0073e9SAndroid Build Coastguard Worker     mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
4010*da0073e9SAndroid Build Coastguard Worker 
4011*da0073e9SAndroid Build Coastguard Worker     file_ofs += pZip->m_pState->m_file_archive_start_ofs;
4012*da0073e9SAndroid Build Coastguard Worker 
4013*da0073e9SAndroid Build Coastguard Worker     if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
4014*da0073e9SAndroid Build Coastguard Worker         return 0;
4015*da0073e9SAndroid Build Coastguard Worker 
4016*da0073e9SAndroid Build Coastguard Worker     return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
4017*da0073e9SAndroid Build Coastguard Worker }
4018*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint32 flags)4019*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
4020*da0073e9SAndroid Build Coastguard Worker {
4021*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
4022*da0073e9SAndroid Build Coastguard Worker }
4023*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_init_file_v2(mz_zip_archive * pZip,const char * pFilename,mz_uint flags,mz_uint64 file_start_ofs,mz_uint64 archive_size)4024*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)
4025*da0073e9SAndroid Build Coastguard Worker {
4026*da0073e9SAndroid Build Coastguard Worker     mz_uint64 file_size;
4027*da0073e9SAndroid Build Coastguard Worker     MZ_FILE *pFile;
4028*da0073e9SAndroid Build Coastguard Worker 
4029*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
4030*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4031*da0073e9SAndroid Build Coastguard Worker 
4032*da0073e9SAndroid Build Coastguard Worker     pFile = MZ_FOPEN(pFilename, "rb");
4033*da0073e9SAndroid Build Coastguard Worker     if (!pFile)
4034*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4035*da0073e9SAndroid Build Coastguard Worker 
4036*da0073e9SAndroid Build Coastguard Worker     file_size = archive_size;
4037*da0073e9SAndroid Build Coastguard Worker     if (!file_size)
4038*da0073e9SAndroid Build Coastguard Worker     {
4039*da0073e9SAndroid Build Coastguard Worker         if (MZ_FSEEK64(pFile, 0, SEEK_END))
4040*da0073e9SAndroid Build Coastguard Worker         {
4041*da0073e9SAndroid Build Coastguard Worker             MZ_FCLOSE(pFile);
4042*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4043*da0073e9SAndroid Build Coastguard Worker         }
4044*da0073e9SAndroid Build Coastguard Worker 
4045*da0073e9SAndroid Build Coastguard Worker         file_size = MZ_FTELL64(pFile);
4046*da0073e9SAndroid Build Coastguard Worker     }
4047*da0073e9SAndroid Build Coastguard Worker 
4048*da0073e9SAndroid Build Coastguard Worker     /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
4049*da0073e9SAndroid Build Coastguard Worker 
4050*da0073e9SAndroid Build Coastguard Worker     if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4051*da0073e9SAndroid Build Coastguard Worker     {
4052*da0073e9SAndroid Build Coastguard Worker 	MZ_FCLOSE(pFile);
4053*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4054*da0073e9SAndroid Build Coastguard Worker     }
4055*da0073e9SAndroid Build Coastguard Worker 
4056*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_init_internal(pZip, flags))
4057*da0073e9SAndroid Build Coastguard Worker     {
4058*da0073e9SAndroid Build Coastguard Worker         MZ_FCLOSE(pFile);
4059*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4060*da0073e9SAndroid Build Coastguard Worker     }
4061*da0073e9SAndroid Build Coastguard Worker 
4062*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
4063*da0073e9SAndroid Build Coastguard Worker     pZip->m_pRead = mz_zip_file_read_func;
4064*da0073e9SAndroid Build Coastguard Worker     pZip->m_pIO_opaque = pZip;
4065*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_pFile = pFile;
4066*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = file_size;
4067*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
4068*da0073e9SAndroid Build Coastguard Worker 
4069*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_read_central_dir(pZip, flags))
4070*da0073e9SAndroid Build Coastguard Worker     {
4071*da0073e9SAndroid Build Coastguard Worker         mz_zip_reader_end_internal(pZip, MZ_FALSE);
4072*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4073*da0073e9SAndroid Build Coastguard Worker     }
4074*da0073e9SAndroid Build Coastguard Worker 
4075*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
4076*da0073e9SAndroid Build Coastguard Worker }
4077*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_init_cfile(mz_zip_archive * pZip,MZ_FILE * pFile,mz_uint64 archive_size,mz_uint flags)4078*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
4079*da0073e9SAndroid Build Coastguard Worker {
4080*da0073e9SAndroid Build Coastguard Worker     mz_uint64 cur_file_ofs;
4081*da0073e9SAndroid Build Coastguard Worker 
4082*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pFile))
4083*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4084*da0073e9SAndroid Build Coastguard Worker 
4085*da0073e9SAndroid Build Coastguard Worker     cur_file_ofs = MZ_FTELL64(pFile);
4086*da0073e9SAndroid Build Coastguard Worker 
4087*da0073e9SAndroid Build Coastguard Worker     if (!archive_size)
4088*da0073e9SAndroid Build Coastguard Worker     {
4089*da0073e9SAndroid Build Coastguard Worker         if (MZ_FSEEK64(pFile, 0, SEEK_END))
4090*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4091*da0073e9SAndroid Build Coastguard Worker 
4092*da0073e9SAndroid Build Coastguard Worker         archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
4093*da0073e9SAndroid Build Coastguard Worker 
4094*da0073e9SAndroid Build Coastguard Worker         if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4095*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4096*da0073e9SAndroid Build Coastguard Worker     }
4097*da0073e9SAndroid Build Coastguard Worker 
4098*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_init_internal(pZip, flags))
4099*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4100*da0073e9SAndroid Build Coastguard Worker 
4101*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
4102*da0073e9SAndroid Build Coastguard Worker     pZip->m_pRead = mz_zip_file_read_func;
4103*da0073e9SAndroid Build Coastguard Worker 
4104*da0073e9SAndroid Build Coastguard Worker     pZip->m_pIO_opaque = pZip;
4105*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_pFile = pFile;
4106*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = archive_size;
4107*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
4108*da0073e9SAndroid Build Coastguard Worker 
4109*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_read_central_dir(pZip, flags))
4110*da0073e9SAndroid Build Coastguard Worker     {
4111*da0073e9SAndroid Build Coastguard Worker         mz_zip_reader_end_internal(pZip, MZ_FALSE);
4112*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4113*da0073e9SAndroid Build Coastguard Worker     }
4114*da0073e9SAndroid Build Coastguard Worker 
4115*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
4116*da0073e9SAndroid Build Coastguard Worker }
4117*da0073e9SAndroid Build Coastguard Worker 
4118*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
4119*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_cdh(mz_zip_archive * pZip,mz_uint file_index)4120*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
4121*da0073e9SAndroid Build Coastguard Worker {
4122*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
4123*da0073e9SAndroid Build Coastguard Worker         return NULL;
4124*da0073e9SAndroid Build Coastguard Worker     return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
4125*da0073e9SAndroid Build Coastguard Worker }
4126*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_is_file_encrypted(mz_zip_archive * pZip,mz_uint file_index)4127*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
4128*da0073e9SAndroid Build Coastguard Worker {
4129*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4130*da0073e9SAndroid Build Coastguard Worker     mz_uint m_bit_flag;
4131*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4132*da0073e9SAndroid Build Coastguard Worker     if (!p)
4133*da0073e9SAndroid Build Coastguard Worker     {
4134*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4135*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4136*da0073e9SAndroid Build Coastguard Worker     }
4137*da0073e9SAndroid Build Coastguard Worker 
4138*da0073e9SAndroid Build Coastguard Worker     m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4139*da0073e9SAndroid Build Coastguard Worker     return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
4140*da0073e9SAndroid Build Coastguard Worker }
4141*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_is_file_supported(mz_zip_archive * pZip,mz_uint file_index)4142*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
4143*da0073e9SAndroid Build Coastguard Worker {
4144*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4145*da0073e9SAndroid Build Coastguard Worker     mz_uint bit_flag;
4146*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4147*da0073e9SAndroid Build Coastguard Worker     mz_uint method;
4148*da0073e9SAndroid Build Coastguard Worker 
4149*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4150*da0073e9SAndroid Build Coastguard Worker     if (!p)
4151*da0073e9SAndroid Build Coastguard Worker     {
4152*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4153*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4154*da0073e9SAndroid Build Coastguard Worker     }
4155*da0073e9SAndroid Build Coastguard Worker 
4156*da0073e9SAndroid Build Coastguard Worker     method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4157*da0073e9SAndroid Build Coastguard Worker     bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4158*da0073e9SAndroid Build Coastguard Worker 
4159*da0073e9SAndroid Build Coastguard Worker     if ((method != 0) && (method != MZ_DEFLATED))
4160*da0073e9SAndroid Build Coastguard Worker     {
4161*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4162*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4163*da0073e9SAndroid Build Coastguard Worker     }
4164*da0073e9SAndroid Build Coastguard Worker 
4165*da0073e9SAndroid Build Coastguard Worker     if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
4166*da0073e9SAndroid Build Coastguard Worker     {
4167*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4168*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4169*da0073e9SAndroid Build Coastguard Worker     }
4170*da0073e9SAndroid Build Coastguard Worker 
4171*da0073e9SAndroid Build Coastguard Worker     if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
4172*da0073e9SAndroid Build Coastguard Worker     {
4173*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
4174*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4175*da0073e9SAndroid Build Coastguard Worker     }
4176*da0073e9SAndroid Build Coastguard Worker 
4177*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
4178*da0073e9SAndroid Build Coastguard Worker }
4179*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_is_file_a_directory(mz_zip_archive * pZip,mz_uint file_index)4180*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
4181*da0073e9SAndroid Build Coastguard Worker {
4182*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4183*da0073e9SAndroid Build Coastguard Worker     mz_uint filename_len, attribute_mapping_id, external_attr;
4184*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4185*da0073e9SAndroid Build Coastguard Worker     if (!p)
4186*da0073e9SAndroid Build Coastguard Worker     {
4187*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4188*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4189*da0073e9SAndroid Build Coastguard Worker     }
4190*da0073e9SAndroid Build Coastguard Worker 
4191*da0073e9SAndroid Build Coastguard Worker     filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4192*da0073e9SAndroid Build Coastguard Worker     if (filename_len)
4193*da0073e9SAndroid Build Coastguard Worker     {
4194*da0073e9SAndroid Build Coastguard Worker         if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
4195*da0073e9SAndroid Build Coastguard Worker             return MZ_TRUE;
4196*da0073e9SAndroid Build Coastguard Worker     }
4197*da0073e9SAndroid Build Coastguard Worker 
4198*da0073e9SAndroid Build Coastguard Worker     /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
4199*da0073e9SAndroid Build Coastguard Worker     /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */
4200*da0073e9SAndroid Build Coastguard Worker     /* FIXME: Remove this check? Is it necessary - we already check the filename. */
4201*da0073e9SAndroid Build Coastguard Worker     attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4202*da0073e9SAndroid Build Coastguard Worker     (void)attribute_mapping_id;
4203*da0073e9SAndroid Build Coastguard Worker 
4204*da0073e9SAndroid Build Coastguard Worker     external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4205*da0073e9SAndroid Build Coastguard Worker     if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4206*da0073e9SAndroid Build Coastguard Worker     {
4207*da0073e9SAndroid Build Coastguard Worker         return MZ_TRUE;
4208*da0073e9SAndroid Build Coastguard Worker     }
4209*da0073e9SAndroid Build Coastguard Worker 
4210*da0073e9SAndroid Build Coastguard Worker     return MZ_FALSE;
4211*da0073e9SAndroid Build Coastguard Worker }
4212*da0073e9SAndroid Build Coastguard Worker 
mz_zip_file_stat_internal(mz_zip_archive * pZip,mz_uint file_index,const mz_uint8 * pCentral_dir_header,mz_zip_archive_file_stat * pStat,mz_bool * pFound_zip64_extra_data)4213*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)
4214*da0073e9SAndroid Build Coastguard Worker {
4215*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4216*da0073e9SAndroid Build Coastguard Worker     mz_uint n;
4217*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *p = pCentral_dir_header;
4218*da0073e9SAndroid Build Coastguard Worker 
4219*da0073e9SAndroid Build Coastguard Worker     if (pFound_zip64_extra_data)
4220*da0073e9SAndroid Build Coastguard Worker         *pFound_zip64_extra_data = MZ_FALSE;
4221*da0073e9SAndroid Build Coastguard Worker 
4222*da0073e9SAndroid Build Coastguard Worker     if ((!p) || (!pStat))
4223*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4224*da0073e9SAndroid Build Coastguard Worker 
4225*da0073e9SAndroid Build Coastguard Worker     /* Extract fields from the central directory record. */
4226*da0073e9SAndroid Build Coastguard Worker     pStat->m_file_index = file_index;
4227*da0073e9SAndroid Build Coastguard Worker     pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
4228*da0073e9SAndroid Build Coastguard Worker     pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
4229*da0073e9SAndroid Build Coastguard Worker     pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
4230*da0073e9SAndroid Build Coastguard Worker     pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4231*da0073e9SAndroid Build Coastguard Worker     pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4232*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
4233*da0073e9SAndroid Build Coastguard Worker     pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
4234*da0073e9SAndroid Build Coastguard Worker #endif
4235*da0073e9SAndroid Build Coastguard Worker     pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
4236*da0073e9SAndroid Build Coastguard Worker     pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4237*da0073e9SAndroid Build Coastguard Worker     pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4238*da0073e9SAndroid Build Coastguard Worker     pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
4239*da0073e9SAndroid Build Coastguard Worker     pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4240*da0073e9SAndroid Build Coastguard Worker     pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4241*da0073e9SAndroid Build Coastguard Worker 
4242*da0073e9SAndroid Build Coastguard Worker     /* Copy as much of the filename and comment as possible. */
4243*da0073e9SAndroid Build Coastguard Worker     n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4244*da0073e9SAndroid Build Coastguard Worker     n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
4245*da0073e9SAndroid Build Coastguard Worker     memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4246*da0073e9SAndroid Build Coastguard Worker     pStat->m_filename[n] = '\0';
4247*da0073e9SAndroid Build Coastguard Worker 
4248*da0073e9SAndroid Build Coastguard Worker     n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4249*da0073e9SAndroid Build Coastguard Worker     n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
4250*da0073e9SAndroid Build Coastguard Worker     pStat->m_comment_size = n;
4251*da0073e9SAndroid Build Coastguard Worker     memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n);
4252*da0073e9SAndroid Build Coastguard Worker     pStat->m_comment[n] = '\0';
4253*da0073e9SAndroid Build Coastguard Worker 
4254*da0073e9SAndroid Build Coastguard Worker     /* Set some flags for convienance */
4255*da0073e9SAndroid Build Coastguard Worker     pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4256*da0073e9SAndroid Build Coastguard Worker     pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4257*da0073e9SAndroid Build Coastguard Worker     pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
4258*da0073e9SAndroid Build Coastguard Worker 
4259*da0073e9SAndroid Build Coastguard Worker     /* See if we need to read any zip64 extended information fields. */
4260*da0073e9SAndroid Build Coastguard Worker     /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */
4261*da0073e9SAndroid Build Coastguard Worker     if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
4262*da0073e9SAndroid Build Coastguard Worker     {
4263*da0073e9SAndroid Build Coastguard Worker         /* Attempt to find zip64 extended information field in the entry's extra data */
4264*da0073e9SAndroid Build Coastguard Worker         mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4265*da0073e9SAndroid Build Coastguard Worker 
4266*da0073e9SAndroid Build Coastguard Worker         if (extra_size_remaining)
4267*da0073e9SAndroid Build Coastguard Worker         {
4268*da0073e9SAndroid Build Coastguard Worker             const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4269*da0073e9SAndroid Build Coastguard Worker 
4270*da0073e9SAndroid Build Coastguard Worker             do
4271*da0073e9SAndroid Build Coastguard Worker             {
4272*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4273*da0073e9SAndroid Build Coastguard Worker                 mz_uint32 field_id;
4274*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4275*da0073e9SAndroid Build Coastguard Worker                 mz_uint32 field_data_size;
4276*da0073e9SAndroid Build Coastguard Worker 
4277*da0073e9SAndroid Build Coastguard Worker                 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4278*da0073e9SAndroid Build Coastguard Worker                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4279*da0073e9SAndroid Build Coastguard Worker 
4280*da0073e9SAndroid Build Coastguard Worker                 field_id = MZ_READ_LE16(pExtra_data);
4281*da0073e9SAndroid Build Coastguard Worker                 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4282*da0073e9SAndroid Build Coastguard Worker 
4283*da0073e9SAndroid Build Coastguard Worker                 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
4284*da0073e9SAndroid Build Coastguard Worker                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4285*da0073e9SAndroid Build Coastguard Worker 
4286*da0073e9SAndroid Build Coastguard Worker                 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
4287*da0073e9SAndroid Build Coastguard Worker                 {
4288*da0073e9SAndroid Build Coastguard Worker                     const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
4289*da0073e9SAndroid Build Coastguard Worker                     mz_uint32 field_data_remaining = field_data_size;
4290*da0073e9SAndroid Build Coastguard Worker 
4291*da0073e9SAndroid Build Coastguard Worker                     if (pFound_zip64_extra_data)
4292*da0073e9SAndroid Build Coastguard Worker                         *pFound_zip64_extra_data = MZ_TRUE;
4293*da0073e9SAndroid Build Coastguard Worker 
4294*da0073e9SAndroid Build Coastguard Worker                     if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4295*da0073e9SAndroid Build Coastguard Worker                     {
4296*da0073e9SAndroid Build Coastguard Worker                         if (field_data_remaining < sizeof(mz_uint64))
4297*da0073e9SAndroid Build Coastguard Worker                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4298*da0073e9SAndroid Build Coastguard Worker 
4299*da0073e9SAndroid Build Coastguard Worker                         pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4300*da0073e9SAndroid Build Coastguard Worker                         pField_data += sizeof(mz_uint64);
4301*da0073e9SAndroid Build Coastguard Worker                         field_data_remaining -= sizeof(mz_uint64);
4302*da0073e9SAndroid Build Coastguard Worker                     }
4303*da0073e9SAndroid Build Coastguard Worker 
4304*da0073e9SAndroid Build Coastguard Worker                     if (pStat->m_comp_size == MZ_UINT32_MAX)
4305*da0073e9SAndroid Build Coastguard Worker                     {
4306*da0073e9SAndroid Build Coastguard Worker                         if (field_data_remaining < sizeof(mz_uint64))
4307*da0073e9SAndroid Build Coastguard Worker                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4308*da0073e9SAndroid Build Coastguard Worker 
4309*da0073e9SAndroid Build Coastguard Worker                         pStat->m_comp_size = MZ_READ_LE64(pField_data);
4310*da0073e9SAndroid Build Coastguard Worker                         pField_data += sizeof(mz_uint64);
4311*da0073e9SAndroid Build Coastguard Worker                         field_data_remaining -= sizeof(mz_uint64);
4312*da0073e9SAndroid Build Coastguard Worker                     }
4313*da0073e9SAndroid Build Coastguard Worker 
4314*da0073e9SAndroid Build Coastguard Worker                     if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4315*da0073e9SAndroid Build Coastguard Worker                     {
4316*da0073e9SAndroid Build Coastguard Worker                         if (field_data_remaining < sizeof(mz_uint64))
4317*da0073e9SAndroid Build Coastguard Worker                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4318*da0073e9SAndroid Build Coastguard Worker 
4319*da0073e9SAndroid Build Coastguard Worker                         pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4320*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
4321*da0073e9SAndroid Build Coastguard Worker                         pField_data += sizeof(mz_uint64);
4322*da0073e9SAndroid Build Coastguard Worker                         // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
4323*da0073e9SAndroid Build Coastguard Worker                         field_data_remaining -= sizeof(mz_uint64);
4324*da0073e9SAndroid Build Coastguard Worker                     }
4325*da0073e9SAndroid Build Coastguard Worker 
4326*da0073e9SAndroid Build Coastguard Worker                     break;
4327*da0073e9SAndroid Build Coastguard Worker                 }
4328*da0073e9SAndroid Build Coastguard Worker 
4329*da0073e9SAndroid Build Coastguard Worker                 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4330*da0073e9SAndroid Build Coastguard Worker                 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4331*da0073e9SAndroid Build Coastguard Worker             } while (extra_size_remaining);
4332*da0073e9SAndroid Build Coastguard Worker         }
4333*da0073e9SAndroid Build Coastguard Worker     }
4334*da0073e9SAndroid Build Coastguard Worker 
4335*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
4336*da0073e9SAndroid Build Coastguard Worker }
4337*da0073e9SAndroid Build Coastguard Worker 
mz_zip_string_equal(const char * pA,const char * pB,mz_uint len,mz_uint flags)4338*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
4339*da0073e9SAndroid Build Coastguard Worker {
4340*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4341*da0073e9SAndroid Build Coastguard Worker     mz_uint i;
4342*da0073e9SAndroid Build Coastguard Worker     if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4343*da0073e9SAndroid Build Coastguard Worker         return 0 == memcmp(pA, pB, len);
4344*da0073e9SAndroid Build Coastguard Worker     for (i = 0; i < len; ++i)
4345*da0073e9SAndroid Build Coastguard Worker         if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4346*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
4347*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
4348*da0073e9SAndroid Build Coastguard Worker }
4349*da0073e9SAndroid Build Coastguard Worker 
mz_zip_filename_compare(const mz_zip_array * pCentral_dir_array,const mz_zip_array * pCentral_dir_offsets,mz_uint l_index,const char * pR,mz_uint r_len)4350*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
4351*da0073e9SAndroid Build Coastguard Worker {
4352*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4353*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
4354*da0073e9SAndroid Build Coastguard Worker     mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4355*da0073e9SAndroid Build Coastguard Worker     mz_uint8 l = 0, r = 0;
4356*da0073e9SAndroid Build Coastguard Worker     pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4357*da0073e9SAndroid Build Coastguard Worker     pE = pL + MZ_MIN(l_len, r_len);
4358*da0073e9SAndroid Build Coastguard Worker     while (pL < pE)
4359*da0073e9SAndroid Build Coastguard Worker     {
4360*da0073e9SAndroid Build Coastguard Worker         if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4361*da0073e9SAndroid Build Coastguard Worker             break;
4362*da0073e9SAndroid Build Coastguard Worker         pL++;
4363*da0073e9SAndroid Build Coastguard Worker         pR++;
4364*da0073e9SAndroid Build Coastguard Worker     }
4365*da0073e9SAndroid Build Coastguard Worker     return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4366*da0073e9SAndroid Build Coastguard Worker }
4367*da0073e9SAndroid Build Coastguard Worker 
mz_zip_locate_file_binary_search(mz_zip_archive * pZip,const char * pFilename,mz_uint32 * pIndex)4368*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
4369*da0073e9SAndroid Build Coastguard Worker {
4370*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState = pZip->m_pState;
4371*da0073e9SAndroid Build Coastguard Worker     const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4372*da0073e9SAndroid Build Coastguard Worker     const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4373*da0073e9SAndroid Build Coastguard Worker     mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4374*da0073e9SAndroid Build Coastguard Worker     const uint32_t size = pZip->m_total_files;
4375*da0073e9SAndroid Build Coastguard Worker     const mz_uint filename_len = (mz_uint)strlen(pFilename);
4376*da0073e9SAndroid Build Coastguard Worker 
4377*da0073e9SAndroid Build Coastguard Worker     if (pIndex)
4378*da0073e9SAndroid Build Coastguard Worker         *pIndex = 0;
4379*da0073e9SAndroid Build Coastguard Worker 
4380*da0073e9SAndroid Build Coastguard Worker     if (size)
4381*da0073e9SAndroid Build Coastguard Worker     {
4382*da0073e9SAndroid Build Coastguard Worker         /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
4383*da0073e9SAndroid Build Coastguard Worker         /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
4384*da0073e9SAndroid Build Coastguard Worker         mz_int64 l = 0, h = (mz_int64)size - 1;
4385*da0073e9SAndroid Build Coastguard Worker 
4386*da0073e9SAndroid Build Coastguard Worker         while (l <= h)
4387*da0073e9SAndroid Build Coastguard Worker         {
4388*da0073e9SAndroid Build Coastguard Worker             mz_int64 m = l + ((h - l) >> 1);
4389*da0073e9SAndroid Build Coastguard Worker             uint32_t file_index = pIndices[(uint32_t)m];
4390*da0073e9SAndroid Build Coastguard Worker 
4391*da0073e9SAndroid Build Coastguard Worker             int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4392*da0073e9SAndroid Build Coastguard Worker             if (!comp)
4393*da0073e9SAndroid Build Coastguard Worker             {
4394*da0073e9SAndroid Build Coastguard Worker                 if (pIndex)
4395*da0073e9SAndroid Build Coastguard Worker                     *pIndex = file_index;
4396*da0073e9SAndroid Build Coastguard Worker                 return MZ_TRUE;
4397*da0073e9SAndroid Build Coastguard Worker             }
4398*da0073e9SAndroid Build Coastguard Worker             else if (comp < 0)
4399*da0073e9SAndroid Build Coastguard Worker                 l = m + 1;
4400*da0073e9SAndroid Build Coastguard Worker             else
4401*da0073e9SAndroid Build Coastguard Worker                 h = m - 1;
4402*da0073e9SAndroid Build Coastguard Worker         }
4403*da0073e9SAndroid Build Coastguard Worker     }
4404*da0073e9SAndroid Build Coastguard Worker 
4405*da0073e9SAndroid Build Coastguard Worker     return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4406*da0073e9SAndroid Build Coastguard Worker }
4407*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_locate_file(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags)4408*da0073e9SAndroid Build Coastguard Worker int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
4409*da0073e9SAndroid Build Coastguard Worker {
4410*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4411*da0073e9SAndroid Build Coastguard Worker     mz_uint32 index;
4412*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4413*da0073e9SAndroid Build Coastguard Worker         return -1;
4414*da0073e9SAndroid Build Coastguard Worker     else
4415*da0073e9SAndroid Build Coastguard Worker         return (int)index;
4416*da0073e9SAndroid Build Coastguard Worker }
4417*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_locate_file_v2(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags,mz_uint32 * pIndex)4418*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
4419*da0073e9SAndroid Build Coastguard Worker {
4420*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4421*da0073e9SAndroid Build Coastguard Worker     mz_uint file_index;
4422*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4423*da0073e9SAndroid Build Coastguard Worker     size_t name_len, comment_len;
4424*da0073e9SAndroid Build Coastguard Worker 
4425*da0073e9SAndroid Build Coastguard Worker     if (pIndex)
4426*da0073e9SAndroid Build Coastguard Worker         *pIndex = 0;
4427*da0073e9SAndroid Build Coastguard Worker 
4428*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (!pName))
4429*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4430*da0073e9SAndroid Build Coastguard Worker 
4431*da0073e9SAndroid Build Coastguard Worker     /* See if we can use a binary search */
4432*da0073e9SAndroid Build Coastguard Worker     if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
4433*da0073e9SAndroid Build Coastguard Worker         (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4434*da0073e9SAndroid Build Coastguard Worker         ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
4435*da0073e9SAndroid Build Coastguard Worker     {
4436*da0073e9SAndroid Build Coastguard Worker         return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4437*da0073e9SAndroid Build Coastguard Worker     }
4438*da0073e9SAndroid Build Coastguard Worker 
4439*da0073e9SAndroid Build Coastguard Worker     /* Locate the entry by scanning the entire central directory */
4440*da0073e9SAndroid Build Coastguard Worker     name_len = strlen(pName);
4441*da0073e9SAndroid Build Coastguard Worker     if (name_len > MZ_UINT16_MAX)
4442*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4443*da0073e9SAndroid Build Coastguard Worker 
4444*da0073e9SAndroid Build Coastguard Worker     comment_len = pComment ? strlen(pComment) : 0;
4445*da0073e9SAndroid Build Coastguard Worker     if (comment_len > MZ_UINT16_MAX)
4446*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4447*da0073e9SAndroid Build Coastguard Worker 
4448*da0073e9SAndroid Build Coastguard Worker     for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4449*da0073e9SAndroid Build Coastguard Worker     {
4450*da0073e9SAndroid Build Coastguard Worker         const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
4451*da0073e9SAndroid Build Coastguard Worker         mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4452*da0073e9SAndroid Build Coastguard Worker         const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4453*da0073e9SAndroid Build Coastguard Worker         if (filename_len < name_len)
4454*da0073e9SAndroid Build Coastguard Worker             continue;
4455*da0073e9SAndroid Build Coastguard Worker         if (comment_len)
4456*da0073e9SAndroid Build Coastguard Worker         {
4457*da0073e9SAndroid Build Coastguard Worker             mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4458*da0073e9SAndroid Build Coastguard Worker             const char *pFile_comment = pFilename + filename_len + file_extra_len;
4459*da0073e9SAndroid Build Coastguard Worker             if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4460*da0073e9SAndroid Build Coastguard Worker                 continue;
4461*da0073e9SAndroid Build Coastguard Worker         }
4462*da0073e9SAndroid Build Coastguard Worker         if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4463*da0073e9SAndroid Build Coastguard Worker         {
4464*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
4465*da0073e9SAndroid Build Coastguard Worker             int ofs = filename_len - 1;
4466*da0073e9SAndroid Build Coastguard Worker             do
4467*da0073e9SAndroid Build Coastguard Worker             {
4468*da0073e9SAndroid Build Coastguard Worker                 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
4469*da0073e9SAndroid Build Coastguard Worker                     break;
4470*da0073e9SAndroid Build Coastguard Worker             } while (--ofs >= 0);
4471*da0073e9SAndroid Build Coastguard Worker             ofs++;
4472*da0073e9SAndroid Build Coastguard Worker             pFilename += ofs;
4473*da0073e9SAndroid Build Coastguard Worker             filename_len -= ofs;
4474*da0073e9SAndroid Build Coastguard Worker         }
4475*da0073e9SAndroid Build Coastguard Worker         if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4476*da0073e9SAndroid Build Coastguard Worker         {
4477*da0073e9SAndroid Build Coastguard Worker             if (pIndex)
4478*da0073e9SAndroid Build Coastguard Worker                 *pIndex = file_index;
4479*da0073e9SAndroid Build Coastguard Worker             return MZ_TRUE;
4480*da0073e9SAndroid Build Coastguard Worker         }
4481*da0073e9SAndroid Build Coastguard Worker     }
4482*da0073e9SAndroid Build Coastguard Worker 
4483*da0073e9SAndroid Build Coastguard Worker     return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4484*da0073e9SAndroid Build Coastguard Worker }
4485*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags,void * pUser_read_buf,size_t user_read_buf_size)4486*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4487*da0073e9SAndroid Build Coastguard Worker {
4488*da0073e9SAndroid Build Coastguard Worker     int status = TINFL_STATUS_DONE;
4489*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4490*da0073e9SAndroid Build Coastguard Worker     mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4491*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive_file_stat file_stat;
4492*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4493*da0073e9SAndroid Build Coastguard Worker     void *pRead_buf;
4494*da0073e9SAndroid Build Coastguard Worker     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4495*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4496*da0073e9SAndroid Build Coastguard Worker     tinfl_decompressor inflator;
4497*da0073e9SAndroid Build Coastguard Worker 
4498*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4499*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4500*da0073e9SAndroid Build Coastguard Worker 
4501*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4502*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4503*da0073e9SAndroid Build Coastguard Worker 
4504*da0073e9SAndroid Build Coastguard Worker     /* A directory or zero length file */
4505*da0073e9SAndroid Build Coastguard Worker     if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4506*da0073e9SAndroid Build Coastguard Worker         return MZ_TRUE;
4507*da0073e9SAndroid Build Coastguard Worker 
4508*da0073e9SAndroid Build Coastguard Worker     /* Encryption and patch files are not supported. */
4509*da0073e9SAndroid Build Coastguard Worker     if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4510*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4511*da0073e9SAndroid Build Coastguard Worker 
4512*da0073e9SAndroid Build Coastguard Worker     /* This function only supports decompressing stored and deflate. */
4513*da0073e9SAndroid Build Coastguard Worker     if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4514*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4515*da0073e9SAndroid Build Coastguard Worker 
4516*da0073e9SAndroid Build Coastguard Worker     /* Ensure supplied output buffer is large enough. */
4517*da0073e9SAndroid Build Coastguard Worker     needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4518*da0073e9SAndroid Build Coastguard Worker     if (buf_size < needed_size)
4519*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
4520*da0073e9SAndroid Build Coastguard Worker 
4521*da0073e9SAndroid Build Coastguard Worker     /* Read and parse the local directory entry. */
4522*da0073e9SAndroid Build Coastguard Worker     cur_file_ofs = file_stat.m_local_header_ofs;
4523*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4524*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4525*da0073e9SAndroid Build Coastguard Worker 
4526*da0073e9SAndroid Build Coastguard Worker     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4527*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4528*da0073e9SAndroid Build Coastguard Worker 
4529*da0073e9SAndroid Build Coastguard Worker     cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4530*da0073e9SAndroid Build Coastguard Worker     if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4531*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4532*da0073e9SAndroid Build Coastguard Worker 
4533*da0073e9SAndroid Build Coastguard Worker     if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4534*da0073e9SAndroid Build Coastguard Worker     {
4535*da0073e9SAndroid Build Coastguard Worker         /* The file is stored or the caller has requested the compressed data. */
4536*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
4537*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4538*da0073e9SAndroid Build Coastguard Worker 
4539*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4540*da0073e9SAndroid Build Coastguard Worker         if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4541*da0073e9SAndroid Build Coastguard Worker         {
4542*da0073e9SAndroid Build Coastguard Worker             if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4543*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4544*da0073e9SAndroid Build Coastguard Worker         }
4545*da0073e9SAndroid Build Coastguard Worker #endif
4546*da0073e9SAndroid Build Coastguard Worker 
4547*da0073e9SAndroid Build Coastguard Worker         return MZ_TRUE;
4548*da0073e9SAndroid Build Coastguard Worker     }
4549*da0073e9SAndroid Build Coastguard Worker 
4550*da0073e9SAndroid Build Coastguard Worker     /* Decompress the file either directly from memory or from a file input buffer. */
4551*da0073e9SAndroid Build Coastguard Worker     tinfl_init(&inflator);
4552*da0073e9SAndroid Build Coastguard Worker 
4553*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pState->m_pMem)
4554*da0073e9SAndroid Build Coastguard Worker     {
4555*da0073e9SAndroid Build Coastguard Worker         /* Read directly from the archive in memory. */
4556*da0073e9SAndroid Build Coastguard Worker         pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4557*da0073e9SAndroid Build Coastguard Worker         read_buf_size = read_buf_avail = file_stat.m_comp_size;
4558*da0073e9SAndroid Build Coastguard Worker         comp_remaining = 0;
4559*da0073e9SAndroid Build Coastguard Worker     }
4560*da0073e9SAndroid Build Coastguard Worker     else if (pUser_read_buf)
4561*da0073e9SAndroid Build Coastguard Worker     {
4562*da0073e9SAndroid Build Coastguard Worker         /* Use a user provided read buffer. */
4563*da0073e9SAndroid Build Coastguard Worker         if (!user_read_buf_size)
4564*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
4565*da0073e9SAndroid Build Coastguard Worker         pRead_buf = (mz_uint8 *)pUser_read_buf;
4566*da0073e9SAndroid Build Coastguard Worker         read_buf_size = user_read_buf_size;
4567*da0073e9SAndroid Build Coastguard Worker         read_buf_avail = 0;
4568*da0073e9SAndroid Build Coastguard Worker         comp_remaining = file_stat.m_comp_size;
4569*da0073e9SAndroid Build Coastguard Worker     }
4570*da0073e9SAndroid Build Coastguard Worker     else
4571*da0073e9SAndroid Build Coastguard Worker     {
4572*da0073e9SAndroid Build Coastguard Worker         /* Temporarily allocate a read buffer. */
4573*da0073e9SAndroid Build Coastguard Worker         read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4574*da0073e9SAndroid Build Coastguard Worker         if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4575*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4576*da0073e9SAndroid Build Coastguard Worker 
4577*da0073e9SAndroid Build Coastguard Worker         if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4578*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4579*da0073e9SAndroid Build Coastguard Worker 
4580*da0073e9SAndroid Build Coastguard Worker         read_buf_avail = 0;
4581*da0073e9SAndroid Build Coastguard Worker         comp_remaining = file_stat.m_comp_size;
4582*da0073e9SAndroid Build Coastguard Worker     }
4583*da0073e9SAndroid Build Coastguard Worker 
4584*da0073e9SAndroid Build Coastguard Worker     do
4585*da0073e9SAndroid Build Coastguard Worker     {
4586*da0073e9SAndroid Build Coastguard Worker         /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
4587*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4588*da0073e9SAndroid Build Coastguard Worker         size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4589*da0073e9SAndroid Build Coastguard Worker         if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4590*da0073e9SAndroid Build Coastguard Worker         {
4591*da0073e9SAndroid Build Coastguard Worker             read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4592*da0073e9SAndroid Build Coastguard Worker             if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4593*da0073e9SAndroid Build Coastguard Worker             {
4594*da0073e9SAndroid Build Coastguard Worker                 status = TINFL_STATUS_FAILED;
4595*da0073e9SAndroid Build Coastguard Worker                 mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4596*da0073e9SAndroid Build Coastguard Worker                 break;
4597*da0073e9SAndroid Build Coastguard Worker             }
4598*da0073e9SAndroid Build Coastguard Worker             cur_file_ofs += read_buf_avail;
4599*da0073e9SAndroid Build Coastguard Worker             comp_remaining -= read_buf_avail;
4600*da0073e9SAndroid Build Coastguard Worker             read_buf_ofs = 0;
4601*da0073e9SAndroid Build Coastguard Worker         }
4602*da0073e9SAndroid Build Coastguard Worker         in_buf_size = (size_t)read_buf_avail;
4603*da0073e9SAndroid Build Coastguard Worker         status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
4604*da0073e9SAndroid Build Coastguard Worker         read_buf_avail -= in_buf_size;
4605*da0073e9SAndroid Build Coastguard Worker         read_buf_ofs += in_buf_size;
4606*da0073e9SAndroid Build Coastguard Worker         out_buf_ofs += out_buf_size;
4607*da0073e9SAndroid Build Coastguard Worker     } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4608*da0073e9SAndroid Build Coastguard Worker 
4609*da0073e9SAndroid Build Coastguard Worker     if (status == TINFL_STATUS_DONE)
4610*da0073e9SAndroid Build Coastguard Worker     {
4611*da0073e9SAndroid Build Coastguard Worker         /* Make sure the entire file was decompressed, and check its CRC. */
4612*da0073e9SAndroid Build Coastguard Worker         if (out_buf_ofs != file_stat.m_uncomp_size)
4613*da0073e9SAndroid Build Coastguard Worker         {
4614*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4615*da0073e9SAndroid Build Coastguard Worker             status = TINFL_STATUS_FAILED;
4616*da0073e9SAndroid Build Coastguard Worker         }
4617*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4618*da0073e9SAndroid Build Coastguard Worker         else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4619*da0073e9SAndroid Build Coastguard Worker         {
4620*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4621*da0073e9SAndroid Build Coastguard Worker             status = TINFL_STATUS_FAILED;
4622*da0073e9SAndroid Build Coastguard Worker         }
4623*da0073e9SAndroid Build Coastguard Worker #endif
4624*da0073e9SAndroid Build Coastguard Worker     }
4625*da0073e9SAndroid Build Coastguard Worker 
4626*da0073e9SAndroid Build Coastguard Worker     if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4627*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4628*da0073e9SAndroid Build Coastguard Worker 
4629*da0073e9SAndroid Build Coastguard Worker     return status == TINFL_STATUS_DONE;
4630*da0073e9SAndroid Build Coastguard Worker }
4631*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags,void * pUser_read_buf,size_t user_read_buf_size)4632*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4633*da0073e9SAndroid Build Coastguard Worker {
4634*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4635*da0073e9SAndroid Build Coastguard Worker     mz_uint32 file_index;
4636*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4637*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4638*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
4639*da0073e9SAndroid Build Coastguard Worker }
4640*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_to_mem(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags)4641*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
4642*da0073e9SAndroid Build Coastguard Worker {
4643*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
4644*da0073e9SAndroid Build Coastguard Worker }
4645*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_file_to_mem(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags)4646*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
4647*da0073e9SAndroid Build Coastguard Worker {
4648*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4649*da0073e9SAndroid Build Coastguard Worker }
4650*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_to_heap(mz_zip_archive * pZip,mz_uint file_index,size_t * pSize,mz_uint flags)4651*da0073e9SAndroid Build Coastguard Worker void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
4652*da0073e9SAndroid Build Coastguard Worker {
4653*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4654*da0073e9SAndroid Build Coastguard Worker     mz_uint64 comp_size, uncomp_size, alloc_size;
4655*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4656*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4657*da0073e9SAndroid Build Coastguard Worker     void *pBuf;
4658*da0073e9SAndroid Build Coastguard Worker 
4659*da0073e9SAndroid Build Coastguard Worker     if (pSize)
4660*da0073e9SAndroid Build Coastguard Worker         *pSize = 0;
4661*da0073e9SAndroid Build Coastguard Worker 
4662*da0073e9SAndroid Build Coastguard Worker     if (!p)
4663*da0073e9SAndroid Build Coastguard Worker     {
4664*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4665*da0073e9SAndroid Build Coastguard Worker         return NULL;
4666*da0073e9SAndroid Build Coastguard Worker     }
4667*da0073e9SAndroid Build Coastguard Worker 
4668*da0073e9SAndroid Build Coastguard Worker     comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4669*da0073e9SAndroid Build Coastguard Worker     uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4670*da0073e9SAndroid Build Coastguard Worker 
4671*da0073e9SAndroid Build Coastguard Worker     alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
4672*da0073e9SAndroid Build Coastguard Worker     if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4673*da0073e9SAndroid Build Coastguard Worker     {
4674*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4675*da0073e9SAndroid Build Coastguard Worker         return NULL;
4676*da0073e9SAndroid Build Coastguard Worker     }
4677*da0073e9SAndroid Build Coastguard Worker 
4678*da0073e9SAndroid Build Coastguard Worker     if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
4679*da0073e9SAndroid Build Coastguard Worker     {
4680*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4681*da0073e9SAndroid Build Coastguard Worker         return NULL;
4682*da0073e9SAndroid Build Coastguard Worker     }
4683*da0073e9SAndroid Build Coastguard Worker 
4684*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
4685*da0073e9SAndroid Build Coastguard Worker     {
4686*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4687*da0073e9SAndroid Build Coastguard Worker         return NULL;
4688*da0073e9SAndroid Build Coastguard Worker     }
4689*da0073e9SAndroid Build Coastguard Worker 
4690*da0073e9SAndroid Build Coastguard Worker     if (pSize)
4691*da0073e9SAndroid Build Coastguard Worker         *pSize = (size_t)alloc_size;
4692*da0073e9SAndroid Build Coastguard Worker     return pBuf;
4693*da0073e9SAndroid Build Coastguard Worker }
4694*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_file_to_heap(mz_zip_archive * pZip,const char * pFilename,size_t * pSize,mz_uint flags)4695*da0073e9SAndroid Build Coastguard Worker void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
4696*da0073e9SAndroid Build Coastguard Worker {
4697*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4698*da0073e9SAndroid Build Coastguard Worker     mz_uint32 file_index;
4699*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4700*da0073e9SAndroid Build Coastguard Worker     {
4701*da0073e9SAndroid Build Coastguard Worker         if (pSize)
4702*da0073e9SAndroid Build Coastguard Worker             *pSize = 0;
4703*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4704*da0073e9SAndroid Build Coastguard Worker     }
4705*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4706*da0073e9SAndroid Build Coastguard Worker }
4707*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_to_callback(mz_zip_archive * pZip,mz_uint file_index,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)4708*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
4709*da0073e9SAndroid Build Coastguard Worker {
4710*da0073e9SAndroid Build Coastguard Worker     int status = TINFL_STATUS_DONE;
4711*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4712*da0073e9SAndroid Build Coastguard Worker     mz_uint file_crc32 = MZ_CRC32_INIT;
4713*da0073e9SAndroid Build Coastguard Worker #endif
4714*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4715*da0073e9SAndroid Build Coastguard Worker     mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4716*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive_file_stat file_stat;
4717*da0073e9SAndroid Build Coastguard Worker     void *pRead_buf = NULL;
4718*da0073e9SAndroid Build Coastguard Worker     void *pWrite_buf = NULL;
4719*da0073e9SAndroid Build Coastguard Worker     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4720*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4721*da0073e9SAndroid Build Coastguard Worker 
4722*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4723*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4724*da0073e9SAndroid Build Coastguard Worker 
4725*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4726*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4727*da0073e9SAndroid Build Coastguard Worker 
4728*da0073e9SAndroid Build Coastguard Worker     /* A directory or zero length file */
4729*da0073e9SAndroid Build Coastguard Worker     if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4730*da0073e9SAndroid Build Coastguard Worker         return MZ_TRUE;
4731*da0073e9SAndroid Build Coastguard Worker 
4732*da0073e9SAndroid Build Coastguard Worker     /* Encryption and patch files are not supported. */
4733*da0073e9SAndroid Build Coastguard Worker     if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4734*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4735*da0073e9SAndroid Build Coastguard Worker 
4736*da0073e9SAndroid Build Coastguard Worker     /* This function only supports decompressing stored and deflate. */
4737*da0073e9SAndroid Build Coastguard Worker     if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4738*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4739*da0073e9SAndroid Build Coastguard Worker 
4740*da0073e9SAndroid Build Coastguard Worker     /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */
4741*da0073e9SAndroid Build Coastguard Worker     cur_file_ofs = file_stat.m_local_header_ofs;
4742*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4743*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4744*da0073e9SAndroid Build Coastguard Worker 
4745*da0073e9SAndroid Build Coastguard Worker     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4746*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4747*da0073e9SAndroid Build Coastguard Worker 
4748*da0073e9SAndroid Build Coastguard Worker     cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4749*da0073e9SAndroid Build Coastguard Worker     if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4750*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4751*da0073e9SAndroid Build Coastguard Worker 
4752*da0073e9SAndroid Build Coastguard Worker     /* Decompress the file either directly from memory or from a file input buffer. */
4753*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pState->m_pMem)
4754*da0073e9SAndroid Build Coastguard Worker     {
4755*da0073e9SAndroid Build Coastguard Worker         pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4756*da0073e9SAndroid Build Coastguard Worker         read_buf_size = read_buf_avail = file_stat.m_comp_size;
4757*da0073e9SAndroid Build Coastguard Worker         comp_remaining = 0;
4758*da0073e9SAndroid Build Coastguard Worker     }
4759*da0073e9SAndroid Build Coastguard Worker     else
4760*da0073e9SAndroid Build Coastguard Worker     {
4761*da0073e9SAndroid Build Coastguard Worker         read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4762*da0073e9SAndroid Build Coastguard Worker         if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4763*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4764*da0073e9SAndroid Build Coastguard Worker 
4765*da0073e9SAndroid Build Coastguard Worker         read_buf_avail = 0;
4766*da0073e9SAndroid Build Coastguard Worker         comp_remaining = file_stat.m_comp_size;
4767*da0073e9SAndroid Build Coastguard Worker     }
4768*da0073e9SAndroid Build Coastguard Worker 
4769*da0073e9SAndroid Build Coastguard Worker     if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4770*da0073e9SAndroid Build Coastguard Worker     {
4771*da0073e9SAndroid Build Coastguard Worker         /* The file is stored or the caller has requested the compressed data. */
4772*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pState->m_pMem)
4773*da0073e9SAndroid Build Coastguard Worker         {
4774*da0073e9SAndroid Build Coastguard Worker             if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4775*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4776*da0073e9SAndroid Build Coastguard Worker 
4777*da0073e9SAndroid Build Coastguard Worker             if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4778*da0073e9SAndroid Build Coastguard Worker             {
4779*da0073e9SAndroid Build Coastguard Worker                 mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4780*da0073e9SAndroid Build Coastguard Worker                 status = TINFL_STATUS_FAILED;
4781*da0073e9SAndroid Build Coastguard Worker             }
4782*da0073e9SAndroid Build Coastguard Worker             else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4783*da0073e9SAndroid Build Coastguard Worker             {
4784*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4785*da0073e9SAndroid Build Coastguard Worker                 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4786*da0073e9SAndroid Build Coastguard Worker #endif
4787*da0073e9SAndroid Build Coastguard Worker             }
4788*da0073e9SAndroid Build Coastguard Worker 
4789*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
4790*da0073e9SAndroid Build Coastguard Worker             cur_file_ofs += file_stat.m_comp_size;
4791*da0073e9SAndroid Build Coastguard Worker             out_buf_ofs += file_stat.m_comp_size;
4792*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
4793*da0073e9SAndroid Build Coastguard Worker             comp_remaining = 0;
4794*da0073e9SAndroid Build Coastguard Worker         }
4795*da0073e9SAndroid Build Coastguard Worker         else
4796*da0073e9SAndroid Build Coastguard Worker         {
4797*da0073e9SAndroid Build Coastguard Worker             while (comp_remaining)
4798*da0073e9SAndroid Build Coastguard Worker             {
4799*da0073e9SAndroid Build Coastguard Worker                 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4800*da0073e9SAndroid Build Coastguard Worker                 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4801*da0073e9SAndroid Build Coastguard Worker                 {
4802*da0073e9SAndroid Build Coastguard Worker                     mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4803*da0073e9SAndroid Build Coastguard Worker                     status = TINFL_STATUS_FAILED;
4804*da0073e9SAndroid Build Coastguard Worker                     break;
4805*da0073e9SAndroid Build Coastguard Worker                 }
4806*da0073e9SAndroid Build Coastguard Worker 
4807*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4808*da0073e9SAndroid Build Coastguard Worker                 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4809*da0073e9SAndroid Build Coastguard Worker                 {
4810*da0073e9SAndroid Build Coastguard Worker                     file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4811*da0073e9SAndroid Build Coastguard Worker                 }
4812*da0073e9SAndroid Build Coastguard Worker #endif
4813*da0073e9SAndroid Build Coastguard Worker 
4814*da0073e9SAndroid Build Coastguard Worker                 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4815*da0073e9SAndroid Build Coastguard Worker                 {
4816*da0073e9SAndroid Build Coastguard Worker                     mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4817*da0073e9SAndroid Build Coastguard Worker                     status = TINFL_STATUS_FAILED;
4818*da0073e9SAndroid Build Coastguard Worker                     break;
4819*da0073e9SAndroid Build Coastguard Worker                 }
4820*da0073e9SAndroid Build Coastguard Worker 
4821*da0073e9SAndroid Build Coastguard Worker                 cur_file_ofs += read_buf_avail;
4822*da0073e9SAndroid Build Coastguard Worker                 out_buf_ofs += read_buf_avail;
4823*da0073e9SAndroid Build Coastguard Worker                 comp_remaining -= read_buf_avail;
4824*da0073e9SAndroid Build Coastguard Worker             }
4825*da0073e9SAndroid Build Coastguard Worker         }
4826*da0073e9SAndroid Build Coastguard Worker     }
4827*da0073e9SAndroid Build Coastguard Worker     else
4828*da0073e9SAndroid Build Coastguard Worker     {
4829*da0073e9SAndroid Build Coastguard Worker         tinfl_decompressor inflator;
4830*da0073e9SAndroid Build Coastguard Worker         tinfl_init(&inflator);
4831*da0073e9SAndroid Build Coastguard Worker 
4832*da0073e9SAndroid Build Coastguard Worker         if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4833*da0073e9SAndroid Build Coastguard Worker         {
4834*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4835*da0073e9SAndroid Build Coastguard Worker             status = TINFL_STATUS_FAILED;
4836*da0073e9SAndroid Build Coastguard Worker         }
4837*da0073e9SAndroid Build Coastguard Worker         else
4838*da0073e9SAndroid Build Coastguard Worker         {
4839*da0073e9SAndroid Build Coastguard Worker             do
4840*da0073e9SAndroid Build Coastguard Worker             {
4841*da0073e9SAndroid Build Coastguard Worker                 mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4842*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4843*da0073e9SAndroid Build Coastguard Worker                 size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4844*da0073e9SAndroid Build Coastguard Worker                 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4845*da0073e9SAndroid Build Coastguard Worker                 {
4846*da0073e9SAndroid Build Coastguard Worker                     read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4847*da0073e9SAndroid Build Coastguard Worker                     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4848*da0073e9SAndroid Build Coastguard Worker                     {
4849*da0073e9SAndroid Build Coastguard Worker                         mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4850*da0073e9SAndroid Build Coastguard Worker                         status = TINFL_STATUS_FAILED;
4851*da0073e9SAndroid Build Coastguard Worker                         break;
4852*da0073e9SAndroid Build Coastguard Worker                     }
4853*da0073e9SAndroid Build Coastguard Worker                     cur_file_ofs += read_buf_avail;
4854*da0073e9SAndroid Build Coastguard Worker                     comp_remaining -= read_buf_avail;
4855*da0073e9SAndroid Build Coastguard Worker                     read_buf_ofs = 0;
4856*da0073e9SAndroid Build Coastguard Worker                 }
4857*da0073e9SAndroid Build Coastguard Worker 
4858*da0073e9SAndroid Build Coastguard Worker                 in_buf_size = (size_t)read_buf_avail;
4859*da0073e9SAndroid Build Coastguard Worker                 status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
4860*da0073e9SAndroid Build Coastguard Worker                 read_buf_avail -= in_buf_size;
4861*da0073e9SAndroid Build Coastguard Worker                 read_buf_ofs += in_buf_size;
4862*da0073e9SAndroid Build Coastguard Worker 
4863*da0073e9SAndroid Build Coastguard Worker                 if (out_buf_size)
4864*da0073e9SAndroid Build Coastguard Worker                 {
4865*da0073e9SAndroid Build Coastguard Worker                     if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4866*da0073e9SAndroid Build Coastguard Worker                     {
4867*da0073e9SAndroid Build Coastguard Worker                         mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4868*da0073e9SAndroid Build Coastguard Worker                         status = TINFL_STATUS_FAILED;
4869*da0073e9SAndroid Build Coastguard Worker                         break;
4870*da0073e9SAndroid Build Coastguard Worker                     }
4871*da0073e9SAndroid Build Coastguard Worker 
4872*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4873*da0073e9SAndroid Build Coastguard Worker                     file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4874*da0073e9SAndroid Build Coastguard Worker #endif
4875*da0073e9SAndroid Build Coastguard Worker                     if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4876*da0073e9SAndroid Build Coastguard Worker                     {
4877*da0073e9SAndroid Build Coastguard Worker                         mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4878*da0073e9SAndroid Build Coastguard Worker                         status = TINFL_STATUS_FAILED;
4879*da0073e9SAndroid Build Coastguard Worker                         break;
4880*da0073e9SAndroid Build Coastguard Worker                     }
4881*da0073e9SAndroid Build Coastguard Worker                 }
4882*da0073e9SAndroid Build Coastguard Worker             } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4883*da0073e9SAndroid Build Coastguard Worker         }
4884*da0073e9SAndroid Build Coastguard Worker     }
4885*da0073e9SAndroid Build Coastguard Worker 
4886*da0073e9SAndroid Build Coastguard Worker     if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4887*da0073e9SAndroid Build Coastguard Worker     {
4888*da0073e9SAndroid Build Coastguard Worker         /* Make sure the entire file was decompressed, and check its CRC. */
4889*da0073e9SAndroid Build Coastguard Worker         if (out_buf_ofs != file_stat.m_uncomp_size)
4890*da0073e9SAndroid Build Coastguard Worker         {
4891*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4892*da0073e9SAndroid Build Coastguard Worker             status = TINFL_STATUS_FAILED;
4893*da0073e9SAndroid Build Coastguard Worker         }
4894*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4895*da0073e9SAndroid Build Coastguard Worker         else if (file_crc32 != file_stat.m_crc32)
4896*da0073e9SAndroid Build Coastguard Worker         {
4897*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4898*da0073e9SAndroid Build Coastguard Worker             status = TINFL_STATUS_FAILED;
4899*da0073e9SAndroid Build Coastguard Worker         }
4900*da0073e9SAndroid Build Coastguard Worker #endif
4901*da0073e9SAndroid Build Coastguard Worker     }
4902*da0073e9SAndroid Build Coastguard Worker 
4903*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_pState->m_pMem)
4904*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4905*da0073e9SAndroid Build Coastguard Worker 
4906*da0073e9SAndroid Build Coastguard Worker     if (pWrite_buf)
4907*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4908*da0073e9SAndroid Build Coastguard Worker 
4909*da0073e9SAndroid Build Coastguard Worker     return status == TINFL_STATUS_DONE;
4910*da0073e9SAndroid Build Coastguard Worker }
4911*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_file_to_callback(mz_zip_archive * pZip,const char * pFilename,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)4912*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
4913*da0073e9SAndroid Build Coastguard Worker {
4914*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4915*da0073e9SAndroid Build Coastguard Worker     mz_uint32 file_index;
4916*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4917*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
4918*da0073e9SAndroid Build Coastguard Worker 
4919*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4920*da0073e9SAndroid Build Coastguard Worker }
4921*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_iter_new(mz_zip_archive * pZip,mz_uint file_index,mz_uint flags)4922*da0073e9SAndroid Build Coastguard Worker mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
4923*da0073e9SAndroid Build Coastguard Worker {
4924*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4925*da0073e9SAndroid Build Coastguard Worker     mz_zip_reader_extract_iter_state *pState;
4926*da0073e9SAndroid Build Coastguard Worker     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4927*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4928*da0073e9SAndroid Build Coastguard Worker 
4929*da0073e9SAndroid Build Coastguard Worker     /* Argument sanity check */
4930*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState))
4931*da0073e9SAndroid Build Coastguard Worker         return NULL;
4932*da0073e9SAndroid Build Coastguard Worker 
4933*da0073e9SAndroid Build Coastguard Worker     /* Allocate an iterator status structure */
4934*da0073e9SAndroid Build Coastguard Worker     pState = (mz_zip_reader_extract_iter_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));
4935*da0073e9SAndroid Build Coastguard Worker     if (!pState)
4936*da0073e9SAndroid Build Coastguard Worker     {
4937*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4938*da0073e9SAndroid Build Coastguard Worker         return NULL;
4939*da0073e9SAndroid Build Coastguard Worker     }
4940*da0073e9SAndroid Build Coastguard Worker 
4941*da0073e9SAndroid Build Coastguard Worker     /* Fetch file details */
4942*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
4943*da0073e9SAndroid Build Coastguard Worker     {
4944*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4945*da0073e9SAndroid Build Coastguard Worker         return NULL;
4946*da0073e9SAndroid Build Coastguard Worker     }
4947*da0073e9SAndroid Build Coastguard Worker 
4948*da0073e9SAndroid Build Coastguard Worker     /* Encryption and patch files are not supported. */
4949*da0073e9SAndroid Build Coastguard Worker     if (pState->file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4950*da0073e9SAndroid Build Coastguard Worker     {
4951*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4952*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4953*da0073e9SAndroid Build Coastguard Worker         return NULL;
4954*da0073e9SAndroid Build Coastguard Worker     }
4955*da0073e9SAndroid Build Coastguard Worker 
4956*da0073e9SAndroid Build Coastguard Worker     /* This function only supports decompressing stored and deflate. */
4957*da0073e9SAndroid Build Coastguard Worker     if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
4958*da0073e9SAndroid Build Coastguard Worker     {
4959*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4960*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4961*da0073e9SAndroid Build Coastguard Worker         return NULL;
4962*da0073e9SAndroid Build Coastguard Worker     }
4963*da0073e9SAndroid Build Coastguard Worker 
4964*da0073e9SAndroid Build Coastguard Worker     /* Init state - save args */
4965*da0073e9SAndroid Build Coastguard Worker     pState->pZip = pZip;
4966*da0073e9SAndroid Build Coastguard Worker     pState->flags = flags;
4967*da0073e9SAndroid Build Coastguard Worker 
4968*da0073e9SAndroid Build Coastguard Worker     /* Init state - reset variables to defaults */
4969*da0073e9SAndroid Build Coastguard Worker     pState->status = TINFL_STATUS_DONE;
4970*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4971*da0073e9SAndroid Build Coastguard Worker     pState->file_crc32 = MZ_CRC32_INIT;
4972*da0073e9SAndroid Build Coastguard Worker #endif
4973*da0073e9SAndroid Build Coastguard Worker     pState->read_buf_ofs = 0;
4974*da0073e9SAndroid Build Coastguard Worker     pState->out_buf_ofs = 0;
4975*da0073e9SAndroid Build Coastguard Worker     pState->pRead_buf = NULL;
4976*da0073e9SAndroid Build Coastguard Worker     pState->pWrite_buf = NULL;
4977*da0073e9SAndroid Build Coastguard Worker     pState->out_blk_remain = 0;
4978*da0073e9SAndroid Build Coastguard Worker 
4979*da0073e9SAndroid Build Coastguard Worker     /* Read and parse the local directory entry. */
4980*da0073e9SAndroid Build Coastguard Worker     pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
4981*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4982*da0073e9SAndroid Build Coastguard Worker     {
4983*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4984*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4985*da0073e9SAndroid Build Coastguard Worker         return NULL;
4986*da0073e9SAndroid Build Coastguard Worker     }
4987*da0073e9SAndroid Build Coastguard Worker 
4988*da0073e9SAndroid Build Coastguard Worker     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4989*da0073e9SAndroid Build Coastguard Worker     {
4990*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4991*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4992*da0073e9SAndroid Build Coastguard Worker         return NULL;
4993*da0073e9SAndroid Build Coastguard Worker     }
4994*da0073e9SAndroid Build Coastguard Worker 
4995*da0073e9SAndroid Build Coastguard Worker     pState->cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4996*da0073e9SAndroid Build Coastguard Worker     if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
4997*da0073e9SAndroid Build Coastguard Worker     {
4998*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4999*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5000*da0073e9SAndroid Build Coastguard Worker         return NULL;
5001*da0073e9SAndroid Build Coastguard Worker     }
5002*da0073e9SAndroid Build Coastguard Worker 
5003*da0073e9SAndroid Build Coastguard Worker     /* Decompress the file either directly from memory or from a file input buffer. */
5004*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pState->m_pMem)
5005*da0073e9SAndroid Build Coastguard Worker     {
5006*da0073e9SAndroid Build Coastguard Worker         pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
5007*da0073e9SAndroid Build Coastguard Worker         pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
5008*da0073e9SAndroid Build Coastguard Worker         pState->comp_remaining = pState->file_stat.m_comp_size;
5009*da0073e9SAndroid Build Coastguard Worker     }
5010*da0073e9SAndroid Build Coastguard Worker     else
5011*da0073e9SAndroid Build Coastguard Worker     {
5012*da0073e9SAndroid Build Coastguard Worker         if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
5013*da0073e9SAndroid Build Coastguard Worker         {
5014*da0073e9SAndroid Build Coastguard Worker             /* Decompression required, therefore intermediate read buffer required */
5015*da0073e9SAndroid Build Coastguard Worker             pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5016*da0073e9SAndroid Build Coastguard Worker             if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))
5017*da0073e9SAndroid Build Coastguard Worker             {
5018*da0073e9SAndroid Build Coastguard Worker                 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5019*da0073e9SAndroid Build Coastguard Worker                 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5020*da0073e9SAndroid Build Coastguard Worker                 return NULL;
5021*da0073e9SAndroid Build Coastguard Worker             }
5022*da0073e9SAndroid Build Coastguard Worker         }
5023*da0073e9SAndroid Build Coastguard Worker         else
5024*da0073e9SAndroid Build Coastguard Worker         {
5025*da0073e9SAndroid Build Coastguard Worker             /* Decompression not required - we will be reading directly into user buffer, no temp buf required */
5026*da0073e9SAndroid Build Coastguard Worker             pState->read_buf_size = 0;
5027*da0073e9SAndroid Build Coastguard Worker         }
5028*da0073e9SAndroid Build Coastguard Worker         pState->read_buf_avail = 0;
5029*da0073e9SAndroid Build Coastguard Worker         pState->comp_remaining = pState->file_stat.m_comp_size;
5030*da0073e9SAndroid Build Coastguard Worker     }
5031*da0073e9SAndroid Build Coastguard Worker 
5032*da0073e9SAndroid Build Coastguard Worker     if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
5033*da0073e9SAndroid Build Coastguard Worker     {
5034*da0073e9SAndroid Build Coastguard Worker         /* Decompression required, init decompressor */
5035*da0073e9SAndroid Build Coastguard Worker         tinfl_init( &pState->inflator );
5036*da0073e9SAndroid Build Coastguard Worker 
5037*da0073e9SAndroid Build Coastguard Worker         /* Allocate write buffer */
5038*da0073e9SAndroid Build Coastguard Worker         if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
5039*da0073e9SAndroid Build Coastguard Worker         {
5040*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5041*da0073e9SAndroid Build Coastguard Worker             if (pState->pRead_buf)
5042*da0073e9SAndroid Build Coastguard Worker                 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
5043*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5044*da0073e9SAndroid Build Coastguard Worker             return NULL;
5045*da0073e9SAndroid Build Coastguard Worker         }
5046*da0073e9SAndroid Build Coastguard Worker     }
5047*da0073e9SAndroid Build Coastguard Worker 
5048*da0073e9SAndroid Build Coastguard Worker     return pState;
5049*da0073e9SAndroid Build Coastguard Worker }
5050*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_file_iter_new(mz_zip_archive * pZip,const char * pFilename,mz_uint flags)5051*da0073e9SAndroid Build Coastguard Worker mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
5052*da0073e9SAndroid Build Coastguard Worker {
5053*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5054*da0073e9SAndroid Build Coastguard Worker     mz_uint32 file_index;
5055*da0073e9SAndroid Build Coastguard Worker 
5056*da0073e9SAndroid Build Coastguard Worker     /* Locate file index by name */
5057*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
5058*da0073e9SAndroid Build Coastguard Worker         return NULL;
5059*da0073e9SAndroid Build Coastguard Worker 
5060*da0073e9SAndroid Build Coastguard Worker     /* Construct iterator */
5061*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
5062*da0073e9SAndroid Build Coastguard Worker }
5063*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state * pState,void * pvBuf,size_t buf_size)5064*da0073e9SAndroid Build Coastguard Worker size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size)
5065*da0073e9SAndroid Build Coastguard Worker {
5066*da0073e9SAndroid Build Coastguard Worker     size_t copied_to_caller = 0;
5067*da0073e9SAndroid Build Coastguard Worker 
5068*da0073e9SAndroid Build Coastguard Worker     /* Argument sanity check */
5069*da0073e9SAndroid Build Coastguard Worker     if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
5070*da0073e9SAndroid Build Coastguard Worker         return 0;
5071*da0073e9SAndroid Build Coastguard Worker 
5072*da0073e9SAndroid Build Coastguard Worker     if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
5073*da0073e9SAndroid Build Coastguard Worker     {
5074*da0073e9SAndroid Build Coastguard Worker         /* The file is stored or the caller has requested the compressed data, calc amount to return. */
5075*da0073e9SAndroid Build Coastguard Worker         copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining );
5076*da0073e9SAndroid Build Coastguard Worker 
5077*da0073e9SAndroid Build Coastguard Worker         /* Zip is in memory....or requires reading from a file? */
5078*da0073e9SAndroid Build Coastguard Worker         if (pState->pZip->m_pState->m_pMem)
5079*da0073e9SAndroid Build Coastguard Worker         {
5080*da0073e9SAndroid Build Coastguard Worker             /* Copy data to caller's buffer */
5081*da0073e9SAndroid Build Coastguard Worker             memcpy( pvBuf, pState->pRead_buf, copied_to_caller );
5082*da0073e9SAndroid Build Coastguard Worker             pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;
5083*da0073e9SAndroid Build Coastguard Worker         }
5084*da0073e9SAndroid Build Coastguard Worker         else
5085*da0073e9SAndroid Build Coastguard Worker         {
5086*da0073e9SAndroid Build Coastguard Worker             /* Read directly into caller's buffer */
5087*da0073e9SAndroid Build Coastguard Worker             if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
5088*da0073e9SAndroid Build Coastguard Worker             {
5089*da0073e9SAndroid Build Coastguard Worker                 /* Failed to read all that was asked for, flag failure and alert user */
5090*da0073e9SAndroid Build Coastguard Worker                 mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5091*da0073e9SAndroid Build Coastguard Worker                 pState->status = TINFL_STATUS_FAILED;
5092*da0073e9SAndroid Build Coastguard Worker                 copied_to_caller = 0;
5093*da0073e9SAndroid Build Coastguard Worker             }
5094*da0073e9SAndroid Build Coastguard Worker         }
5095*da0073e9SAndroid Build Coastguard Worker 
5096*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5097*da0073e9SAndroid Build Coastguard Worker         /* Compute CRC if not returning compressed data only */
5098*da0073e9SAndroid Build Coastguard Worker         if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5099*da0073e9SAndroid Build Coastguard Worker             pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
5100*da0073e9SAndroid Build Coastguard Worker #endif
5101*da0073e9SAndroid Build Coastguard Worker 
5102*da0073e9SAndroid Build Coastguard Worker         /* Advance offsets, dec counters */
5103*da0073e9SAndroid Build Coastguard Worker         pState->cur_file_ofs += copied_to_caller;
5104*da0073e9SAndroid Build Coastguard Worker         pState->out_buf_ofs += copied_to_caller;
5105*da0073e9SAndroid Build Coastguard Worker         pState->comp_remaining -= copied_to_caller;
5106*da0073e9SAndroid Build Coastguard Worker     }
5107*da0073e9SAndroid Build Coastguard Worker     else
5108*da0073e9SAndroid Build Coastguard Worker     {
5109*da0073e9SAndroid Build Coastguard Worker         do
5110*da0073e9SAndroid Build Coastguard Worker         {
5111*da0073e9SAndroid Build Coastguard Worker             /* Calc ptr to write buffer - given current output pos and block size */
5112*da0073e9SAndroid Build Coastguard Worker             mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5113*da0073e9SAndroid Build Coastguard Worker 
5114*da0073e9SAndroid Build Coastguard Worker             /* Calc max output size - given current output pos and block size */
5115*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5116*da0073e9SAndroid Build Coastguard Worker             size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5117*da0073e9SAndroid Build Coastguard Worker 
5118*da0073e9SAndroid Build Coastguard Worker             if (!pState->out_blk_remain)
5119*da0073e9SAndroid Build Coastguard Worker             {
5120*da0073e9SAndroid Build Coastguard Worker                 /* Read more data from file if none available (and reading from file) */
5121*da0073e9SAndroid Build Coastguard Worker                 if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
5122*da0073e9SAndroid Build Coastguard Worker                 {
5123*da0073e9SAndroid Build Coastguard Worker                     /* Calc read size */
5124*da0073e9SAndroid Build Coastguard Worker                     pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
5125*da0073e9SAndroid Build Coastguard Worker                     if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pState->pRead_buf, (size_t)pState->read_buf_avail) != pState->read_buf_avail)
5126*da0073e9SAndroid Build Coastguard Worker                     {
5127*da0073e9SAndroid Build Coastguard Worker                         mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5128*da0073e9SAndroid Build Coastguard Worker                         pState->status = TINFL_STATUS_FAILED;
5129*da0073e9SAndroid Build Coastguard Worker                         break;
5130*da0073e9SAndroid Build Coastguard Worker                     }
5131*da0073e9SAndroid Build Coastguard Worker 
5132*da0073e9SAndroid Build Coastguard Worker                     /* Advance offsets, dec counters */
5133*da0073e9SAndroid Build Coastguard Worker                     pState->cur_file_ofs += pState->read_buf_avail;
5134*da0073e9SAndroid Build Coastguard Worker                     pState->comp_remaining -= pState->read_buf_avail;
5135*da0073e9SAndroid Build Coastguard Worker                     pState->read_buf_ofs = 0;
5136*da0073e9SAndroid Build Coastguard Worker                 }
5137*da0073e9SAndroid Build Coastguard Worker 
5138*da0073e9SAndroid Build Coastguard Worker                 /* Perform decompression */
5139*da0073e9SAndroid Build Coastguard Worker                 in_buf_size = (size_t)pState->read_buf_avail;
5140*da0073e9SAndroid Build Coastguard Worker                 pState->status = tinfl_decompress(&pState->inflator, (const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs, &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur, &out_buf_size, pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5141*da0073e9SAndroid Build Coastguard Worker                 pState->read_buf_avail -= in_buf_size;
5142*da0073e9SAndroid Build Coastguard Worker                 pState->read_buf_ofs += in_buf_size;
5143*da0073e9SAndroid Build Coastguard Worker 
5144*da0073e9SAndroid Build Coastguard Worker                 /* Update current output block size remaining */
5145*da0073e9SAndroid Build Coastguard Worker                 pState->out_blk_remain = out_buf_size;
5146*da0073e9SAndroid Build Coastguard Worker             }
5147*da0073e9SAndroid Build Coastguard Worker 
5148*da0073e9SAndroid Build Coastguard Worker             if (pState->out_blk_remain)
5149*da0073e9SAndroid Build Coastguard Worker             {
5150*da0073e9SAndroid Build Coastguard Worker                 /* Calc amount to return. */
5151*da0073e9SAndroid Build Coastguard Worker                 size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );
5152*da0073e9SAndroid Build Coastguard Worker 
5153*da0073e9SAndroid Build Coastguard Worker                 /* Copy data to caller's buffer */
5154*da0073e9SAndroid Build Coastguard Worker                 memcpy( (uint8_t*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );
5155*da0073e9SAndroid Build Coastguard Worker 
5156*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5157*da0073e9SAndroid Build Coastguard Worker                 /* Perform CRC */
5158*da0073e9SAndroid Build Coastguard Worker                 pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
5159*da0073e9SAndroid Build Coastguard Worker #endif
5160*da0073e9SAndroid Build Coastguard Worker 
5161*da0073e9SAndroid Build Coastguard Worker                 /* Decrement data consumed from block */
5162*da0073e9SAndroid Build Coastguard Worker                 pState->out_blk_remain -= to_copy;
5163*da0073e9SAndroid Build Coastguard Worker 
5164*da0073e9SAndroid Build Coastguard Worker                 /* Inc output offset, while performing sanity check */
5165*da0073e9SAndroid Build Coastguard Worker                 if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
5166*da0073e9SAndroid Build Coastguard Worker                 {
5167*da0073e9SAndroid Build Coastguard Worker                     mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5168*da0073e9SAndroid Build Coastguard Worker                     pState->status = TINFL_STATUS_FAILED;
5169*da0073e9SAndroid Build Coastguard Worker                     break;
5170*da0073e9SAndroid Build Coastguard Worker                 }
5171*da0073e9SAndroid Build Coastguard Worker 
5172*da0073e9SAndroid Build Coastguard Worker                 /* Increment counter of data copied to caller */
5173*da0073e9SAndroid Build Coastguard Worker                 copied_to_caller += to_copy;
5174*da0073e9SAndroid Build Coastguard Worker             }
5175*da0073e9SAndroid Build Coastguard Worker         } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );
5176*da0073e9SAndroid Build Coastguard Worker     }
5177*da0073e9SAndroid Build Coastguard Worker 
5178*da0073e9SAndroid Build Coastguard Worker     /* Return how many bytes were copied into user buffer */
5179*da0073e9SAndroid Build Coastguard Worker     return copied_to_caller;
5180*da0073e9SAndroid Build Coastguard Worker }
5181*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state * pState)5182*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState)
5183*da0073e9SAndroid Build Coastguard Worker {
5184*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5185*da0073e9SAndroid Build Coastguard Worker     int status;
5186*da0073e9SAndroid Build Coastguard Worker 
5187*da0073e9SAndroid Build Coastguard Worker     /* Argument sanity check */
5188*da0073e9SAndroid Build Coastguard Worker     if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
5189*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5190*da0073e9SAndroid Build Coastguard Worker 
5191*da0073e9SAndroid Build Coastguard Worker     /* Was decompression completed and requested? */
5192*da0073e9SAndroid Build Coastguard Worker     if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
5193*da0073e9SAndroid Build Coastguard Worker     {
5194*da0073e9SAndroid Build Coastguard Worker         /* Make sure the entire file was decompressed, and check its CRC. */
5195*da0073e9SAndroid Build Coastguard Worker         if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
5196*da0073e9SAndroid Build Coastguard Worker         {
5197*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
5198*da0073e9SAndroid Build Coastguard Worker             pState->status = TINFL_STATUS_FAILED;
5199*da0073e9SAndroid Build Coastguard Worker         }
5200*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5201*da0073e9SAndroid Build Coastguard Worker         else if (pState->file_crc32 != pState->file_stat.m_crc32)
5202*da0073e9SAndroid Build Coastguard Worker         {
5203*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5204*da0073e9SAndroid Build Coastguard Worker             pState->status = TINFL_STATUS_FAILED;
5205*da0073e9SAndroid Build Coastguard Worker         }
5206*da0073e9SAndroid Build Coastguard Worker #endif
5207*da0073e9SAndroid Build Coastguard Worker     }
5208*da0073e9SAndroid Build Coastguard Worker 
5209*da0073e9SAndroid Build Coastguard Worker     /* Free buffers */
5210*da0073e9SAndroid Build Coastguard Worker     if (!pState->pZip->m_pState->m_pMem)
5211*da0073e9SAndroid Build Coastguard Worker         pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
5212*da0073e9SAndroid Build Coastguard Worker     if (pState->pWrite_buf)
5213*da0073e9SAndroid Build Coastguard Worker         pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
5214*da0073e9SAndroid Build Coastguard Worker 
5215*da0073e9SAndroid Build Coastguard Worker     /* Save status */
5216*da0073e9SAndroid Build Coastguard Worker     status = pState->status;
5217*da0073e9SAndroid Build Coastguard Worker 
5218*da0073e9SAndroid Build Coastguard Worker     /* Free context */
5219*da0073e9SAndroid Build Coastguard Worker     pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
5220*da0073e9SAndroid Build Coastguard Worker 
5221*da0073e9SAndroid Build Coastguard Worker     return status == TINFL_STATUS_DONE;
5222*da0073e9SAndroid Build Coastguard Worker }
5223*da0073e9SAndroid Build Coastguard Worker 
5224*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
mz_zip_file_write_callback(void * pOpaque,mz_uint64 ofs,const void * pBuf,size_t n)5225*da0073e9SAndroid Build Coastguard Worker static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
5226*da0073e9SAndroid Build Coastguard Worker {
5227*da0073e9SAndroid Build Coastguard Worker     (void)ofs;
5228*da0073e9SAndroid Build Coastguard Worker 
5229*da0073e9SAndroid Build Coastguard Worker     return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5230*da0073e9SAndroid Build Coastguard Worker }
5231*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_to_file(mz_zip_archive * pZip,mz_uint file_index,const char * pDst_filename,mz_uint flags)5232*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
5233*da0073e9SAndroid Build Coastguard Worker {
5234*da0073e9SAndroid Build Coastguard Worker     mz_bool status;
5235*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive_file_stat file_stat;
5236*da0073e9SAndroid Build Coastguard Worker     MZ_FILE *pFile;
5237*da0073e9SAndroid Build Coastguard Worker 
5238*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5239*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5240*da0073e9SAndroid Build Coastguard Worker 
5241*da0073e9SAndroid Build Coastguard Worker     if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5242*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5243*da0073e9SAndroid Build Coastguard Worker 
5244*da0073e9SAndroid Build Coastguard Worker     pFile = MZ_FOPEN(pDst_filename, "wb");
5245*da0073e9SAndroid Build Coastguard Worker     if (!pFile)
5246*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5247*da0073e9SAndroid Build Coastguard Worker 
5248*da0073e9SAndroid Build Coastguard Worker     status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5249*da0073e9SAndroid Build Coastguard Worker 
5250*da0073e9SAndroid Build Coastguard Worker     if (MZ_FCLOSE(pFile) == EOF)
5251*da0073e9SAndroid Build Coastguard Worker     {
5252*da0073e9SAndroid Build Coastguard Worker         if (status)
5253*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5254*da0073e9SAndroid Build Coastguard Worker 
5255*da0073e9SAndroid Build Coastguard Worker         status = MZ_FALSE;
5256*da0073e9SAndroid Build Coastguard Worker     }
5257*da0073e9SAndroid Build Coastguard Worker 
5258*da0073e9SAndroid Build Coastguard Worker #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
5259*da0073e9SAndroid Build Coastguard Worker     if (status)
5260*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5261*da0073e9SAndroid Build Coastguard Worker #endif
5262*da0073e9SAndroid Build Coastguard Worker 
5263*da0073e9SAndroid Build Coastguard Worker     return status;
5264*da0073e9SAndroid Build Coastguard Worker }
5265*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_file_to_file(mz_zip_archive * pZip,const char * pArchive_filename,const char * pDst_filename,mz_uint flags)5266*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
5267*da0073e9SAndroid Build Coastguard Worker {
5268*da0073e9SAndroid Build Coastguard Worker     mz_uint32 file_index;
5269*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5270*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5271*da0073e9SAndroid Build Coastguard Worker 
5272*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5273*da0073e9SAndroid Build Coastguard Worker }
5274*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_to_cfile(mz_zip_archive * pZip,mz_uint file_index,MZ_FILE * pFile,mz_uint flags)5275*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
5276*da0073e9SAndroid Build Coastguard Worker {
5277*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive_file_stat file_stat;
5278*da0073e9SAndroid Build Coastguard Worker 
5279*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5280*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5281*da0073e9SAndroid Build Coastguard Worker 
5282*da0073e9SAndroid Build Coastguard Worker     if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5283*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5284*da0073e9SAndroid Build Coastguard Worker 
5285*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5286*da0073e9SAndroid Build Coastguard Worker }
5287*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_extract_file_to_cfile(mz_zip_archive * pZip,const char * pArchive_filename,MZ_FILE * pFile,mz_uint flags)5288*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
5289*da0073e9SAndroid Build Coastguard Worker {
5290*da0073e9SAndroid Build Coastguard Worker     mz_uint32 file_index;
5291*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5292*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5293*da0073e9SAndroid Build Coastguard Worker 
5294*da0073e9SAndroid Build Coastguard Worker     return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
5295*da0073e9SAndroid Build Coastguard Worker }
5296*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
5297*da0073e9SAndroid Build Coastguard Worker 
mz_zip_compute_crc32_callback(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5298*da0073e9SAndroid Build Coastguard Worker static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5299*da0073e9SAndroid Build Coastguard Worker {
5300*da0073e9SAndroid Build Coastguard Worker     mz_uint32 *p = (mz_uint32 *)pOpaque;
5301*da0073e9SAndroid Build Coastguard Worker     (void)file_ofs;
5302*da0073e9SAndroid Build Coastguard Worker     *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
5303*da0073e9SAndroid Build Coastguard Worker     return n;
5304*da0073e9SAndroid Build Coastguard Worker }
5305*da0073e9SAndroid Build Coastguard Worker 
mz_zip_validate_file(mz_zip_archive * pZip,mz_uint file_index,mz_uint flags)5306*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
5307*da0073e9SAndroid Build Coastguard Worker {
5308*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive_file_stat file_stat;
5309*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5310*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState;
5311*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5312*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *pCentral_dir_header;
5313*da0073e9SAndroid Build Coastguard Worker     mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
5314*da0073e9SAndroid Build Coastguard Worker     mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
5315*da0073e9SAndroid Build Coastguard Worker     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
5316*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5317*da0073e9SAndroid Build Coastguard Worker     mz_uint64 local_header_ofs = 0;
5318*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5319*da0073e9SAndroid Build Coastguard Worker     mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
5320*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5321*da0073e9SAndroid Build Coastguard Worker     mz_uint64 local_header_comp_size, local_header_uncomp_size;
5322*da0073e9SAndroid Build Coastguard Worker     mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
5323*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5324*da0073e9SAndroid Build Coastguard Worker     mz_bool has_data_descriptor;
5325*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5326*da0073e9SAndroid Build Coastguard Worker     mz_uint32 local_header_bit_flags;
5327*da0073e9SAndroid Build Coastguard Worker 
5328*da0073e9SAndroid Build Coastguard Worker     mz_zip_array file_data_array;
5329*da0073e9SAndroid Build Coastguard Worker     mz_zip_array_init(&file_data_array, 1);
5330*da0073e9SAndroid Build Coastguard Worker 
5331*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5332*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5333*da0073e9SAndroid Build Coastguard Worker 
5334*da0073e9SAndroid Build Coastguard Worker     if (file_index > pZip->m_total_files)
5335*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5336*da0073e9SAndroid Build Coastguard Worker 
5337*da0073e9SAndroid Build Coastguard Worker     pState = pZip->m_pState;
5338*da0073e9SAndroid Build Coastguard Worker 
5339*da0073e9SAndroid Build Coastguard Worker     pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
5340*da0073e9SAndroid Build Coastguard Worker 
5341*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
5342*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5343*da0073e9SAndroid Build Coastguard Worker 
5344*da0073e9SAndroid Build Coastguard Worker     /* A directory or zero length file */
5345*da0073e9SAndroid Build Coastguard Worker     if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
5346*da0073e9SAndroid Build Coastguard Worker         return MZ_TRUE;
5347*da0073e9SAndroid Build Coastguard Worker 
5348*da0073e9SAndroid Build Coastguard Worker     /* Encryption and patch files are not supported. */
5349*da0073e9SAndroid Build Coastguard Worker     if (file_stat.m_is_encrypted)
5350*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5351*da0073e9SAndroid Build Coastguard Worker 
5352*da0073e9SAndroid Build Coastguard Worker     /* This function only supports stored and deflate. */
5353*da0073e9SAndroid Build Coastguard Worker     if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
5354*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
5355*da0073e9SAndroid Build Coastguard Worker 
5356*da0073e9SAndroid Build Coastguard Worker     if (!file_stat.m_is_supported)
5357*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5358*da0073e9SAndroid Build Coastguard Worker 
5359*da0073e9SAndroid Build Coastguard Worker     /* Read and parse the local directory entry. */
5360*da0073e9SAndroid Build Coastguard Worker     local_header_ofs = file_stat.m_local_header_ofs;
5361*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5362*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5363*da0073e9SAndroid Build Coastguard Worker 
5364*da0073e9SAndroid Build Coastguard Worker     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5365*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5366*da0073e9SAndroid Build Coastguard Worker 
5367*da0073e9SAndroid Build Coastguard Worker     local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
5368*da0073e9SAndroid Build Coastguard Worker     local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5369*da0073e9SAndroid Build Coastguard Worker     local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
5370*da0073e9SAndroid Build Coastguard Worker     local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
5371*da0073e9SAndroid Build Coastguard Worker     local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
5372*da0073e9SAndroid Build Coastguard Worker     local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
5373*da0073e9SAndroid Build Coastguard Worker     has_data_descriptor = (local_header_bit_flags & 8) != 0;
5374*da0073e9SAndroid Build Coastguard Worker 
5375*da0073e9SAndroid Build Coastguard Worker     if (local_header_filename_len != strlen(file_stat.m_filename))
5376*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5377*da0073e9SAndroid Build Coastguard Worker 
5378*da0073e9SAndroid Build Coastguard Worker     if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size)
5379*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5380*da0073e9SAndroid Build Coastguard Worker 
5381*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
5382*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5383*da0073e9SAndroid Build Coastguard Worker 
5384*da0073e9SAndroid Build Coastguard Worker     if (local_header_filename_len)
5385*da0073e9SAndroid Build Coastguard Worker     {
5386*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len)
5387*da0073e9SAndroid Build Coastguard Worker         {
5388*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5389*da0073e9SAndroid Build Coastguard Worker             goto handle_failure;
5390*da0073e9SAndroid Build Coastguard Worker         }
5391*da0073e9SAndroid Build Coastguard Worker 
5392*da0073e9SAndroid Build Coastguard Worker         /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */
5393*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(clang-analyzer-unix.cstring.NullArg)
5394*da0073e9SAndroid Build Coastguard Worker         if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
5395*da0073e9SAndroid Build Coastguard Worker         {
5396*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5397*da0073e9SAndroid Build Coastguard Worker             goto handle_failure;
5398*da0073e9SAndroid Build Coastguard Worker         }
5399*da0073e9SAndroid Build Coastguard Worker     }
5400*da0073e9SAndroid Build Coastguard Worker 
5401*da0073e9SAndroid Build Coastguard Worker     if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
5402*da0073e9SAndroid Build Coastguard Worker     {
5403*da0073e9SAndroid Build Coastguard Worker         mz_uint32 extra_size_remaining = local_header_extra_len;
5404*da0073e9SAndroid Build Coastguard Worker         const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
5405*da0073e9SAndroid Build Coastguard Worker 
5406*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
5407*da0073e9SAndroid Build Coastguard Worker         {
5408*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5409*da0073e9SAndroid Build Coastguard Worker             goto handle_failure;
5410*da0073e9SAndroid Build Coastguard Worker         }
5411*da0073e9SAndroid Build Coastguard Worker 
5412*da0073e9SAndroid Build Coastguard Worker         do
5413*da0073e9SAndroid Build Coastguard Worker         {
5414*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5415*da0073e9SAndroid Build Coastguard Worker             mz_uint32 field_id, field_data_size, field_total_size;
5416*da0073e9SAndroid Build Coastguard Worker 
5417*da0073e9SAndroid Build Coastguard Worker             if (extra_size_remaining < (sizeof(mz_uint16) * 2))
5418*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5419*da0073e9SAndroid Build Coastguard Worker 
5420*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
5421*da0073e9SAndroid Build Coastguard Worker             field_id = MZ_READ_LE16(pExtra_data);
5422*da0073e9SAndroid Build Coastguard Worker             field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
5423*da0073e9SAndroid Build Coastguard Worker             field_total_size = field_data_size + sizeof(mz_uint16) * 2;
5424*da0073e9SAndroid Build Coastguard Worker 
5425*da0073e9SAndroid Build Coastguard Worker             if (field_total_size > extra_size_remaining)
5426*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5427*da0073e9SAndroid Build Coastguard Worker 
5428*da0073e9SAndroid Build Coastguard Worker             if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
5429*da0073e9SAndroid Build Coastguard Worker             {
5430*da0073e9SAndroid Build Coastguard Worker                 const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
5431*da0073e9SAndroid Build Coastguard Worker 
5432*da0073e9SAndroid Build Coastguard Worker                 if (field_data_size < sizeof(mz_uint64) * 2)
5433*da0073e9SAndroid Build Coastguard Worker                 {
5434*da0073e9SAndroid Build Coastguard Worker                     mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5435*da0073e9SAndroid Build Coastguard Worker                     goto handle_failure;
5436*da0073e9SAndroid Build Coastguard Worker                 }
5437*da0073e9SAndroid Build Coastguard Worker 
5438*da0073e9SAndroid Build Coastguard Worker                 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
5439*da0073e9SAndroid Build Coastguard Worker                 local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
5440*da0073e9SAndroid Build Coastguard Worker 
5441*da0073e9SAndroid Build Coastguard Worker                 found_zip64_ext_data_in_ldir = MZ_TRUE;
5442*da0073e9SAndroid Build Coastguard Worker                 break;
5443*da0073e9SAndroid Build Coastguard Worker             }
5444*da0073e9SAndroid Build Coastguard Worker 
5445*da0073e9SAndroid Build Coastguard Worker             pExtra_data += field_total_size;
5446*da0073e9SAndroid Build Coastguard Worker             extra_size_remaining -= field_total_size;
5447*da0073e9SAndroid Build Coastguard Worker         } while (extra_size_remaining);
5448*da0073e9SAndroid Build Coastguard Worker     }
5449*da0073e9SAndroid Build Coastguard Worker 
5450*da0073e9SAndroid Build Coastguard Worker     /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */
5451*da0073e9SAndroid Build Coastguard Worker     /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */
5452*da0073e9SAndroid Build Coastguard Worker     if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
5453*da0073e9SAndroid Build Coastguard Worker     {
5454*da0073e9SAndroid Build Coastguard Worker         mz_uint8 descriptor_buf[32];
5455*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5456*da0073e9SAndroid Build Coastguard Worker         mz_bool has_id;
5457*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5458*da0073e9SAndroid Build Coastguard Worker         const mz_uint8 *pSrc;
5459*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5460*da0073e9SAndroid Build Coastguard Worker         mz_uint32 file_crc32;
5461*da0073e9SAndroid Build Coastguard Worker         mz_uint64 comp_size = 0, uncomp_size = 0;
5462*da0073e9SAndroid Build Coastguard Worker 
5463*da0073e9SAndroid Build Coastguard Worker         mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
5464*da0073e9SAndroid Build Coastguard Worker 
5465*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s))
5466*da0073e9SAndroid Build Coastguard Worker         {
5467*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5468*da0073e9SAndroid Build Coastguard Worker             goto handle_failure;
5469*da0073e9SAndroid Build Coastguard Worker         }
5470*da0073e9SAndroid Build Coastguard Worker 
5471*da0073e9SAndroid Build Coastguard Worker         has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
5472*da0073e9SAndroid Build Coastguard Worker         pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
5473*da0073e9SAndroid Build Coastguard Worker 
5474*da0073e9SAndroid Build Coastguard Worker         file_crc32 = MZ_READ_LE32(pSrc);
5475*da0073e9SAndroid Build Coastguard Worker 
5476*da0073e9SAndroid Build Coastguard Worker         if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
5477*da0073e9SAndroid Build Coastguard Worker         {
5478*da0073e9SAndroid Build Coastguard Worker             comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
5479*da0073e9SAndroid Build Coastguard Worker             uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
5480*da0073e9SAndroid Build Coastguard Worker         }
5481*da0073e9SAndroid Build Coastguard Worker         else
5482*da0073e9SAndroid Build Coastguard Worker         {
5483*da0073e9SAndroid Build Coastguard Worker             comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
5484*da0073e9SAndroid Build Coastguard Worker             uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
5485*da0073e9SAndroid Build Coastguard Worker         }
5486*da0073e9SAndroid Build Coastguard Worker 
5487*da0073e9SAndroid Build Coastguard Worker         if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
5488*da0073e9SAndroid Build Coastguard Worker         {
5489*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5490*da0073e9SAndroid Build Coastguard Worker             goto handle_failure;
5491*da0073e9SAndroid Build Coastguard Worker         }
5492*da0073e9SAndroid Build Coastguard Worker     }
5493*da0073e9SAndroid Build Coastguard Worker     else
5494*da0073e9SAndroid Build Coastguard Worker     {
5495*da0073e9SAndroid Build Coastguard Worker         if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size))
5496*da0073e9SAndroid Build Coastguard Worker         {
5497*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5498*da0073e9SAndroid Build Coastguard Worker             goto handle_failure;
5499*da0073e9SAndroid Build Coastguard Worker         }
5500*da0073e9SAndroid Build Coastguard Worker     }
5501*da0073e9SAndroid Build Coastguard Worker 
5502*da0073e9SAndroid Build Coastguard Worker     mz_zip_array_clear(pZip, &file_data_array);
5503*da0073e9SAndroid Build Coastguard Worker 
5504*da0073e9SAndroid Build Coastguard Worker     if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
5505*da0073e9SAndroid Build Coastguard Worker     {
5506*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
5507*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
5508*da0073e9SAndroid Build Coastguard Worker 
5509*da0073e9SAndroid Build Coastguard Worker         /* 1 more check to be sure, although the extract checks too. */
5510*da0073e9SAndroid Build Coastguard Worker         if (uncomp_crc32 != file_stat.m_crc32)
5511*da0073e9SAndroid Build Coastguard Worker         {
5512*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5513*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
5514*da0073e9SAndroid Build Coastguard Worker         }
5515*da0073e9SAndroid Build Coastguard Worker     }
5516*da0073e9SAndroid Build Coastguard Worker 
5517*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
5518*da0073e9SAndroid Build Coastguard Worker 
5519*da0073e9SAndroid Build Coastguard Worker handle_failure:
5520*da0073e9SAndroid Build Coastguard Worker     mz_zip_array_clear(pZip, &file_data_array);
5521*da0073e9SAndroid Build Coastguard Worker     return MZ_FALSE;
5522*da0073e9SAndroid Build Coastguard Worker }
5523*da0073e9SAndroid Build Coastguard Worker 
mz_zip_validate_archive(mz_zip_archive * pZip,mz_uint flags)5524*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
5525*da0073e9SAndroid Build Coastguard Worker {
5526*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5527*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState;
5528*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5529*da0073e9SAndroid Build Coastguard Worker     uint32_t i;
5530*da0073e9SAndroid Build Coastguard Worker 
5531*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5532*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5533*da0073e9SAndroid Build Coastguard Worker 
5534*da0073e9SAndroid Build Coastguard Worker     pState = pZip->m_pState;
5535*da0073e9SAndroid Build Coastguard Worker 
5536*da0073e9SAndroid Build Coastguard Worker     /* Basic sanity checks */
5537*da0073e9SAndroid Build Coastguard Worker     if (!pState->m_zip64)
5538*da0073e9SAndroid Build Coastguard Worker     {
5539*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files > MZ_UINT16_MAX)
5540*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5541*da0073e9SAndroid Build Coastguard Worker 
5542*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_archive_size > MZ_UINT32_MAX)
5543*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5544*da0073e9SAndroid Build Coastguard Worker     }
5545*da0073e9SAndroid Build Coastguard Worker     else
5546*da0073e9SAndroid Build Coastguard Worker     {
5547*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files >= MZ_UINT32_MAX)
5548*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5549*da0073e9SAndroid Build Coastguard Worker 
5550*da0073e9SAndroid Build Coastguard Worker         if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5551*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5552*da0073e9SAndroid Build Coastguard Worker     }
5553*da0073e9SAndroid Build Coastguard Worker 
5554*da0073e9SAndroid Build Coastguard Worker     for (i = 0; i < pZip->m_total_files; i++)
5555*da0073e9SAndroid Build Coastguard Worker     {
5556*da0073e9SAndroid Build Coastguard Worker         if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)
5557*da0073e9SAndroid Build Coastguard Worker         {
5558*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5559*da0073e9SAndroid Build Coastguard Worker             mz_uint32 found_index;
5560*da0073e9SAndroid Build Coastguard Worker             mz_zip_archive_file_stat stat;
5561*da0073e9SAndroid Build Coastguard Worker 
5562*da0073e9SAndroid Build Coastguard Worker             if (!mz_zip_reader_file_stat(pZip, i, &stat))
5563*da0073e9SAndroid Build Coastguard Worker                 return MZ_FALSE;
5564*da0073e9SAndroid Build Coastguard Worker 
5565*da0073e9SAndroid Build Coastguard Worker             if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5566*da0073e9SAndroid Build Coastguard Worker                 return MZ_FALSE;
5567*da0073e9SAndroid Build Coastguard Worker 
5568*da0073e9SAndroid Build Coastguard Worker             /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */
5569*da0073e9SAndroid Build Coastguard Worker             if (found_index != i)
5570*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5571*da0073e9SAndroid Build Coastguard Worker         }
5572*da0073e9SAndroid Build Coastguard Worker 
5573*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_validate_file(pZip, i, flags))
5574*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
5575*da0073e9SAndroid Build Coastguard Worker     }
5576*da0073e9SAndroid Build Coastguard Worker 
5577*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
5578*da0073e9SAndroid Build Coastguard Worker }
5579*da0073e9SAndroid Build Coastguard Worker 
mz_zip_validate_mem_archive(const void * pMem,size_t size,mz_uint flags,mz_zip_error * pErr)5580*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
5581*da0073e9SAndroid Build Coastguard Worker {
5582*da0073e9SAndroid Build Coastguard Worker     mz_bool success = MZ_TRUE;
5583*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive zip;
5584*da0073e9SAndroid Build Coastguard Worker     mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5585*da0073e9SAndroid Build Coastguard Worker 
5586*da0073e9SAndroid Build Coastguard Worker     if ((!pMem) || (!size))
5587*da0073e9SAndroid Build Coastguard Worker     {
5588*da0073e9SAndroid Build Coastguard Worker         if (pErr)
5589*da0073e9SAndroid Build Coastguard Worker             *pErr = MZ_ZIP_INVALID_PARAMETER;
5590*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5591*da0073e9SAndroid Build Coastguard Worker     }
5592*da0073e9SAndroid Build Coastguard Worker 
5593*da0073e9SAndroid Build Coastguard Worker     mz_zip_zero_struct(&zip);
5594*da0073e9SAndroid Build Coastguard Worker 
5595*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5596*da0073e9SAndroid Build Coastguard Worker     {
5597*da0073e9SAndroid Build Coastguard Worker         if (pErr)
5598*da0073e9SAndroid Build Coastguard Worker             *pErr = zip.m_last_error;
5599*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5600*da0073e9SAndroid Build Coastguard Worker     }
5601*da0073e9SAndroid Build Coastguard Worker 
5602*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_validate_archive(&zip, flags))
5603*da0073e9SAndroid Build Coastguard Worker     {
5604*da0073e9SAndroid Build Coastguard Worker         actual_err = zip.m_last_error;
5605*da0073e9SAndroid Build Coastguard Worker         success = MZ_FALSE;
5606*da0073e9SAndroid Build Coastguard Worker     }
5607*da0073e9SAndroid Build Coastguard Worker 
5608*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_end_internal(&zip, success))
5609*da0073e9SAndroid Build Coastguard Worker     {
5610*da0073e9SAndroid Build Coastguard Worker         if (!actual_err)
5611*da0073e9SAndroid Build Coastguard Worker             actual_err = zip.m_last_error;
5612*da0073e9SAndroid Build Coastguard Worker         success = MZ_FALSE;
5613*da0073e9SAndroid Build Coastguard Worker     }
5614*da0073e9SAndroid Build Coastguard Worker 
5615*da0073e9SAndroid Build Coastguard Worker     if (pErr)
5616*da0073e9SAndroid Build Coastguard Worker         *pErr = actual_err;
5617*da0073e9SAndroid Build Coastguard Worker 
5618*da0073e9SAndroid Build Coastguard Worker     return success;
5619*da0073e9SAndroid Build Coastguard Worker }
5620*da0073e9SAndroid Build Coastguard Worker 
5621*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
mz_zip_validate_file_archive(const char * pFilename,mz_uint flags,mz_zip_error * pErr)5622*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
5623*da0073e9SAndroid Build Coastguard Worker {
5624*da0073e9SAndroid Build Coastguard Worker     mz_bool success = MZ_TRUE;
5625*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive zip;
5626*da0073e9SAndroid Build Coastguard Worker     mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5627*da0073e9SAndroid Build Coastguard Worker 
5628*da0073e9SAndroid Build Coastguard Worker     if (!pFilename)
5629*da0073e9SAndroid Build Coastguard Worker     {
5630*da0073e9SAndroid Build Coastguard Worker         if (pErr)
5631*da0073e9SAndroid Build Coastguard Worker             *pErr = MZ_ZIP_INVALID_PARAMETER;
5632*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5633*da0073e9SAndroid Build Coastguard Worker     }
5634*da0073e9SAndroid Build Coastguard Worker 
5635*da0073e9SAndroid Build Coastguard Worker     mz_zip_zero_struct(&zip);
5636*da0073e9SAndroid Build Coastguard Worker 
5637*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5638*da0073e9SAndroid Build Coastguard Worker     {
5639*da0073e9SAndroid Build Coastguard Worker         if (pErr)
5640*da0073e9SAndroid Build Coastguard Worker             *pErr = zip.m_last_error;
5641*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5642*da0073e9SAndroid Build Coastguard Worker     }
5643*da0073e9SAndroid Build Coastguard Worker 
5644*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_validate_archive(&zip, flags))
5645*da0073e9SAndroid Build Coastguard Worker     {
5646*da0073e9SAndroid Build Coastguard Worker         actual_err = zip.m_last_error;
5647*da0073e9SAndroid Build Coastguard Worker         success = MZ_FALSE;
5648*da0073e9SAndroid Build Coastguard Worker     }
5649*da0073e9SAndroid Build Coastguard Worker 
5650*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_end_internal(&zip, success))
5651*da0073e9SAndroid Build Coastguard Worker     {
5652*da0073e9SAndroid Build Coastguard Worker         if (!actual_err)
5653*da0073e9SAndroid Build Coastguard Worker             actual_err = zip.m_last_error;
5654*da0073e9SAndroid Build Coastguard Worker         success = MZ_FALSE;
5655*da0073e9SAndroid Build Coastguard Worker     }
5656*da0073e9SAndroid Build Coastguard Worker 
5657*da0073e9SAndroid Build Coastguard Worker     if (pErr)
5658*da0073e9SAndroid Build Coastguard Worker         *pErr = actual_err;
5659*da0073e9SAndroid Build Coastguard Worker 
5660*da0073e9SAndroid Build Coastguard Worker     return success;
5661*da0073e9SAndroid Build Coastguard Worker }
5662*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
5663*da0073e9SAndroid Build Coastguard Worker 
5664*da0073e9SAndroid Build Coastguard Worker /* ------------------- .ZIP archive writing */
5665*da0073e9SAndroid Build Coastguard Worker 
5666*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5667*da0073e9SAndroid Build Coastguard Worker 
mz_write_le16(mz_uint8 * p,mz_uint16 v)5668*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)
5669*da0073e9SAndroid Build Coastguard Worker {
5670*da0073e9SAndroid Build Coastguard Worker     p[0] = (mz_uint8)v;
5671*da0073e9SAndroid Build Coastguard Worker     p[1] = (mz_uint8)(v >> 8);
5672*da0073e9SAndroid Build Coastguard Worker }
mz_write_le32(mz_uint8 * p,mz_uint32 v)5673*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
5674*da0073e9SAndroid Build Coastguard Worker {
5675*da0073e9SAndroid Build Coastguard Worker     p[0] = (mz_uint8)v;
5676*da0073e9SAndroid Build Coastguard Worker     p[1] = (mz_uint8)(v >> 8);
5677*da0073e9SAndroid Build Coastguard Worker     p[2] = (mz_uint8)(v >> 16);
5678*da0073e9SAndroid Build Coastguard Worker     p[3] = (mz_uint8)(v >> 24);
5679*da0073e9SAndroid Build Coastguard Worker }
mz_write_le64(mz_uint8 * p,mz_uint64 v)5680*da0073e9SAndroid Build Coastguard Worker static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
5681*da0073e9SAndroid Build Coastguard Worker {
5682*da0073e9SAndroid Build Coastguard Worker     mz_write_le32(p, (mz_uint32)v);
5683*da0073e9SAndroid Build Coastguard Worker     mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
5684*da0073e9SAndroid Build Coastguard Worker }
5685*da0073e9SAndroid Build Coastguard Worker 
5686*da0073e9SAndroid Build Coastguard Worker #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5687*da0073e9SAndroid Build Coastguard Worker #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5688*da0073e9SAndroid Build Coastguard Worker #define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
5689*da0073e9SAndroid Build Coastguard Worker 
mz_zip_heap_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5690*da0073e9SAndroid Build Coastguard Worker static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5691*da0073e9SAndroid Build Coastguard Worker {
5692*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5693*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState = pZip->m_pState;
5694*da0073e9SAndroid Build Coastguard Worker     mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5695*da0073e9SAndroid Build Coastguard Worker 
5696*da0073e9SAndroid Build Coastguard Worker     if (!n)
5697*da0073e9SAndroid Build Coastguard Worker         return 0;
5698*da0073e9SAndroid Build Coastguard Worker 
5699*da0073e9SAndroid Build Coastguard Worker     /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
5700*da0073e9SAndroid Build Coastguard Worker     if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5701*da0073e9SAndroid Build Coastguard Worker     {
5702*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5703*da0073e9SAndroid Build Coastguard Worker         return 0;
5704*da0073e9SAndroid Build Coastguard Worker     }
5705*da0073e9SAndroid Build Coastguard Worker 
5706*da0073e9SAndroid Build Coastguard Worker     if (new_size > pState->m_mem_capacity)
5707*da0073e9SAndroid Build Coastguard Worker     {
5708*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5709*da0073e9SAndroid Build Coastguard Worker         void *pNew_block;
5710*da0073e9SAndroid Build Coastguard Worker         size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5711*da0073e9SAndroid Build Coastguard Worker 
5712*da0073e9SAndroid Build Coastguard Worker         while (new_capacity < new_size)
5713*da0073e9SAndroid Build Coastguard Worker             new_capacity *= 2;
5714*da0073e9SAndroid Build Coastguard Worker 
5715*da0073e9SAndroid Build Coastguard Worker         if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5716*da0073e9SAndroid Build Coastguard Worker         {
5717*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5718*da0073e9SAndroid Build Coastguard Worker             return 0;
5719*da0073e9SAndroid Build Coastguard Worker         }
5720*da0073e9SAndroid Build Coastguard Worker 
5721*da0073e9SAndroid Build Coastguard Worker         pState->m_pMem = pNew_block;
5722*da0073e9SAndroid Build Coastguard Worker         pState->m_mem_capacity = new_capacity;
5723*da0073e9SAndroid Build Coastguard Worker     }
5724*da0073e9SAndroid Build Coastguard Worker     memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5725*da0073e9SAndroid Build Coastguard Worker     pState->m_mem_size = (size_t)new_size;
5726*da0073e9SAndroid Build Coastguard Worker     return n;
5727*da0073e9SAndroid Build Coastguard Worker }
5728*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_end_internal(mz_zip_archive * pZip,mz_bool set_last_error)5729*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
5730*da0073e9SAndroid Build Coastguard Worker {
5731*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5732*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState;
5733*da0073e9SAndroid Build Coastguard Worker     mz_bool status = MZ_TRUE;
5734*da0073e9SAndroid Build Coastguard Worker 
5735*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
5736*da0073e9SAndroid Build Coastguard Worker     {
5737*da0073e9SAndroid Build Coastguard Worker         if (set_last_error)
5738*da0073e9SAndroid Build Coastguard Worker             mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5739*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5740*da0073e9SAndroid Build Coastguard Worker     }
5741*da0073e9SAndroid Build Coastguard Worker 
5742*da0073e9SAndroid Build Coastguard Worker     pState = pZip->m_pState;
5743*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState = NULL;
5744*da0073e9SAndroid Build Coastguard Worker     mz_zip_array_clear(pZip, &pState->m_central_dir);
5745*da0073e9SAndroid Build Coastguard Worker     mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5746*da0073e9SAndroid Build Coastguard Worker     mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5747*da0073e9SAndroid Build Coastguard Worker 
5748*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
5749*da0073e9SAndroid Build Coastguard Worker     if (pState->m_pFile)
5750*da0073e9SAndroid Build Coastguard Worker     {
5751*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5752*da0073e9SAndroid Build Coastguard Worker         {
5753*da0073e9SAndroid Build Coastguard Worker             if (MZ_FCLOSE(pState->m_pFile) == EOF)
5754*da0073e9SAndroid Build Coastguard Worker             {
5755*da0073e9SAndroid Build Coastguard Worker                 if (set_last_error)
5756*da0073e9SAndroid Build Coastguard Worker                     mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5757*da0073e9SAndroid Build Coastguard Worker                 status = MZ_FALSE;
5758*da0073e9SAndroid Build Coastguard Worker             }
5759*da0073e9SAndroid Build Coastguard Worker         }
5760*da0073e9SAndroid Build Coastguard Worker 
5761*da0073e9SAndroid Build Coastguard Worker         pState->m_pFile = NULL;
5762*da0073e9SAndroid Build Coastguard Worker     }
5763*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
5764*da0073e9SAndroid Build Coastguard Worker 
5765*da0073e9SAndroid Build Coastguard Worker     if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5766*da0073e9SAndroid Build Coastguard Worker     {
5767*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5768*da0073e9SAndroid Build Coastguard Worker         pState->m_pMem = NULL;
5769*da0073e9SAndroid Build Coastguard Worker     }
5770*da0073e9SAndroid Build Coastguard Worker 
5771*da0073e9SAndroid Build Coastguard Worker     pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5772*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5773*da0073e9SAndroid Build Coastguard Worker     return status;
5774*da0073e9SAndroid Build Coastguard Worker }
5775*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init_v2(mz_zip_archive * pZip,mz_uint64 existing_size,mz_uint flags)5776*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
5777*da0073e9SAndroid Build Coastguard Worker {
5778*da0073e9SAndroid Build Coastguard Worker     mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5779*da0073e9SAndroid Build Coastguard Worker 
5780*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5781*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5782*da0073e9SAndroid Build Coastguard Worker 
5783*da0073e9SAndroid Build Coastguard Worker     if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5784*da0073e9SAndroid Build Coastguard Worker     {
5785*da0073e9SAndroid Build Coastguard Worker         if (!pZip->m_pRead)
5786*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5787*da0073e9SAndroid Build Coastguard Worker     }
5788*da0073e9SAndroid Build Coastguard Worker 
5789*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_file_offset_alignment)
5790*da0073e9SAndroid Build Coastguard Worker     {
5791*da0073e9SAndroid Build Coastguard Worker         /* Ensure user specified file offset alignment is a power of 2. */
5792*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5793*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5794*da0073e9SAndroid Build Coastguard Worker     }
5795*da0073e9SAndroid Build Coastguard Worker 
5796*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_pAlloc)
5797*da0073e9SAndroid Build Coastguard Worker         pZip->m_pAlloc = miniz_def_alloc_func;
5798*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_pFree)
5799*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree = miniz_def_free_func;
5800*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_pRealloc)
5801*da0073e9SAndroid Build Coastguard Worker         pZip->m_pRealloc = miniz_def_realloc_func;
5802*da0073e9SAndroid Build Coastguard Worker 
5803*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = existing_size;
5804*da0073e9SAndroid Build Coastguard Worker     pZip->m_central_directory_file_ofs = 0;
5805*da0073e9SAndroid Build Coastguard Worker     pZip->m_total_files = 0;
5806*da0073e9SAndroid Build Coastguard Worker 
5807*da0073e9SAndroid Build Coastguard Worker     if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5808*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5809*da0073e9SAndroid Build Coastguard Worker 
5810*da0073e9SAndroid Build Coastguard Worker     memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5811*da0073e9SAndroid Build Coastguard Worker 
5812*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
5813*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
5814*da0073e9SAndroid Build Coastguard Worker     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
5815*da0073e9SAndroid Build Coastguard Worker 
5816*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_zip64 = zip64;
5817*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
5818*da0073e9SAndroid Build Coastguard Worker 
5819*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_type = MZ_ZIP_TYPE_USER;
5820*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5821*da0073e9SAndroid Build Coastguard Worker 
5822*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
5823*da0073e9SAndroid Build Coastguard Worker }
5824*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init(mz_zip_archive * pZip,mz_uint64 existing_size)5825*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
5826*da0073e9SAndroid Build Coastguard Worker {
5827*da0073e9SAndroid Build Coastguard Worker     return mz_zip_writer_init_v2(pZip, existing_size, 0);
5828*da0073e9SAndroid Build Coastguard Worker }
5829*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init_heap_v2(mz_zip_archive * pZip,size_t size_to_reserve_at_beginning,size_t initial_allocation_size,mz_uint flags)5830*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
5831*da0073e9SAndroid Build Coastguard Worker {
5832*da0073e9SAndroid Build Coastguard Worker     pZip->m_pWrite = mz_zip_heap_write_func;
5833*da0073e9SAndroid Build Coastguard Worker     pZip->m_pNeeds_keepalive = NULL;
5834*da0073e9SAndroid Build Coastguard Worker 
5835*da0073e9SAndroid Build Coastguard Worker     if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5836*da0073e9SAndroid Build Coastguard Worker         pZip->m_pRead = mz_zip_mem_read_func;
5837*da0073e9SAndroid Build Coastguard Worker 
5838*da0073e9SAndroid Build Coastguard Worker     pZip->m_pIO_opaque = pZip;
5839*da0073e9SAndroid Build Coastguard Worker 
5840*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5841*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5842*da0073e9SAndroid Build Coastguard Worker 
5843*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
5844*da0073e9SAndroid Build Coastguard Worker 
5845*da0073e9SAndroid Build Coastguard Worker     if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5846*da0073e9SAndroid Build Coastguard Worker     {
5847*da0073e9SAndroid Build Coastguard Worker         if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5848*da0073e9SAndroid Build Coastguard Worker         {
5849*da0073e9SAndroid Build Coastguard Worker             mz_zip_writer_end_internal(pZip, MZ_FALSE);
5850*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5851*da0073e9SAndroid Build Coastguard Worker         }
5852*da0073e9SAndroid Build Coastguard Worker         pZip->m_pState->m_mem_capacity = initial_allocation_size;
5853*da0073e9SAndroid Build Coastguard Worker     }
5854*da0073e9SAndroid Build Coastguard Worker 
5855*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
5856*da0073e9SAndroid Build Coastguard Worker }
5857*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init_heap(mz_zip_archive * pZip,size_t size_to_reserve_at_beginning,size_t initial_allocation_size)5858*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
5859*da0073e9SAndroid Build Coastguard Worker {
5860*da0073e9SAndroid Build Coastguard Worker     return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5861*da0073e9SAndroid Build Coastguard Worker }
5862*da0073e9SAndroid Build Coastguard Worker 
5863*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
mz_zip_file_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5864*da0073e9SAndroid Build Coastguard Worker static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5865*da0073e9SAndroid Build Coastguard Worker {
5866*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5867*da0073e9SAndroid Build Coastguard Worker     mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5868*da0073e9SAndroid Build Coastguard Worker 
5869*da0073e9SAndroid Build Coastguard Worker     file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5870*da0073e9SAndroid Build Coastguard Worker 
5871*da0073e9SAndroid Build Coastguard Worker     if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5872*da0073e9SAndroid Build Coastguard Worker     {
5873*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5874*da0073e9SAndroid Build Coastguard Worker         return 0;
5875*da0073e9SAndroid Build Coastguard Worker     }
5876*da0073e9SAndroid Build Coastguard Worker 
5877*da0073e9SAndroid Build Coastguard Worker     return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5878*da0073e9SAndroid Build Coastguard Worker }
5879*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint64 size_to_reserve_at_beginning)5880*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5881*da0073e9SAndroid Build Coastguard Worker {
5882*da0073e9SAndroid Build Coastguard Worker     return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5883*da0073e9SAndroid Build Coastguard Worker }
5884*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init_file_v2(mz_zip_archive * pZip,const char * pFilename,mz_uint64 size_to_reserve_at_beginning,mz_uint flags)5885*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)
5886*da0073e9SAndroid Build Coastguard Worker {
5887*da0073e9SAndroid Build Coastguard Worker     MZ_FILE *pFile;
5888*da0073e9SAndroid Build Coastguard Worker 
5889*da0073e9SAndroid Build Coastguard Worker     pZip->m_pWrite = mz_zip_file_write_func;
5890*da0073e9SAndroid Build Coastguard Worker     pZip->m_pNeeds_keepalive = NULL;
5891*da0073e9SAndroid Build Coastguard Worker 
5892*da0073e9SAndroid Build Coastguard Worker     if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5893*da0073e9SAndroid Build Coastguard Worker         pZip->m_pRead = mz_zip_file_read_func;
5894*da0073e9SAndroid Build Coastguard Worker 
5895*da0073e9SAndroid Build Coastguard Worker     pZip->m_pIO_opaque = pZip;
5896*da0073e9SAndroid Build Coastguard Worker 
5897*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5898*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5899*da0073e9SAndroid Build Coastguard Worker 
5900*da0073e9SAndroid Build Coastguard Worker     if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
5901*da0073e9SAndroid Build Coastguard Worker     {
5902*da0073e9SAndroid Build Coastguard Worker         mz_zip_writer_end(pZip);
5903*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5904*da0073e9SAndroid Build Coastguard Worker     }
5905*da0073e9SAndroid Build Coastguard Worker 
5906*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_pFile = pFile;
5907*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
5908*da0073e9SAndroid Build Coastguard Worker 
5909*da0073e9SAndroid Build Coastguard Worker     if (size_to_reserve_at_beginning)
5910*da0073e9SAndroid Build Coastguard Worker     {
5911*da0073e9SAndroid Build Coastguard Worker         mz_uint64 cur_ofs = 0;
5912*da0073e9SAndroid Build Coastguard Worker         char buf[4096];
5913*da0073e9SAndroid Build Coastguard Worker 
5914*da0073e9SAndroid Build Coastguard Worker         MZ_CLEAR_OBJ(buf);
5915*da0073e9SAndroid Build Coastguard Worker 
5916*da0073e9SAndroid Build Coastguard Worker         do
5917*da0073e9SAndroid Build Coastguard Worker         {
5918*da0073e9SAndroid Build Coastguard Worker             size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5919*da0073e9SAndroid Build Coastguard Worker             if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5920*da0073e9SAndroid Build Coastguard Worker             {
5921*da0073e9SAndroid Build Coastguard Worker                 mz_zip_writer_end(pZip);
5922*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
5923*da0073e9SAndroid Build Coastguard Worker             }
5924*da0073e9SAndroid Build Coastguard Worker             cur_ofs += n;
5925*da0073e9SAndroid Build Coastguard Worker             size_to_reserve_at_beginning -= n;
5926*da0073e9SAndroid Build Coastguard Worker         } while (size_to_reserve_at_beginning);
5927*da0073e9SAndroid Build Coastguard Worker     }
5928*da0073e9SAndroid Build Coastguard Worker 
5929*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
5930*da0073e9SAndroid Build Coastguard Worker }
5931*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init_cfile(mz_zip_archive * pZip,MZ_FILE * pFile,mz_uint flags)5932*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
5933*da0073e9SAndroid Build Coastguard Worker {
5934*da0073e9SAndroid Build Coastguard Worker     pZip->m_pWrite = mz_zip_file_write_func;
5935*da0073e9SAndroid Build Coastguard Worker     pZip->m_pNeeds_keepalive = NULL;
5936*da0073e9SAndroid Build Coastguard Worker 
5937*da0073e9SAndroid Build Coastguard Worker     if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5938*da0073e9SAndroid Build Coastguard Worker         pZip->m_pRead = mz_zip_file_read_func;
5939*da0073e9SAndroid Build Coastguard Worker 
5940*da0073e9SAndroid Build Coastguard Worker     pZip->m_pIO_opaque = pZip;
5941*da0073e9SAndroid Build Coastguard Worker 
5942*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_init_v2(pZip, 0, flags))
5943*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
5944*da0073e9SAndroid Build Coastguard Worker 
5945*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_pFile = pFile;
5946*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5947*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
5948*da0073e9SAndroid Build Coastguard Worker 
5949*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
5950*da0073e9SAndroid Build Coastguard Worker }
5951*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
5952*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init_from_reader_v2(mz_zip_archive * pZip,const char * pFilename,mz_uint flags)5953*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
5954*da0073e9SAndroid Build Coastguard Worker {
5955*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5956*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState;
5957*da0073e9SAndroid Build Coastguard Worker 
5958*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5959*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5960*da0073e9SAndroid Build Coastguard Worker 
5961*da0073e9SAndroid Build Coastguard Worker     if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
5962*da0073e9SAndroid Build Coastguard Worker     {
5963*da0073e9SAndroid Build Coastguard Worker         /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */
5964*da0073e9SAndroid Build Coastguard Worker         if (!pZip->m_pState->m_zip64)
5965*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5966*da0073e9SAndroid Build Coastguard Worker     }
5967*da0073e9SAndroid Build Coastguard Worker 
5968*da0073e9SAndroid Build Coastguard Worker     /* No sense in trying to write to an archive that's already at the support max size */
5969*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pState->m_zip64)
5970*da0073e9SAndroid Build Coastguard Worker     {
5971*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files == MZ_UINT32_MAX)
5972*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5973*da0073e9SAndroid Build Coastguard Worker     }
5974*da0073e9SAndroid Build Coastguard Worker     else
5975*da0073e9SAndroid Build Coastguard Worker     {
5976*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files == MZ_UINT16_MAX)
5977*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5978*da0073e9SAndroid Build Coastguard Worker 
5979*da0073e9SAndroid Build Coastguard Worker         if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
5980*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5981*da0073e9SAndroid Build Coastguard Worker     }
5982*da0073e9SAndroid Build Coastguard Worker 
5983*da0073e9SAndroid Build Coastguard Worker     pState = pZip->m_pState;
5984*da0073e9SAndroid Build Coastguard Worker 
5985*da0073e9SAndroid Build Coastguard Worker     if (pState->m_pFile)
5986*da0073e9SAndroid Build Coastguard Worker     {
5987*da0073e9SAndroid Build Coastguard Worker #ifdef MINIZ_NO_STDIO
5988*da0073e9SAndroid Build Coastguard Worker         (void)pFilename;
5989*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5990*da0073e9SAndroid Build Coastguard Worker #else
5991*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pIO_opaque != pZip)
5992*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5993*da0073e9SAndroid Build Coastguard Worker 
5994*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5995*da0073e9SAndroid Build Coastguard Worker         {
5996*da0073e9SAndroid Build Coastguard Worker             if (!pFilename)
5997*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5998*da0073e9SAndroid Build Coastguard Worker 
5999*da0073e9SAndroid Build Coastguard Worker             /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
6000*da0073e9SAndroid Build Coastguard Worker             if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
6001*da0073e9SAndroid Build Coastguard Worker             {
6002*da0073e9SAndroid Build Coastguard Worker                 /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
6003*da0073e9SAndroid Build Coastguard Worker                 mz_zip_reader_end_internal(pZip, MZ_FALSE);
6004*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6005*da0073e9SAndroid Build Coastguard Worker             }
6006*da0073e9SAndroid Build Coastguard Worker         }
6007*da0073e9SAndroid Build Coastguard Worker 
6008*da0073e9SAndroid Build Coastguard Worker         pZip->m_pWrite = mz_zip_file_write_func;
6009*da0073e9SAndroid Build Coastguard Worker         pZip->m_pNeeds_keepalive = NULL;
6010*da0073e9SAndroid Build Coastguard Worker #endif /* #ifdef MINIZ_NO_STDIO */
6011*da0073e9SAndroid Build Coastguard Worker     }
6012*da0073e9SAndroid Build Coastguard Worker     else if (pState->m_pMem)
6013*da0073e9SAndroid Build Coastguard Worker     {
6014*da0073e9SAndroid Build Coastguard Worker         /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
6015*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pIO_opaque != pZip)
6016*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6017*da0073e9SAndroid Build Coastguard Worker 
6018*da0073e9SAndroid Build Coastguard Worker         pState->m_mem_capacity = pState->m_mem_size;
6019*da0073e9SAndroid Build Coastguard Worker         pZip->m_pWrite = mz_zip_heap_write_func;
6020*da0073e9SAndroid Build Coastguard Worker         pZip->m_pNeeds_keepalive = NULL;
6021*da0073e9SAndroid Build Coastguard Worker     }
6022*da0073e9SAndroid Build Coastguard Worker     /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
6023*da0073e9SAndroid Build Coastguard Worker     else if (!pZip->m_pWrite)
6024*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6025*da0073e9SAndroid Build Coastguard Worker 
6026*da0073e9SAndroid Build Coastguard Worker     /* Start writing new files at the archive's current central directory location. */
6027*da0073e9SAndroid Build Coastguard Worker     /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */
6028*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = pZip->m_central_directory_file_ofs;
6029*da0073e9SAndroid Build Coastguard Worker     pZip->m_central_directory_file_ofs = 0;
6030*da0073e9SAndroid Build Coastguard Worker 
6031*da0073e9SAndroid Build Coastguard Worker     /* Clear the sorted central dir offsets, they aren't useful or maintained now. */
6032*da0073e9SAndroid Build Coastguard Worker     /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */
6033*da0073e9SAndroid Build Coastguard Worker     /* TODO: We could easily maintain the sorted central directory offsets. */
6034*da0073e9SAndroid Build Coastguard Worker     mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
6035*da0073e9SAndroid Build Coastguard Worker 
6036*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
6037*da0073e9SAndroid Build Coastguard Worker 
6038*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6039*da0073e9SAndroid Build Coastguard Worker }
6040*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_init_from_reader(mz_zip_archive * pZip,const char * pFilename)6041*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
6042*da0073e9SAndroid Build Coastguard Worker {
6043*da0073e9SAndroid Build Coastguard Worker     return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
6044*da0073e9SAndroid Build Coastguard Worker }
6045*da0073e9SAndroid Build Coastguard Worker 
6046*da0073e9SAndroid Build Coastguard Worker /* TODO: pArchive_name is a terrible name here! */
mz_zip_writer_add_mem(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,mz_uint level_and_flags)6047*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
6048*da0073e9SAndroid Build Coastguard Worker {
6049*da0073e9SAndroid Build Coastguard Worker     return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
6050*da0073e9SAndroid Build Coastguard Worker }
6051*da0073e9SAndroid Build Coastguard Worker 
6052*da0073e9SAndroid Build Coastguard Worker typedef struct
6053*da0073e9SAndroid Build Coastguard Worker {
6054*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive *m_pZip;
6055*da0073e9SAndroid Build Coastguard Worker     mz_uint64 m_cur_archive_file_ofs;
6056*da0073e9SAndroid Build Coastguard Worker     mz_uint64 m_comp_size;
6057*da0073e9SAndroid Build Coastguard Worker } mz_zip_writer_add_state;
6058*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_add_put_buf_callback(const void * pBuf,int len,void * pUser)6059*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
6060*da0073e9SAndroid Build Coastguard Worker {
6061*da0073e9SAndroid Build Coastguard Worker     mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
6062*da0073e9SAndroid Build Coastguard Worker     if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
6063*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
6064*da0073e9SAndroid Build Coastguard Worker 
6065*da0073e9SAndroid Build Coastguard Worker     pState->m_cur_archive_file_ofs += len;
6066*da0073e9SAndroid Build Coastguard Worker     pState->m_comp_size += len;
6067*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6068*da0073e9SAndroid Build Coastguard Worker }
6069*da0073e9SAndroid Build Coastguard Worker 
6070*da0073e9SAndroid Build Coastguard Worker #define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
6071*da0073e9SAndroid Build Coastguard Worker #define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
mz_zip_writer_create_zip64_extra_data(mz_uint8 * pBuf,mz_uint64 * pUncomp_size,mz_uint64 * pComp_size,mz_uint64 * pLocal_header_ofs)6072*da0073e9SAndroid Build Coastguard Worker static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)
6073*da0073e9SAndroid Build Coastguard Worker {
6074*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pDst = pBuf;
6075*da0073e9SAndroid Build Coastguard Worker     mz_uint32 field_size = 0;
6076*da0073e9SAndroid Build Coastguard Worker 
6077*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6078*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + 2, 0);
6079*da0073e9SAndroid Build Coastguard Worker     pDst += sizeof(mz_uint16) * 2;
6080*da0073e9SAndroid Build Coastguard Worker 
6081*da0073e9SAndroid Build Coastguard Worker     if (pUncomp_size)
6082*da0073e9SAndroid Build Coastguard Worker     {
6083*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(pDst, *pUncomp_size);
6084*da0073e9SAndroid Build Coastguard Worker         pDst += sizeof(mz_uint64);
6085*da0073e9SAndroid Build Coastguard Worker         field_size += sizeof(mz_uint64);
6086*da0073e9SAndroid Build Coastguard Worker     }
6087*da0073e9SAndroid Build Coastguard Worker 
6088*da0073e9SAndroid Build Coastguard Worker     if (pComp_size)
6089*da0073e9SAndroid Build Coastguard Worker     {
6090*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(pDst, *pComp_size);
6091*da0073e9SAndroid Build Coastguard Worker         pDst += sizeof(mz_uint64);
6092*da0073e9SAndroid Build Coastguard Worker         field_size += sizeof(mz_uint64);
6093*da0073e9SAndroid Build Coastguard Worker     }
6094*da0073e9SAndroid Build Coastguard Worker 
6095*da0073e9SAndroid Build Coastguard Worker     if (pLocal_header_ofs)
6096*da0073e9SAndroid Build Coastguard Worker     {
6097*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
6098*da0073e9SAndroid Build Coastguard Worker         pDst += sizeof(mz_uint64);
6099*da0073e9SAndroid Build Coastguard Worker         field_size += sizeof(mz_uint64);
6100*da0073e9SAndroid Build Coastguard Worker     }
6101*da0073e9SAndroid Build Coastguard Worker 
6102*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pBuf + 2, field_size);
6103*da0073e9SAndroid Build Coastguard Worker 
6104*da0073e9SAndroid Build Coastguard Worker     return (mz_uint32)(pDst - pBuf);
6105*da0073e9SAndroid Build Coastguard Worker }
6106*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_create_local_dir_header(mz_zip_archive * pZip,mz_uint8 * pDst,mz_uint16 filename_size,mz_uint16 extra_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date)6107*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
6108*da0073e9SAndroid Build Coastguard Worker {
6109*da0073e9SAndroid Build Coastguard Worker     (void)pZip;
6110*da0073e9SAndroid Build Coastguard Worker     memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
6111*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
6112*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6113*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
6114*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
6115*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
6116*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
6117*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
6118*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6119*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6120*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6121*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6122*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6123*da0073e9SAndroid Build Coastguard Worker }
6124*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_create_central_dir_header(mz_zip_archive * pZip,mz_uint8 * pDst,mz_uint16 filename_size,mz_uint16 extra_size,mz_uint16 comment_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date,mz_uint64 local_header_ofs,mz_uint32 ext_attributes)6125*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst,
6126*da0073e9SAndroid Build Coastguard Worker                                                        mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
6127*da0073e9SAndroid Build Coastguard Worker                                                        mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6128*da0073e9SAndroid Build Coastguard Worker                                                        mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6129*da0073e9SAndroid Build Coastguard Worker                                                        mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
6130*da0073e9SAndroid Build Coastguard Worker {
6131*da0073e9SAndroid Build Coastguard Worker     (void)pZip;
6132*da0073e9SAndroid Build Coastguard Worker     memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6133*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6134*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6135*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6136*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6137*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6138*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6139*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6140*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6141*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6142*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6143*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6144*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6145*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6146*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
6147*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6148*da0073e9SAndroid Build Coastguard Worker }
6149*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_add_to_central_dir(mz_zip_archive * pZip,const char * pFilename,mz_uint16 filename_size,const void * pExtra,mz_uint16 extra_size,const void * pComment,mz_uint16 comment_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date,mz_uint64 local_header_ofs,mz_uint32 ext_attributes,const char * user_extra_data,mz_uint user_extra_data_len)6150*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6151*da0073e9SAndroid Build Coastguard Worker                                                 const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,
6152*da0073e9SAndroid Build Coastguard Worker                                                 mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6153*da0073e9SAndroid Build Coastguard Worker                                                 mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6154*da0073e9SAndroid Build Coastguard Worker                                                 mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
6155*da0073e9SAndroid Build Coastguard Worker                                                 const char *user_extra_data, mz_uint user_extra_data_len)
6156*da0073e9SAndroid Build Coastguard Worker {
6157*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState = pZip->m_pState;
6158*da0073e9SAndroid Build Coastguard Worker     mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6159*da0073e9SAndroid Build Coastguard Worker     size_t orig_central_dir_size = pState->m_central_dir.m_size;
6160*da0073e9SAndroid Build Coastguard Worker     mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6161*da0073e9SAndroid Build Coastguard Worker 
6162*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_pState->m_zip64)
6163*da0073e9SAndroid Build Coastguard Worker     {
6164*da0073e9SAndroid Build Coastguard Worker         if (local_header_ofs > 0xFFFFFFFF)
6165*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
6166*da0073e9SAndroid Build Coastguard Worker     }
6167*da0073e9SAndroid Build Coastguard Worker 
6168*da0073e9SAndroid Build Coastguard Worker     /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6169*da0073e9SAndroid Build Coastguard Worker     if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX)
6170*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6171*da0073e9SAndroid Build Coastguard Worker 
6172*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, (mz_uint16)(extra_size + user_extra_data_len), comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
6173*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6174*da0073e9SAndroid Build Coastguard Worker 
6175*da0073e9SAndroid Build Coastguard Worker     if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6176*da0073e9SAndroid Build Coastguard Worker         (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
6177*da0073e9SAndroid Build Coastguard Worker         (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
6178*da0073e9SAndroid Build Coastguard Worker         (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
6179*da0073e9SAndroid Build Coastguard Worker         (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
6180*da0073e9SAndroid Build Coastguard Worker         (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
6181*da0073e9SAndroid Build Coastguard Worker     {
6182*da0073e9SAndroid Build Coastguard Worker         /* Try to resize the central directory array back into its original state. */
6183*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6184*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6185*da0073e9SAndroid Build Coastguard Worker     }
6186*da0073e9SAndroid Build Coastguard Worker 
6187*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6188*da0073e9SAndroid Build Coastguard Worker }
6189*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_validate_archive_name(const char * pArchive_name)6190*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
6191*da0073e9SAndroid Build Coastguard Worker {
6192*da0073e9SAndroid Build Coastguard Worker     /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */
6193*da0073e9SAndroid Build Coastguard Worker     if (*pArchive_name == '/')
6194*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
6195*da0073e9SAndroid Build Coastguard Worker 
6196*da0073e9SAndroid Build Coastguard Worker     /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/
6197*da0073e9SAndroid Build Coastguard Worker 
6198*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6199*da0073e9SAndroid Build Coastguard Worker }
6200*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive * pZip)6201*da0073e9SAndroid Build Coastguard Worker static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
6202*da0073e9SAndroid Build Coastguard Worker {
6203*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6204*da0073e9SAndroid Build Coastguard Worker     mz_uint32 n;
6205*da0073e9SAndroid Build Coastguard Worker     if (!pZip->m_file_offset_alignment)
6206*da0073e9SAndroid Build Coastguard Worker         return 0;
6207*da0073e9SAndroid Build Coastguard Worker     n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6208*da0073e9SAndroid Build Coastguard Worker     return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
6209*da0073e9SAndroid Build Coastguard Worker }
6210*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_write_zeros(mz_zip_archive * pZip,mz_uint64 cur_file_ofs,mz_uint32 n)6211*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
6212*da0073e9SAndroid Build Coastguard Worker {
6213*da0073e9SAndroid Build Coastguard Worker     char buf[4096];
6214*da0073e9SAndroid Build Coastguard Worker     memset(buf, 0, MZ_MIN(sizeof(buf), n));
6215*da0073e9SAndroid Build Coastguard Worker     while (n)
6216*da0073e9SAndroid Build Coastguard Worker     {
6217*da0073e9SAndroid Build Coastguard Worker         mz_uint32 s = MZ_MIN(sizeof(buf), n);
6218*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6219*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6220*da0073e9SAndroid Build Coastguard Worker 
6221*da0073e9SAndroid Build Coastguard Worker         cur_file_ofs += s;
6222*da0073e9SAndroid Build Coastguard Worker         n -= s;
6223*da0073e9SAndroid Build Coastguard Worker     }
6224*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6225*da0073e9SAndroid Build Coastguard Worker }
6226*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_add_mem_ex(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,mz_uint64 uncomp_size,mz_uint32 uncomp_crc32)6227*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6228*da0073e9SAndroid Build Coastguard Worker                                  mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
6229*da0073e9SAndroid Build Coastguard Worker {
6230*da0073e9SAndroid Build Coastguard Worker     return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0);
6231*da0073e9SAndroid Build Coastguard Worker }
6232*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_add_mem_ex_v2(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,mz_uint64 uncomp_size,mz_uint32 uncomp_crc32,MZ_TIME_T * last_modified,const char * user_extra_data,mz_uint user_extra_data_len,const char * user_extra_data_central,mz_uint user_extra_data_central_len)6233*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size,
6234*da0073e9SAndroid Build Coastguard Worker                                     mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
6235*da0073e9SAndroid Build Coastguard Worker                                     const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6236*da0073e9SAndroid Build Coastguard Worker {
6237*da0073e9SAndroid Build Coastguard Worker     mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6238*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6239*da0073e9SAndroid Build Coastguard Worker     mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6240*da0073e9SAndroid Build Coastguard Worker     mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6241*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6242*da0073e9SAndroid Build Coastguard Worker     size_t archive_name_size;
6243*da0073e9SAndroid Build Coastguard Worker     mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6244*da0073e9SAndroid Build Coastguard Worker     tdefl_compressor *pComp = NULL;
6245*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6246*da0073e9SAndroid Build Coastguard Worker     mz_bool store_data_uncompressed;
6247*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6248*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState;
6249*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pExtra_data = NULL;
6250*da0073e9SAndroid Build Coastguard Worker     mz_uint32 extra_size = 0;
6251*da0073e9SAndroid Build Coastguard Worker     mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6252*da0073e9SAndroid Build Coastguard Worker     mz_uint16 bit_flags = 0;
6253*da0073e9SAndroid Build Coastguard Worker     mz_bool write_metadata_only = buf_size && !pBuf;
6254*da0073e9SAndroid Build Coastguard Worker 
6255*da0073e9SAndroid Build Coastguard Worker     if ((int)level_and_flags < 0)
6256*da0073e9SAndroid Build Coastguard Worker         level_and_flags = MZ_DEFAULT_LEVEL;
6257*da0073e9SAndroid Build Coastguard Worker 
6258*da0073e9SAndroid Build Coastguard Worker     if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
6259*da0073e9SAndroid Build Coastguard Worker         bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6260*da0073e9SAndroid Build Coastguard Worker 
6261*da0073e9SAndroid Build Coastguard Worker     if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6262*da0073e9SAndroid Build Coastguard Worker         bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6263*da0073e9SAndroid Build Coastguard Worker 
6264*da0073e9SAndroid Build Coastguard Worker     level = level_and_flags & 0xF;
6265*da0073e9SAndroid Build Coastguard Worker     store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6266*da0073e9SAndroid Build Coastguard Worker 
6267*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6268*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6269*da0073e9SAndroid Build Coastguard Worker 
6270*da0073e9SAndroid Build Coastguard Worker     pState = pZip->m_pState;
6271*da0073e9SAndroid Build Coastguard Worker 
6272*da0073e9SAndroid Build Coastguard Worker     if (pState->m_zip64)
6273*da0073e9SAndroid Build Coastguard Worker     {
6274*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files == MZ_UINT32_MAX)
6275*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6276*da0073e9SAndroid Build Coastguard Worker     }
6277*da0073e9SAndroid Build Coastguard Worker     else
6278*da0073e9SAndroid Build Coastguard Worker     {
6279*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files == MZ_UINT16_MAX)
6280*da0073e9SAndroid Build Coastguard Worker         {
6281*da0073e9SAndroid Build Coastguard Worker             pState->m_zip64 = MZ_TRUE;
6282*da0073e9SAndroid Build Coastguard Worker             /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6283*da0073e9SAndroid Build Coastguard Worker         }
6284*da0073e9SAndroid Build Coastguard Worker         if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6285*da0073e9SAndroid Build Coastguard Worker         {
6286*da0073e9SAndroid Build Coastguard Worker             pState->m_zip64 = MZ_TRUE;
6287*da0073e9SAndroid Build Coastguard Worker             /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6288*da0073e9SAndroid Build Coastguard Worker         }
6289*da0073e9SAndroid Build Coastguard Worker     }
6290*da0073e9SAndroid Build Coastguard Worker 
6291*da0073e9SAndroid Build Coastguard Worker     if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6292*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6293*da0073e9SAndroid Build Coastguard Worker 
6294*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_validate_archive_name(pArchive_name))
6295*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6296*da0073e9SAndroid Build Coastguard Worker 
6297*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
6298*da0073e9SAndroid Build Coastguard Worker     if (last_modified != NULL)
6299*da0073e9SAndroid Build Coastguard Worker     {
6300*da0073e9SAndroid Build Coastguard Worker         mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
6301*da0073e9SAndroid Build Coastguard Worker     }
6302*da0073e9SAndroid Build Coastguard Worker     else
6303*da0073e9SAndroid Build Coastguard Worker     {
6304*da0073e9SAndroid Build Coastguard Worker         MZ_TIME_T cur_time;
6305*da0073e9SAndroid Build Coastguard Worker         time(&cur_time);
6306*da0073e9SAndroid Build Coastguard Worker         mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6307*da0073e9SAndroid Build Coastguard Worker     }
6308*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_TIME */
6309*da0073e9SAndroid Build Coastguard Worker 
6310*da0073e9SAndroid Build Coastguard Worker 	if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6311*da0073e9SAndroid Build Coastguard Worker 	{
6312*da0073e9SAndroid Build Coastguard Worker         if (!write_metadata_only) {
6313*da0073e9SAndroid Build Coastguard Worker             uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6314*da0073e9SAndroid Build Coastguard Worker         }
6315*da0073e9SAndroid Build Coastguard Worker 		uncomp_size = buf_size;
6316*da0073e9SAndroid Build Coastguard Worker 		if (uncomp_size <= 3)
6317*da0073e9SAndroid Build Coastguard Worker 		{
6318*da0073e9SAndroid Build Coastguard Worker 			level = 0;
6319*da0073e9SAndroid Build Coastguard Worker 			store_data_uncompressed = MZ_TRUE;
6320*da0073e9SAndroid Build Coastguard Worker 		}
6321*da0073e9SAndroid Build Coastguard Worker 	}
6322*da0073e9SAndroid Build Coastguard Worker 
6323*da0073e9SAndroid Build Coastguard Worker     archive_name_size = strlen(pArchive_name);
6324*da0073e9SAndroid Build Coastguard Worker     if (archive_name_size > MZ_UINT16_MAX)
6325*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6326*da0073e9SAndroid Build Coastguard Worker 
6327*da0073e9SAndroid Build Coastguard Worker     num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6328*da0073e9SAndroid Build Coastguard Worker 
6329*da0073e9SAndroid Build Coastguard Worker     /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6330*da0073e9SAndroid Build Coastguard Worker     if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
6331*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6332*da0073e9SAndroid Build Coastguard Worker 
6333*da0073e9SAndroid Build Coastguard Worker     if (!pState->m_zip64)
6334*da0073e9SAndroid Build Coastguard Worker     {
6335*da0073e9SAndroid Build Coastguard Worker         /* Bail early if the archive would obviously become too large */
6336*da0073e9SAndroid Build Coastguard Worker         if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size
6337*da0073e9SAndroid Build Coastguard Worker 			+ MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len +
6338*da0073e9SAndroid Build Coastguard Worker 			pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len
6339*da0073e9SAndroid Build Coastguard Worker 			+ MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)
6340*da0073e9SAndroid Build Coastguard Worker         {
6341*da0073e9SAndroid Build Coastguard Worker             pState->m_zip64 = MZ_TRUE;
6342*da0073e9SAndroid Build Coastguard Worker             /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6343*da0073e9SAndroid Build Coastguard Worker         }
6344*da0073e9SAndroid Build Coastguard Worker     }
6345*da0073e9SAndroid Build Coastguard Worker 
6346*da0073e9SAndroid Build Coastguard Worker     if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
6347*da0073e9SAndroid Build Coastguard Worker     {
6348*da0073e9SAndroid Build Coastguard Worker         /* Set DOS Subdirectory attribute bit. */
6349*da0073e9SAndroid Build Coastguard Worker         ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
6350*da0073e9SAndroid Build Coastguard Worker 
6351*da0073e9SAndroid Build Coastguard Worker         /* Subdirectories cannot contain data. */
6352*da0073e9SAndroid Build Coastguard Worker         if ((buf_size) || (uncomp_size))
6353*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6354*da0073e9SAndroid Build Coastguard Worker     }
6355*da0073e9SAndroid Build Coastguard Worker 
6356*da0073e9SAndroid Build Coastguard Worker     /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */
6357*da0073e9SAndroid Build Coastguard Worker     if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6358*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6359*da0073e9SAndroid Build Coastguard Worker 
6360*da0073e9SAndroid Build Coastguard Worker     if ((!store_data_uncompressed) && (buf_size))
6361*da0073e9SAndroid Build Coastguard Worker     {
6362*da0073e9SAndroid Build Coastguard Worker         if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6363*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6364*da0073e9SAndroid Build Coastguard Worker     }
6365*da0073e9SAndroid Build Coastguard Worker 
6366*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6367*da0073e9SAndroid Build Coastguard Worker     {
6368*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6369*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
6370*da0073e9SAndroid Build Coastguard Worker     }
6371*da0073e9SAndroid Build Coastguard Worker 
6372*da0073e9SAndroid Build Coastguard Worker     local_dir_header_ofs += num_alignment_padding_bytes;
6373*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_file_offset_alignment)
6374*da0073e9SAndroid Build Coastguard Worker     {
6375*da0073e9SAndroid Build Coastguard Worker         MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6376*da0073e9SAndroid Build Coastguard Worker     }
6377*da0073e9SAndroid Build Coastguard Worker     cur_archive_file_ofs += num_alignment_padding_bytes;
6378*da0073e9SAndroid Build Coastguard Worker 
6379*da0073e9SAndroid Build Coastguard Worker     MZ_CLEAR_OBJ(local_dir_header);
6380*da0073e9SAndroid Build Coastguard Worker 
6381*da0073e9SAndroid Build Coastguard Worker     if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6382*da0073e9SAndroid Build Coastguard Worker     {
6383*da0073e9SAndroid Build Coastguard Worker         method = MZ_DEFLATED;
6384*da0073e9SAndroid Build Coastguard Worker     }
6385*da0073e9SAndroid Build Coastguard Worker 
6386*da0073e9SAndroid Build Coastguard Worker     if (pState->m_zip64)
6387*da0073e9SAndroid Build Coastguard Worker     {
6388*da0073e9SAndroid Build Coastguard Worker         if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6389*da0073e9SAndroid Build Coastguard Worker         {
6390*da0073e9SAndroid Build Coastguard Worker             pExtra_data = extra_data;
6391*da0073e9SAndroid Build Coastguard Worker             extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6392*da0073e9SAndroid Build Coastguard Worker                                                                (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6393*da0073e9SAndroid Build Coastguard Worker         }
6394*da0073e9SAndroid Build Coastguard Worker 
6395*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, bit_flags, dos_time, dos_date))
6396*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6397*da0073e9SAndroid Build Coastguard Worker 
6398*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6399*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6400*da0073e9SAndroid Build Coastguard Worker 
6401*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += sizeof(local_dir_header);
6402*da0073e9SAndroid Build Coastguard Worker 
6403*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6404*da0073e9SAndroid Build Coastguard Worker         {
6405*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6406*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6407*da0073e9SAndroid Build Coastguard Worker         }
6408*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += archive_name_size;
6409*da0073e9SAndroid Build Coastguard Worker 
6410*da0073e9SAndroid Build Coastguard Worker         if (pExtra_data != NULL)
6411*da0073e9SAndroid Build Coastguard Worker         {
6412*da0073e9SAndroid Build Coastguard Worker             if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6413*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6414*da0073e9SAndroid Build Coastguard Worker 
6415*da0073e9SAndroid Build Coastguard Worker             cur_archive_file_ofs += extra_size;
6416*da0073e9SAndroid Build Coastguard Worker         }
6417*da0073e9SAndroid Build Coastguard Worker     }
6418*da0073e9SAndroid Build Coastguard Worker     else
6419*da0073e9SAndroid Build Coastguard Worker     {
6420*da0073e9SAndroid Build Coastguard Worker         if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6421*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6422*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
6423*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6424*da0073e9SAndroid Build Coastguard Worker 
6425*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6426*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6427*da0073e9SAndroid Build Coastguard Worker 
6428*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += sizeof(local_dir_header);
6429*da0073e9SAndroid Build Coastguard Worker 
6430*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6431*da0073e9SAndroid Build Coastguard Worker         {
6432*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6433*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6434*da0073e9SAndroid Build Coastguard Worker         }
6435*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += archive_name_size;
6436*da0073e9SAndroid Build Coastguard Worker     }
6437*da0073e9SAndroid Build Coastguard Worker 
6438*da0073e9SAndroid Build Coastguard Worker 	if (user_extra_data_len > 0)
6439*da0073e9SAndroid Build Coastguard Worker 	{
6440*da0073e9SAndroid Build Coastguard Worker 		if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6441*da0073e9SAndroid Build Coastguard Worker 			return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6442*da0073e9SAndroid Build Coastguard Worker 
6443*da0073e9SAndroid Build Coastguard Worker 		cur_archive_file_ofs += user_extra_data_len;
6444*da0073e9SAndroid Build Coastguard Worker 	}
6445*da0073e9SAndroid Build Coastguard Worker 
6446*da0073e9SAndroid Build Coastguard Worker     if (store_data_uncompressed)
6447*da0073e9SAndroid Build Coastguard Worker     {
6448*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
6449*da0073e9SAndroid Build Coastguard Worker         {
6450*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6451*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6452*da0073e9SAndroid Build Coastguard Worker         }
6453*da0073e9SAndroid Build Coastguard Worker 
6454*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += buf_size;
6455*da0073e9SAndroid Build Coastguard Worker         comp_size = buf_size;
6456*da0073e9SAndroid Build Coastguard Worker     }
6457*da0073e9SAndroid Build Coastguard Worker     else if (buf_size)
6458*da0073e9SAndroid Build Coastguard Worker     {
6459*da0073e9SAndroid Build Coastguard Worker         mz_zip_writer_add_state state;
6460*da0073e9SAndroid Build Coastguard Worker 
6461*da0073e9SAndroid Build Coastguard Worker         state.m_pZip = pZip;
6462*da0073e9SAndroid Build Coastguard Worker         state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6463*da0073e9SAndroid Build Coastguard Worker         state.m_comp_size = 0;
6464*da0073e9SAndroid Build Coastguard Worker 
6465*da0073e9SAndroid Build Coastguard Worker         if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
6466*da0073e9SAndroid Build Coastguard Worker             (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
6467*da0073e9SAndroid Build Coastguard Worker         {
6468*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6469*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6470*da0073e9SAndroid Build Coastguard Worker         }
6471*da0073e9SAndroid Build Coastguard Worker 
6472*da0073e9SAndroid Build Coastguard Worker         comp_size = state.m_comp_size;
6473*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6474*da0073e9SAndroid Build Coastguard Worker     }
6475*da0073e9SAndroid Build Coastguard Worker 
6476*da0073e9SAndroid Build Coastguard Worker     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6477*da0073e9SAndroid Build Coastguard Worker     pComp = NULL;
6478*da0073e9SAndroid Build Coastguard Worker 
6479*da0073e9SAndroid Build Coastguard Worker     if (uncomp_size)
6480*da0073e9SAndroid Build Coastguard Worker     {
6481*da0073e9SAndroid Build Coastguard Worker         mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6482*da0073e9SAndroid Build Coastguard Worker         mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6483*da0073e9SAndroid Build Coastguard Worker 
6484*da0073e9SAndroid Build Coastguard Worker         MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
6485*da0073e9SAndroid Build Coastguard Worker 
6486*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6487*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6488*da0073e9SAndroid Build Coastguard Worker         if (pExtra_data == NULL)
6489*da0073e9SAndroid Build Coastguard Worker         {
6490*da0073e9SAndroid Build Coastguard Worker             if (comp_size > MZ_UINT32_MAX)
6491*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6492*da0073e9SAndroid Build Coastguard Worker 
6493*da0073e9SAndroid Build Coastguard Worker             MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6494*da0073e9SAndroid Build Coastguard Worker             MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6495*da0073e9SAndroid Build Coastguard Worker         }
6496*da0073e9SAndroid Build Coastguard Worker         else
6497*da0073e9SAndroid Build Coastguard Worker         {
6498*da0073e9SAndroid Build Coastguard Worker             MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6499*da0073e9SAndroid Build Coastguard Worker             MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6500*da0073e9SAndroid Build Coastguard Worker             local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6501*da0073e9SAndroid Build Coastguard Worker         }
6502*da0073e9SAndroid Build Coastguard Worker 
6503*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6504*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
6505*da0073e9SAndroid Build Coastguard Worker 
6506*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += local_dir_footer_size;
6507*da0073e9SAndroid Build Coastguard Worker     }
6508*da0073e9SAndroid Build Coastguard Worker 
6509*da0073e9SAndroid Build Coastguard Worker     if (pExtra_data != NULL)
6510*da0073e9SAndroid Build Coastguard Worker     {
6511*da0073e9SAndroid Build Coastguard Worker         extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6512*da0073e9SAndroid Build Coastguard Worker                                                            (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6513*da0073e9SAndroid Build Coastguard Worker     }
6514*da0073e9SAndroid Build Coastguard Worker 
6515*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment,
6516*da0073e9SAndroid Build Coastguard Worker                                           comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6517*da0073e9SAndroid Build Coastguard Worker                                           user_extra_data_central, user_extra_data_central_len))
6518*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
6519*da0073e9SAndroid Build Coastguard Worker 
6520*da0073e9SAndroid Build Coastguard Worker     pZip->m_total_files++;
6521*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = cur_archive_file_ofs;
6522*da0073e9SAndroid Build Coastguard Worker 
6523*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6524*da0073e9SAndroid Build Coastguard Worker }
6525*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_add_read_buf_callback(mz_zip_archive * pZip,const char * pArchive_name,mz_file_read_func read_callback,void * callback_opaque,mz_uint64 size_to_add,const MZ_TIME_T * pFile_time,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,const char * user_extra_data,mz_uint user_extra_data_len,const char * user_extra_data_central,mz_uint user_extra_data_central_len)6526*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6527*da0073e9SAndroid Build Coastguard Worker                                 const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6528*da0073e9SAndroid Build Coastguard Worker {
6529*da0073e9SAndroid Build Coastguard Worker     mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6530*da0073e9SAndroid Build Coastguard Worker     mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6531*da0073e9SAndroid Build Coastguard Worker     mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6532*da0073e9SAndroid Build Coastguard Worker     mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
6533*da0073e9SAndroid Build Coastguard Worker     size_t archive_name_size;
6534*da0073e9SAndroid Build Coastguard Worker     mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6535*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pExtra_data = NULL;
6536*da0073e9SAndroid Build Coastguard Worker     mz_uint32 extra_size = 0;
6537*da0073e9SAndroid Build Coastguard Worker     mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6538*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState;
6539*da0073e9SAndroid Build Coastguard Worker 	mz_uint64 file_ofs = 0;
6540*da0073e9SAndroid Build Coastguard Worker 
6541*da0073e9SAndroid Build Coastguard Worker     if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6542*da0073e9SAndroid Build Coastguard Worker         gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6543*da0073e9SAndroid Build Coastguard Worker 
6544*da0073e9SAndroid Build Coastguard Worker     if ((int)level_and_flags < 0)
6545*da0073e9SAndroid Build Coastguard Worker         level_and_flags = MZ_DEFAULT_LEVEL;
6546*da0073e9SAndroid Build Coastguard Worker     level = level_and_flags & 0xF;
6547*da0073e9SAndroid Build Coastguard Worker 
6548*da0073e9SAndroid Build Coastguard Worker     /* Sanity checks */
6549*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6550*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6551*da0073e9SAndroid Build Coastguard Worker 
6552*da0073e9SAndroid Build Coastguard Worker     pState = pZip->m_pState;
6553*da0073e9SAndroid Build Coastguard Worker 
6554*da0073e9SAndroid Build Coastguard Worker     if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))
6555*da0073e9SAndroid Build Coastguard Worker     {
6556*da0073e9SAndroid Build Coastguard Worker         /* Source file is too large for non-zip64 */
6557*da0073e9SAndroid Build Coastguard Worker         /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6558*da0073e9SAndroid Build Coastguard Worker         pState->m_zip64 = MZ_TRUE;
6559*da0073e9SAndroid Build Coastguard Worker     }
6560*da0073e9SAndroid Build Coastguard Worker 
6561*da0073e9SAndroid Build Coastguard Worker     /* We could support this, but why? */
6562*da0073e9SAndroid Build Coastguard Worker     if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6563*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6564*da0073e9SAndroid Build Coastguard Worker 
6565*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_validate_archive_name(pArchive_name))
6566*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6567*da0073e9SAndroid Build Coastguard Worker 
6568*da0073e9SAndroid Build Coastguard Worker     if (pState->m_zip64)
6569*da0073e9SAndroid Build Coastguard Worker     {
6570*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files == MZ_UINT32_MAX)
6571*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6572*da0073e9SAndroid Build Coastguard Worker     }
6573*da0073e9SAndroid Build Coastguard Worker     else
6574*da0073e9SAndroid Build Coastguard Worker     {
6575*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files == MZ_UINT16_MAX)
6576*da0073e9SAndroid Build Coastguard Worker         {
6577*da0073e9SAndroid Build Coastguard Worker             pState->m_zip64 = MZ_TRUE;
6578*da0073e9SAndroid Build Coastguard Worker             /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6579*da0073e9SAndroid Build Coastguard Worker         }
6580*da0073e9SAndroid Build Coastguard Worker     }
6581*da0073e9SAndroid Build Coastguard Worker 
6582*da0073e9SAndroid Build Coastguard Worker     archive_name_size = strlen(pArchive_name);
6583*da0073e9SAndroid Build Coastguard Worker     if (archive_name_size > MZ_UINT16_MAX)
6584*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6585*da0073e9SAndroid Build Coastguard Worker 
6586*da0073e9SAndroid Build Coastguard Worker     num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6587*da0073e9SAndroid Build Coastguard Worker 
6588*da0073e9SAndroid Build Coastguard Worker     /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6589*da0073e9SAndroid Build Coastguard Worker     if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
6590*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6591*da0073e9SAndroid Build Coastguard Worker 
6592*da0073e9SAndroid Build Coastguard Worker     if (!pState->m_zip64)
6593*da0073e9SAndroid Build Coastguard Worker     {
6594*da0073e9SAndroid Build Coastguard Worker         /* Bail early if the archive would obviously become too large */
6595*da0073e9SAndroid Build Coastguard Worker         if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
6596*da0073e9SAndroid Build Coastguard Worker 			+ archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024
6597*da0073e9SAndroid Build Coastguard Worker 			+ MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)
6598*da0073e9SAndroid Build Coastguard Worker         {
6599*da0073e9SAndroid Build Coastguard Worker             pState->m_zip64 = MZ_TRUE;
6600*da0073e9SAndroid Build Coastguard Worker             /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6601*da0073e9SAndroid Build Coastguard Worker         }
6602*da0073e9SAndroid Build Coastguard Worker     }
6603*da0073e9SAndroid Build Coastguard Worker 
6604*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_TIME
6605*da0073e9SAndroid Build Coastguard Worker     if (pFile_time)
6606*da0073e9SAndroid Build Coastguard Worker     {
6607*da0073e9SAndroid Build Coastguard Worker         mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6608*da0073e9SAndroid Build Coastguard Worker     }
6609*da0073e9SAndroid Build Coastguard Worker #endif
6610*da0073e9SAndroid Build Coastguard Worker 
6611*da0073e9SAndroid Build Coastguard Worker     if (uncomp_size <= 3)
6612*da0073e9SAndroid Build Coastguard Worker         level = 0;
6613*da0073e9SAndroid Build Coastguard Worker 
6614*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6615*da0073e9SAndroid Build Coastguard Worker     {
6616*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6617*da0073e9SAndroid Build Coastguard Worker     }
6618*da0073e9SAndroid Build Coastguard Worker 
6619*da0073e9SAndroid Build Coastguard Worker     cur_archive_file_ofs += num_alignment_padding_bytes;
6620*da0073e9SAndroid Build Coastguard Worker     local_dir_header_ofs = cur_archive_file_ofs;
6621*da0073e9SAndroid Build Coastguard Worker 
6622*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_file_offset_alignment)
6623*da0073e9SAndroid Build Coastguard Worker     {
6624*da0073e9SAndroid Build Coastguard Worker         MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6625*da0073e9SAndroid Build Coastguard Worker     }
6626*da0073e9SAndroid Build Coastguard Worker 
6627*da0073e9SAndroid Build Coastguard Worker     if (uncomp_size && level)
6628*da0073e9SAndroid Build Coastguard Worker     {
6629*da0073e9SAndroid Build Coastguard Worker         method = MZ_DEFLATED;
6630*da0073e9SAndroid Build Coastguard Worker     }
6631*da0073e9SAndroid Build Coastguard Worker 
6632*da0073e9SAndroid Build Coastguard Worker     MZ_CLEAR_OBJ(local_dir_header);
6633*da0073e9SAndroid Build Coastguard Worker     if (pState->m_zip64)
6634*da0073e9SAndroid Build Coastguard Worker     {
6635*da0073e9SAndroid Build Coastguard Worker         if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6636*da0073e9SAndroid Build Coastguard Worker         {
6637*da0073e9SAndroid Build Coastguard Worker             pExtra_data = extra_data;
6638*da0073e9SAndroid Build Coastguard Worker             extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6639*da0073e9SAndroid Build Coastguard Worker                                                                (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6640*da0073e9SAndroid Build Coastguard Worker         }
6641*da0073e9SAndroid Build Coastguard Worker 
6642*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date))
6643*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6644*da0073e9SAndroid Build Coastguard Worker 
6645*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6646*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6647*da0073e9SAndroid Build Coastguard Worker 
6648*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += sizeof(local_dir_header);
6649*da0073e9SAndroid Build Coastguard Worker 
6650*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6651*da0073e9SAndroid Build Coastguard Worker         {
6652*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6653*da0073e9SAndroid Build Coastguard Worker         }
6654*da0073e9SAndroid Build Coastguard Worker 
6655*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += archive_name_size;
6656*da0073e9SAndroid Build Coastguard Worker 
6657*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6658*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6659*da0073e9SAndroid Build Coastguard Worker 
6660*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += extra_size;
6661*da0073e9SAndroid Build Coastguard Worker     }
6662*da0073e9SAndroid Build Coastguard Worker     else
6663*da0073e9SAndroid Build Coastguard Worker     {
6664*da0073e9SAndroid Build Coastguard Worker         if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6665*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6666*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
6667*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6668*da0073e9SAndroid Build Coastguard Worker 
6669*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6670*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6671*da0073e9SAndroid Build Coastguard Worker 
6672*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += sizeof(local_dir_header);
6673*da0073e9SAndroid Build Coastguard Worker 
6674*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6675*da0073e9SAndroid Build Coastguard Worker         {
6676*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6677*da0073e9SAndroid Build Coastguard Worker         }
6678*da0073e9SAndroid Build Coastguard Worker 
6679*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += archive_name_size;
6680*da0073e9SAndroid Build Coastguard Worker     }
6681*da0073e9SAndroid Build Coastguard Worker 
6682*da0073e9SAndroid Build Coastguard Worker     if (user_extra_data_len > 0)
6683*da0073e9SAndroid Build Coastguard Worker     {
6684*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6685*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6686*da0073e9SAndroid Build Coastguard Worker 
6687*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += user_extra_data_len;
6688*da0073e9SAndroid Build Coastguard Worker     }
6689*da0073e9SAndroid Build Coastguard Worker 
6690*da0073e9SAndroid Build Coastguard Worker     if (uncomp_size)
6691*da0073e9SAndroid Build Coastguard Worker     {
6692*da0073e9SAndroid Build Coastguard Worker         mz_uint64 uncomp_remaining = uncomp_size;
6693*da0073e9SAndroid Build Coastguard Worker         void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6694*da0073e9SAndroid Build Coastguard Worker         if (!pRead_buf)
6695*da0073e9SAndroid Build Coastguard Worker         {
6696*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6697*da0073e9SAndroid Build Coastguard Worker         }
6698*da0073e9SAndroid Build Coastguard Worker 
6699*da0073e9SAndroid Build Coastguard Worker         if (!level)
6700*da0073e9SAndroid Build Coastguard Worker         {
6701*da0073e9SAndroid Build Coastguard Worker             while (uncomp_remaining)
6702*da0073e9SAndroid Build Coastguard Worker             {
6703*da0073e9SAndroid Build Coastguard Worker                 mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6704*da0073e9SAndroid Build Coastguard Worker                 if ((read_callback(callback_opaque, file_ofs, pRead_buf, n) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
6705*da0073e9SAndroid Build Coastguard Worker                 {
6706*da0073e9SAndroid Build Coastguard Worker                     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6707*da0073e9SAndroid Build Coastguard Worker                     return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6708*da0073e9SAndroid Build Coastguard Worker                 }
6709*da0073e9SAndroid Build Coastguard Worker 				file_ofs += n;
6710*da0073e9SAndroid Build Coastguard Worker                 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6711*da0073e9SAndroid Build Coastguard Worker                 uncomp_remaining -= n;
6712*da0073e9SAndroid Build Coastguard Worker                 cur_archive_file_ofs += n;
6713*da0073e9SAndroid Build Coastguard Worker             }
6714*da0073e9SAndroid Build Coastguard Worker             comp_size = uncomp_size;
6715*da0073e9SAndroid Build Coastguard Worker         }
6716*da0073e9SAndroid Build Coastguard Worker         else
6717*da0073e9SAndroid Build Coastguard Worker         {
6718*da0073e9SAndroid Build Coastguard Worker             mz_bool result = MZ_FALSE;
6719*da0073e9SAndroid Build Coastguard Worker             mz_zip_writer_add_state state;
6720*da0073e9SAndroid Build Coastguard Worker             tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6721*da0073e9SAndroid Build Coastguard Worker             if (!pComp)
6722*da0073e9SAndroid Build Coastguard Worker             {
6723*da0073e9SAndroid Build Coastguard Worker                 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6724*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6725*da0073e9SAndroid Build Coastguard Worker             }
6726*da0073e9SAndroid Build Coastguard Worker 
6727*da0073e9SAndroid Build Coastguard Worker             state.m_pZip = pZip;
6728*da0073e9SAndroid Build Coastguard Worker             state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6729*da0073e9SAndroid Build Coastguard Worker             state.m_comp_size = 0;
6730*da0073e9SAndroid Build Coastguard Worker 
6731*da0073e9SAndroid Build Coastguard Worker             if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
6732*da0073e9SAndroid Build Coastguard Worker             {
6733*da0073e9SAndroid Build Coastguard Worker                 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6734*da0073e9SAndroid Build Coastguard Worker                 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6735*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6736*da0073e9SAndroid Build Coastguard Worker             }
6737*da0073e9SAndroid Build Coastguard Worker 
6738*da0073e9SAndroid Build Coastguard Worker             for (;;)
6739*da0073e9SAndroid Build Coastguard Worker             {
6740*da0073e9SAndroid Build Coastguard Worker                 size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6741*da0073e9SAndroid Build Coastguard Worker                 tdefl_status status;
6742*da0073e9SAndroid Build Coastguard Worker                 tdefl_flush flush = TDEFL_NO_FLUSH;
6743*da0073e9SAndroid Build Coastguard Worker 
6744*da0073e9SAndroid Build Coastguard Worker                 if (read_callback(callback_opaque, file_ofs, pRead_buf, in_buf_size)!= in_buf_size)
6745*da0073e9SAndroid Build Coastguard Worker                 {
6746*da0073e9SAndroid Build Coastguard Worker                     mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6747*da0073e9SAndroid Build Coastguard Worker                     break;
6748*da0073e9SAndroid Build Coastguard Worker                 }
6749*da0073e9SAndroid Build Coastguard Worker 
6750*da0073e9SAndroid Build Coastguard Worker 				file_ofs += in_buf_size;
6751*da0073e9SAndroid Build Coastguard Worker                 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6752*da0073e9SAndroid Build Coastguard Worker                 uncomp_remaining -= in_buf_size;
6753*da0073e9SAndroid Build Coastguard Worker 
6754*da0073e9SAndroid Build Coastguard Worker                 if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6755*da0073e9SAndroid Build Coastguard Worker                     flush = TDEFL_FULL_FLUSH;
6756*da0073e9SAndroid Build Coastguard Worker 
6757*da0073e9SAndroid Build Coastguard Worker                 status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
6758*da0073e9SAndroid Build Coastguard Worker                 if (status == TDEFL_STATUS_DONE)
6759*da0073e9SAndroid Build Coastguard Worker                 {
6760*da0073e9SAndroid Build Coastguard Worker                     result = MZ_TRUE;
6761*da0073e9SAndroid Build Coastguard Worker                     break;
6762*da0073e9SAndroid Build Coastguard Worker                 }
6763*da0073e9SAndroid Build Coastguard Worker                 else if (status != TDEFL_STATUS_OKAY)
6764*da0073e9SAndroid Build Coastguard Worker                 {
6765*da0073e9SAndroid Build Coastguard Worker                     mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6766*da0073e9SAndroid Build Coastguard Worker                     break;
6767*da0073e9SAndroid Build Coastguard Worker                 }
6768*da0073e9SAndroid Build Coastguard Worker             }
6769*da0073e9SAndroid Build Coastguard Worker 
6770*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6771*da0073e9SAndroid Build Coastguard Worker 
6772*da0073e9SAndroid Build Coastguard Worker             if (!result)
6773*da0073e9SAndroid Build Coastguard Worker             {
6774*da0073e9SAndroid Build Coastguard Worker                 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6775*da0073e9SAndroid Build Coastguard Worker                 return MZ_FALSE;
6776*da0073e9SAndroid Build Coastguard Worker             }
6777*da0073e9SAndroid Build Coastguard Worker 
6778*da0073e9SAndroid Build Coastguard Worker             comp_size = state.m_comp_size;
6779*da0073e9SAndroid Build Coastguard Worker             cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6780*da0073e9SAndroid Build Coastguard Worker         }
6781*da0073e9SAndroid Build Coastguard Worker 
6782*da0073e9SAndroid Build Coastguard Worker         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6783*da0073e9SAndroid Build Coastguard Worker     }
6784*da0073e9SAndroid Build Coastguard Worker 
6785*da0073e9SAndroid Build Coastguard Worker     {
6786*da0073e9SAndroid Build Coastguard Worker         mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6787*da0073e9SAndroid Build Coastguard Worker         mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6788*da0073e9SAndroid Build Coastguard Worker 
6789*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6790*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6791*da0073e9SAndroid Build Coastguard Worker         if (pExtra_data == NULL)
6792*da0073e9SAndroid Build Coastguard Worker         {
6793*da0073e9SAndroid Build Coastguard Worker             if (comp_size > MZ_UINT32_MAX)
6794*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6795*da0073e9SAndroid Build Coastguard Worker 
6796*da0073e9SAndroid Build Coastguard Worker             MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6797*da0073e9SAndroid Build Coastguard Worker             MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6798*da0073e9SAndroid Build Coastguard Worker         }
6799*da0073e9SAndroid Build Coastguard Worker         else
6800*da0073e9SAndroid Build Coastguard Worker         {
6801*da0073e9SAndroid Build Coastguard Worker             MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6802*da0073e9SAndroid Build Coastguard Worker             MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6803*da0073e9SAndroid Build Coastguard Worker             local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6804*da0073e9SAndroid Build Coastguard Worker         }
6805*da0073e9SAndroid Build Coastguard Worker 
6806*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6807*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
6808*da0073e9SAndroid Build Coastguard Worker 
6809*da0073e9SAndroid Build Coastguard Worker         cur_archive_file_ofs += local_dir_footer_size;
6810*da0073e9SAndroid Build Coastguard Worker     }
6811*da0073e9SAndroid Build Coastguard Worker 
6812*da0073e9SAndroid Build Coastguard Worker     if (pExtra_data != NULL)
6813*da0073e9SAndroid Build Coastguard Worker     {
6814*da0073e9SAndroid Build Coastguard Worker         extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6815*da0073e9SAndroid Build Coastguard Worker                                                            (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6816*da0073e9SAndroid Build Coastguard Worker     }
6817*da0073e9SAndroid Build Coastguard Worker 
6818*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, comment_size,
6819*da0073e9SAndroid Build Coastguard Worker                                           uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6820*da0073e9SAndroid Build Coastguard Worker                                           user_extra_data_central, user_extra_data_central_len))
6821*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
6822*da0073e9SAndroid Build Coastguard Worker 
6823*da0073e9SAndroid Build Coastguard Worker     pZip->m_total_files++;
6824*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = cur_archive_file_ofs;
6825*da0073e9SAndroid Build Coastguard Worker 
6826*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6827*da0073e9SAndroid Build Coastguard Worker }
6828*da0073e9SAndroid Build Coastguard Worker 
6829*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
6830*da0073e9SAndroid Build Coastguard Worker 
mz_file_read_func_stdio(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)6831*da0073e9SAndroid Build Coastguard Worker static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
6832*da0073e9SAndroid Build Coastguard Worker {
6833*da0073e9SAndroid Build Coastguard Worker 	MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
6834*da0073e9SAndroid Build Coastguard Worker 	mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
6835*da0073e9SAndroid Build Coastguard Worker 
6836*da0073e9SAndroid Build Coastguard Worker 	if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
6837*da0073e9SAndroid Build Coastguard Worker 		return 0;
6838*da0073e9SAndroid Build Coastguard Worker 
6839*da0073e9SAndroid Build Coastguard Worker 	return MZ_FREAD(pBuf, 1, n, pSrc_file);
6840*da0073e9SAndroid Build Coastguard Worker }
6841*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_add_cfile(mz_zip_archive * pZip,const char * pArchive_name,MZ_FILE * pSrc_file,mz_uint64 size_to_add,const MZ_TIME_T * pFile_time,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,const char * user_extra_data,mz_uint user_extra_data_len,const char * user_extra_data_central,mz_uint user_extra_data_central_len)6842*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6843*da0073e9SAndroid Build Coastguard Worker 	const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6844*da0073e9SAndroid Build Coastguard Worker {
6845*da0073e9SAndroid Build Coastguard Worker 	return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, size_to_add, pFile_time, pComment, comment_size, level_and_flags,
6846*da0073e9SAndroid Build Coastguard Worker 		user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len);
6847*da0073e9SAndroid Build Coastguard Worker }
6848*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_add_file(mz_zip_archive * pZip,const char * pArchive_name,const char * pSrc_filename,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags)6849*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
6850*da0073e9SAndroid Build Coastguard Worker {
6851*da0073e9SAndroid Build Coastguard Worker     MZ_FILE *pSrc_file = NULL;
6852*da0073e9SAndroid Build Coastguard Worker     mz_uint64 uncomp_size = 0;
6853*da0073e9SAndroid Build Coastguard Worker     MZ_TIME_T file_modified_time;
6854*da0073e9SAndroid Build Coastguard Worker     MZ_TIME_T *pFile_time = NULL;
6855*da0073e9SAndroid Build Coastguard Worker     mz_bool status;
6856*da0073e9SAndroid Build Coastguard Worker 
6857*da0073e9SAndroid Build Coastguard Worker     memset(&file_modified_time, 0, sizeof(file_modified_time));
6858*da0073e9SAndroid Build Coastguard Worker 
6859*da0073e9SAndroid Build Coastguard Worker #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6860*da0073e9SAndroid Build Coastguard Worker     pFile_time = &file_modified_time;
6861*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6862*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
6863*da0073e9SAndroid Build Coastguard Worker #endif
6864*da0073e9SAndroid Build Coastguard Worker 
6865*da0073e9SAndroid Build Coastguard Worker     pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6866*da0073e9SAndroid Build Coastguard Worker     if (!pSrc_file)
6867*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6868*da0073e9SAndroid Build Coastguard Worker 
6869*da0073e9SAndroid Build Coastguard Worker     MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6870*da0073e9SAndroid Build Coastguard Worker     uncomp_size = MZ_FTELL64(pSrc_file);
6871*da0073e9SAndroid Build Coastguard Worker     MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6872*da0073e9SAndroid Build Coastguard Worker 
6873*da0073e9SAndroid Build Coastguard Worker     status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0);
6874*da0073e9SAndroid Build Coastguard Worker 
6875*da0073e9SAndroid Build Coastguard Worker     MZ_FCLOSE(pSrc_file);
6876*da0073e9SAndroid Build Coastguard Worker 
6877*da0073e9SAndroid Build Coastguard Worker     return status;
6878*da0073e9SAndroid Build Coastguard Worker }
6879*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
6880*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_update_zip64_extension_block(mz_zip_array * pNew_ext,mz_zip_archive * pZip,const mz_uint8 * pExt,uint32_t ext_len,mz_uint64 * pComp_size,mz_uint64 * pUncomp_size,mz_uint64 * pLocal_header_ofs,mz_uint32 * pDisk_start)6881*da0073e9SAndroid Build Coastguard Worker static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)
6882*da0073e9SAndroid Build Coastguard Worker {
6883*da0073e9SAndroid Build Coastguard Worker     /* + 64 should be enough for any new zip64 data */
6884*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6885*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6886*da0073e9SAndroid Build Coastguard Worker 
6887*da0073e9SAndroid Build Coastguard Worker     mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6888*da0073e9SAndroid Build Coastguard Worker 
6889*da0073e9SAndroid Build Coastguard Worker     if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6890*da0073e9SAndroid Build Coastguard Worker     {
6891*da0073e9SAndroid Build Coastguard Worker         mz_uint8 new_ext_block[64];
6892*da0073e9SAndroid Build Coastguard Worker         mz_uint8 *pDst = new_ext_block;
6893*da0073e9SAndroid Build Coastguard Worker         mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6894*da0073e9SAndroid Build Coastguard Worker         mz_write_le16(pDst + sizeof(mz_uint16), 0);
6895*da0073e9SAndroid Build Coastguard Worker         pDst += sizeof(mz_uint16) * 2;
6896*da0073e9SAndroid Build Coastguard Worker 
6897*da0073e9SAndroid Build Coastguard Worker         if (pUncomp_size)
6898*da0073e9SAndroid Build Coastguard Worker         {
6899*da0073e9SAndroid Build Coastguard Worker             mz_write_le64(pDst, *pUncomp_size);
6900*da0073e9SAndroid Build Coastguard Worker             pDst += sizeof(mz_uint64);
6901*da0073e9SAndroid Build Coastguard Worker         }
6902*da0073e9SAndroid Build Coastguard Worker 
6903*da0073e9SAndroid Build Coastguard Worker         if (pComp_size)
6904*da0073e9SAndroid Build Coastguard Worker         {
6905*da0073e9SAndroid Build Coastguard Worker             mz_write_le64(pDst, *pComp_size);
6906*da0073e9SAndroid Build Coastguard Worker             pDst += sizeof(mz_uint64);
6907*da0073e9SAndroid Build Coastguard Worker         }
6908*da0073e9SAndroid Build Coastguard Worker 
6909*da0073e9SAndroid Build Coastguard Worker         if (pLocal_header_ofs)
6910*da0073e9SAndroid Build Coastguard Worker         {
6911*da0073e9SAndroid Build Coastguard Worker             mz_write_le64(pDst, *pLocal_header_ofs);
6912*da0073e9SAndroid Build Coastguard Worker             pDst += sizeof(mz_uint64);
6913*da0073e9SAndroid Build Coastguard Worker         }
6914*da0073e9SAndroid Build Coastguard Worker 
6915*da0073e9SAndroid Build Coastguard Worker         if (pDisk_start)
6916*da0073e9SAndroid Build Coastguard Worker         {
6917*da0073e9SAndroid Build Coastguard Worker             mz_write_le32(pDst, *pDisk_start);
6918*da0073e9SAndroid Build Coastguard Worker             pDst += sizeof(mz_uint32);
6919*da0073e9SAndroid Build Coastguard Worker         }
6920*da0073e9SAndroid Build Coastguard Worker 
6921*da0073e9SAndroid Build Coastguard Worker         mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
6922*da0073e9SAndroid Build Coastguard Worker 
6923*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
6924*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6925*da0073e9SAndroid Build Coastguard Worker     }
6926*da0073e9SAndroid Build Coastguard Worker 
6927*da0073e9SAndroid Build Coastguard Worker     if ((pExt) && (ext_len))
6928*da0073e9SAndroid Build Coastguard Worker     {
6929*da0073e9SAndroid Build Coastguard Worker         mz_uint32 extra_size_remaining = ext_len;
6930*da0073e9SAndroid Build Coastguard Worker         const mz_uint8 *pExtra_data = pExt;
6931*da0073e9SAndroid Build Coastguard Worker 
6932*da0073e9SAndroid Build Coastguard Worker         do
6933*da0073e9SAndroid Build Coastguard Worker         {
6934*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6935*da0073e9SAndroid Build Coastguard Worker             mz_uint32 field_id, field_data_size, field_total_size;
6936*da0073e9SAndroid Build Coastguard Worker 
6937*da0073e9SAndroid Build Coastguard Worker             if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6938*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6939*da0073e9SAndroid Build Coastguard Worker 
6940*da0073e9SAndroid Build Coastguard Worker             field_id = MZ_READ_LE16(pExtra_data);
6941*da0073e9SAndroid Build Coastguard Worker             field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6942*da0073e9SAndroid Build Coastguard Worker             field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6943*da0073e9SAndroid Build Coastguard Worker 
6944*da0073e9SAndroid Build Coastguard Worker             if (field_total_size > extra_size_remaining)
6945*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6946*da0073e9SAndroid Build Coastguard Worker 
6947*da0073e9SAndroid Build Coastguard Worker             if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6948*da0073e9SAndroid Build Coastguard Worker             {
6949*da0073e9SAndroid Build Coastguard Worker                 if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
6950*da0073e9SAndroid Build Coastguard Worker                     return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6951*da0073e9SAndroid Build Coastguard Worker             }
6952*da0073e9SAndroid Build Coastguard Worker 
6953*da0073e9SAndroid Build Coastguard Worker             pExtra_data += field_total_size;
6954*da0073e9SAndroid Build Coastguard Worker             extra_size_remaining -= field_total_size;
6955*da0073e9SAndroid Build Coastguard Worker         } while (extra_size_remaining);
6956*da0073e9SAndroid Build Coastguard Worker     }
6957*da0073e9SAndroid Build Coastguard Worker 
6958*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
6959*da0073e9SAndroid Build Coastguard Worker }
6960*da0073e9SAndroid Build Coastguard Worker 
6961*da0073e9SAndroid Build Coastguard Worker /* TODO: This func is now pretty freakin complex due to zip64, split it up? */
mz_zip_writer_add_from_zip_reader(mz_zip_archive * pZip,mz_zip_archive * pSource_zip,mz_uint src_file_index)6962*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)
6963*da0073e9SAndroid Build Coastguard Worker {
6964*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6965*da0073e9SAndroid Build Coastguard Worker     mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
6966*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6967*da0073e9SAndroid Build Coastguard Worker     mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
6968*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6969*da0073e9SAndroid Build Coastguard Worker     mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6970*da0073e9SAndroid Build Coastguard Worker     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
6971*da0073e9SAndroid Build Coastguard Worker     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6972*da0073e9SAndroid Build Coastguard Worker     mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6973*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6974*da0073e9SAndroid Build Coastguard Worker     size_t orig_central_dir_size;
6975*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6976*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState;
6977*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6978*da0073e9SAndroid Build Coastguard Worker     void *pBuf;
6979*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6980*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *pSrc_central_header;
6981*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive_file_stat src_file_stat;
6982*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6983*da0073e9SAndroid Build Coastguard Worker     mz_uint32 src_filename_len, src_comment_len, src_ext_len;
6984*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6985*da0073e9SAndroid Build Coastguard Worker     mz_uint32 local_header_filename_size, local_header_extra_len;
6986*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6987*da0073e9SAndroid Build Coastguard Worker     mz_uint64 local_header_comp_size, local_header_uncomp_size;
6988*da0073e9SAndroid Build Coastguard Worker     mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
6989*da0073e9SAndroid Build Coastguard Worker 
6990*da0073e9SAndroid Build Coastguard Worker     /* Sanity checks */
6991*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
6992*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6993*da0073e9SAndroid Build Coastguard Worker 
6994*da0073e9SAndroid Build Coastguard Worker     pState = pZip->m_pState;
6995*da0073e9SAndroid Build Coastguard Worker 
6996*da0073e9SAndroid Build Coastguard Worker     /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */
6997*da0073e9SAndroid Build Coastguard Worker     if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
6998*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6999*da0073e9SAndroid Build Coastguard Worker 
7000*da0073e9SAndroid Build Coastguard Worker     /* Get pointer to the source central dir header and crack it */
7001*da0073e9SAndroid Build Coastguard Worker     if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
7002*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7003*da0073e9SAndroid Build Coastguard Worker 
7004*da0073e9SAndroid Build Coastguard Worker     if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
7005*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7006*da0073e9SAndroid Build Coastguard Worker 
7007*da0073e9SAndroid Build Coastguard Worker     src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7008*da0073e9SAndroid Build Coastguard Worker     src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
7009*da0073e9SAndroid Build Coastguard Worker     src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
7010*da0073e9SAndroid Build Coastguard Worker     src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
7011*da0073e9SAndroid Build Coastguard Worker 
7012*da0073e9SAndroid Build Coastguard Worker     /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */
7013*da0073e9SAndroid Build Coastguard Worker     if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
7014*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7015*da0073e9SAndroid Build Coastguard Worker 
7016*da0073e9SAndroid Build Coastguard Worker     num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
7017*da0073e9SAndroid Build Coastguard Worker 
7018*da0073e9SAndroid Build Coastguard Worker     if (!pState->m_zip64)
7019*da0073e9SAndroid Build Coastguard Worker     {
7020*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files == MZ_UINT16_MAX)
7021*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7022*da0073e9SAndroid Build Coastguard Worker     }
7023*da0073e9SAndroid Build Coastguard Worker     else
7024*da0073e9SAndroid Build Coastguard Worker     {
7025*da0073e9SAndroid Build Coastguard Worker         /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
7026*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_total_files == MZ_UINT32_MAX)
7027*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7028*da0073e9SAndroid Build Coastguard Worker     }
7029*da0073e9SAndroid Build Coastguard Worker 
7030*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
7031*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
7032*da0073e9SAndroid Build Coastguard Worker 
7033*da0073e9SAndroid Build Coastguard Worker     cur_src_file_ofs = src_file_stat.m_local_header_ofs;
7034*da0073e9SAndroid Build Coastguard Worker     cur_dst_file_ofs = pZip->m_archive_size;
7035*da0073e9SAndroid Build Coastguard Worker 
7036*da0073e9SAndroid Build Coastguard Worker     /* Read the source archive's local dir header */
7037*da0073e9SAndroid Build Coastguard Worker     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
7038*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7039*da0073e9SAndroid Build Coastguard Worker 
7040*da0073e9SAndroid Build Coastguard Worker     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
7041*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7042*da0073e9SAndroid Build Coastguard Worker 
7043*da0073e9SAndroid Build Coastguard Worker     cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
7044*da0073e9SAndroid Build Coastguard Worker 
7045*da0073e9SAndroid Build Coastguard Worker     /* Compute the total size we need to copy (filename+extra data+compressed data) */
7046*da0073e9SAndroid Build Coastguard Worker     local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
7047*da0073e9SAndroid Build Coastguard Worker     local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
7048*da0073e9SAndroid Build Coastguard Worker     local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
7049*da0073e9SAndroid Build Coastguard Worker     local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
7050*da0073e9SAndroid Build Coastguard Worker     src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;
7051*da0073e9SAndroid Build Coastguard Worker 
7052*da0073e9SAndroid Build Coastguard Worker     /* Try to find a zip64 extended information field */
7053*da0073e9SAndroid Build Coastguard Worker     if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
7054*da0073e9SAndroid Build Coastguard Worker     {
7055*da0073e9SAndroid Build Coastguard Worker         mz_zip_array file_data_array;
7056*da0073e9SAndroid Build Coastguard Worker         const mz_uint8 *pExtra_data;
7057*da0073e9SAndroid Build Coastguard Worker         mz_uint32 extra_size_remaining = local_header_extra_len;
7058*da0073e9SAndroid Build Coastguard Worker 
7059*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_init(&file_data_array, 1);
7060*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
7061*da0073e9SAndroid Build Coastguard Worker         {
7062*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7063*da0073e9SAndroid Build Coastguard Worker         }
7064*da0073e9SAndroid Build Coastguard Worker 
7065*da0073e9SAndroid Build Coastguard Worker         if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
7066*da0073e9SAndroid Build Coastguard Worker         {
7067*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_clear(pZip, &file_data_array);
7068*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7069*da0073e9SAndroid Build Coastguard Worker         }
7070*da0073e9SAndroid Build Coastguard Worker 
7071*da0073e9SAndroid Build Coastguard Worker         pExtra_data = (const mz_uint8 *)file_data_array.m_p;
7072*da0073e9SAndroid Build Coastguard Worker 
7073*da0073e9SAndroid Build Coastguard Worker         do
7074*da0073e9SAndroid Build Coastguard Worker         {
7075*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7076*da0073e9SAndroid Build Coastguard Worker             mz_uint32 field_id, field_data_size, field_total_size;
7077*da0073e9SAndroid Build Coastguard Worker 
7078*da0073e9SAndroid Build Coastguard Worker             if (extra_size_remaining < (sizeof(mz_uint16) * 2))
7079*da0073e9SAndroid Build Coastguard Worker             {
7080*da0073e9SAndroid Build Coastguard Worker                 mz_zip_array_clear(pZip, &file_data_array);
7081*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7082*da0073e9SAndroid Build Coastguard Worker             }
7083*da0073e9SAndroid Build Coastguard Worker 
7084*da0073e9SAndroid Build Coastguard Worker             field_id = MZ_READ_LE16(pExtra_data);
7085*da0073e9SAndroid Build Coastguard Worker             field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
7086*da0073e9SAndroid Build Coastguard Worker             field_total_size = field_data_size + sizeof(mz_uint16) * 2;
7087*da0073e9SAndroid Build Coastguard Worker 
7088*da0073e9SAndroid Build Coastguard Worker             if (field_total_size > extra_size_remaining)
7089*da0073e9SAndroid Build Coastguard Worker             {
7090*da0073e9SAndroid Build Coastguard Worker                 mz_zip_array_clear(pZip, &file_data_array);
7091*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7092*da0073e9SAndroid Build Coastguard Worker             }
7093*da0073e9SAndroid Build Coastguard Worker 
7094*da0073e9SAndroid Build Coastguard Worker             if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
7095*da0073e9SAndroid Build Coastguard Worker             {
7096*da0073e9SAndroid Build Coastguard Worker                 const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
7097*da0073e9SAndroid Build Coastguard Worker 
7098*da0073e9SAndroid Build Coastguard Worker                 if (field_data_size < sizeof(mz_uint64) * 2)
7099*da0073e9SAndroid Build Coastguard Worker                 {
7100*da0073e9SAndroid Build Coastguard Worker                     mz_zip_array_clear(pZip, &file_data_array);
7101*da0073e9SAndroid Build Coastguard Worker                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7102*da0073e9SAndroid Build Coastguard Worker                 }
7103*da0073e9SAndroid Build Coastguard Worker 
7104*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
7105*da0073e9SAndroid Build Coastguard Worker                 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
7106*da0073e9SAndroid Build Coastguard Worker                 // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
7107*da0073e9SAndroid Build Coastguard Worker                 local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
7108*da0073e9SAndroid Build Coastguard Worker 
7109*da0073e9SAndroid Build Coastguard Worker                 found_zip64_ext_data_in_ldir = MZ_TRUE;
7110*da0073e9SAndroid Build Coastguard Worker                 break;
7111*da0073e9SAndroid Build Coastguard Worker             }
7112*da0073e9SAndroid Build Coastguard Worker 
7113*da0073e9SAndroid Build Coastguard Worker             pExtra_data += field_total_size;
7114*da0073e9SAndroid Build Coastguard Worker             extra_size_remaining -= field_total_size;
7115*da0073e9SAndroid Build Coastguard Worker         } while (extra_size_remaining);
7116*da0073e9SAndroid Build Coastguard Worker 
7117*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_clear(pZip, &file_data_array);
7118*da0073e9SAndroid Build Coastguard Worker     }
7119*da0073e9SAndroid Build Coastguard Worker 
7120*da0073e9SAndroid Build Coastguard Worker     if (!pState->m_zip64)
7121*da0073e9SAndroid Build Coastguard Worker     {
7122*da0073e9SAndroid Build Coastguard Worker         /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */
7123*da0073e9SAndroid Build Coastguard Worker         /* We also check when the archive is finalized so this doesn't need to be perfect. */
7124*da0073e9SAndroid Build Coastguard Worker         mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) +
7125*da0073e9SAndroid Build Coastguard Worker                                             pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64;
7126*da0073e9SAndroid Build Coastguard Worker 
7127*da0073e9SAndroid Build Coastguard Worker         if (approx_new_archive_size >= MZ_UINT32_MAX)
7128*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7129*da0073e9SAndroid Build Coastguard Worker     }
7130*da0073e9SAndroid Build Coastguard Worker 
7131*da0073e9SAndroid Build Coastguard Worker     /* Write dest archive padding */
7132*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
7133*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
7134*da0073e9SAndroid Build Coastguard Worker 
7135*da0073e9SAndroid Build Coastguard Worker     cur_dst_file_ofs += num_alignment_padding_bytes;
7136*da0073e9SAndroid Build Coastguard Worker 
7137*da0073e9SAndroid Build Coastguard Worker     local_dir_header_ofs = cur_dst_file_ofs;
7138*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_file_offset_alignment)
7139*da0073e9SAndroid Build Coastguard Worker     {
7140*da0073e9SAndroid Build Coastguard Worker         MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
7141*da0073e9SAndroid Build Coastguard Worker     }
7142*da0073e9SAndroid Build Coastguard Worker 
7143*da0073e9SAndroid Build Coastguard Worker     /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */
7144*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
7145*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7146*da0073e9SAndroid Build Coastguard Worker 
7147*da0073e9SAndroid Build Coastguard Worker     cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
7148*da0073e9SAndroid Build Coastguard Worker 
7149*da0073e9SAndroid Build Coastguard Worker     /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
7150*da0073e9SAndroid Build Coastguard Worker     if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining)))))
7151*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7152*da0073e9SAndroid Build Coastguard Worker 
7153*da0073e9SAndroid Build Coastguard Worker     while (src_archive_bytes_remaining)
7154*da0073e9SAndroid Build Coastguard Worker     {
7155*da0073e9SAndroid Build Coastguard Worker         n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
7156*da0073e9SAndroid Build Coastguard Worker         if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
7157*da0073e9SAndroid Build Coastguard Worker         {
7158*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7159*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7160*da0073e9SAndroid Build Coastguard Worker         }
7161*da0073e9SAndroid Build Coastguard Worker         cur_src_file_ofs += n;
7162*da0073e9SAndroid Build Coastguard Worker 
7163*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7164*da0073e9SAndroid Build Coastguard Worker         {
7165*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7166*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7167*da0073e9SAndroid Build Coastguard Worker         }
7168*da0073e9SAndroid Build Coastguard Worker         cur_dst_file_ofs += n;
7169*da0073e9SAndroid Build Coastguard Worker 
7170*da0073e9SAndroid Build Coastguard Worker         src_archive_bytes_remaining -= n;
7171*da0073e9SAndroid Build Coastguard Worker     }
7172*da0073e9SAndroid Build Coastguard Worker 
7173*da0073e9SAndroid Build Coastguard Worker     /* Now deal with the optional data descriptor */
7174*da0073e9SAndroid Build Coastguard Worker     bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
7175*da0073e9SAndroid Build Coastguard Worker     if (bit_flags & 8)
7176*da0073e9SAndroid Build Coastguard Worker     {
7177*da0073e9SAndroid Build Coastguard Worker         /* Copy data descriptor */
7178*da0073e9SAndroid Build Coastguard Worker         if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
7179*da0073e9SAndroid Build Coastguard Worker         {
7180*da0073e9SAndroid Build Coastguard Worker             /* src is zip64, dest must be zip64 */
7181*da0073e9SAndroid Build Coastguard Worker 
7182*da0073e9SAndroid Build Coastguard Worker             /* name			uint32_t's */
7183*da0073e9SAndroid Build Coastguard Worker             /* id				1 (optional in zip64?) */
7184*da0073e9SAndroid Build Coastguard Worker             /* crc			1 */
7185*da0073e9SAndroid Build Coastguard Worker             /* comp_size	2 */
7186*da0073e9SAndroid Build Coastguard Worker             /* uncomp_size 2 */
7187*da0073e9SAndroid Build Coastguard Worker             if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
7188*da0073e9SAndroid Build Coastguard Worker             {
7189*da0073e9SAndroid Build Coastguard Worker                 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7190*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7191*da0073e9SAndroid Build Coastguard Worker             }
7192*da0073e9SAndroid Build Coastguard Worker 
7193*da0073e9SAndroid Build Coastguard Worker             n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
7194*da0073e9SAndroid Build Coastguard Worker         }
7195*da0073e9SAndroid Build Coastguard Worker         else
7196*da0073e9SAndroid Build Coastguard Worker         {
7197*da0073e9SAndroid Build Coastguard Worker             /* src is NOT zip64 */
7198*da0073e9SAndroid Build Coastguard Worker             // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7199*da0073e9SAndroid Build Coastguard Worker             mz_bool has_id;
7200*da0073e9SAndroid Build Coastguard Worker 
7201*da0073e9SAndroid Build Coastguard Worker             if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
7202*da0073e9SAndroid Build Coastguard Worker             {
7203*da0073e9SAndroid Build Coastguard Worker                 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7204*da0073e9SAndroid Build Coastguard Worker                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7205*da0073e9SAndroid Build Coastguard Worker             }
7206*da0073e9SAndroid Build Coastguard Worker 
7207*da0073e9SAndroid Build Coastguard Worker             has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
7208*da0073e9SAndroid Build Coastguard Worker 
7209*da0073e9SAndroid Build Coastguard Worker             if (pZip->m_pState->m_zip64)
7210*da0073e9SAndroid Build Coastguard Worker             {
7211*da0073e9SAndroid Build Coastguard Worker                 /* dest is zip64, so upgrade the data descriptor */
7212*da0073e9SAndroid Build Coastguard Worker                 const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0));
7213*da0073e9SAndroid Build Coastguard Worker                 const mz_uint32 src_crc32 = pSrc_descriptor[0];
7214*da0073e9SAndroid Build Coastguard Worker                 const mz_uint64 src_comp_size = pSrc_descriptor[1];
7215*da0073e9SAndroid Build Coastguard Worker                 const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
7216*da0073e9SAndroid Build Coastguard Worker 
7217*da0073e9SAndroid Build Coastguard Worker                 mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
7218*da0073e9SAndroid Build Coastguard Worker                 mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
7219*da0073e9SAndroid Build Coastguard Worker                 mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
7220*da0073e9SAndroid Build Coastguard Worker                 mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
7221*da0073e9SAndroid Build Coastguard Worker 
7222*da0073e9SAndroid Build Coastguard Worker                 n = sizeof(mz_uint32) * 6;
7223*da0073e9SAndroid Build Coastguard Worker             }
7224*da0073e9SAndroid Build Coastguard Worker             else
7225*da0073e9SAndroid Build Coastguard Worker             {
7226*da0073e9SAndroid Build Coastguard Worker                 /* dest is NOT zip64, just copy it as-is */
7227*da0073e9SAndroid Build Coastguard Worker                 n = sizeof(mz_uint32) * (has_id ? 4 : 3);
7228*da0073e9SAndroid Build Coastguard Worker             }
7229*da0073e9SAndroid Build Coastguard Worker         }
7230*da0073e9SAndroid Build Coastguard Worker 
7231*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7232*da0073e9SAndroid Build Coastguard Worker         {
7233*da0073e9SAndroid Build Coastguard Worker             pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7234*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7235*da0073e9SAndroid Build Coastguard Worker         }
7236*da0073e9SAndroid Build Coastguard Worker 
7237*da0073e9SAndroid Build Coastguard Worker         // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
7238*da0073e9SAndroid Build Coastguard Worker         cur_src_file_ofs += n;
7239*da0073e9SAndroid Build Coastguard Worker         cur_dst_file_ofs += n;
7240*da0073e9SAndroid Build Coastguard Worker     }
7241*da0073e9SAndroid Build Coastguard Worker     pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7242*da0073e9SAndroid Build Coastguard Worker 
7243*da0073e9SAndroid Build Coastguard Worker     /* Finally, add the new central dir header */
7244*da0073e9SAndroid Build Coastguard Worker     orig_central_dir_size = pState->m_central_dir.m_size;
7245*da0073e9SAndroid Build Coastguard Worker 
7246*da0073e9SAndroid Build Coastguard Worker     memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
7247*da0073e9SAndroid Build Coastguard Worker 
7248*da0073e9SAndroid Build Coastguard Worker     if (pState->m_zip64)
7249*da0073e9SAndroid Build Coastguard Worker     {
7250*da0073e9SAndroid Build Coastguard Worker         /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */
7251*da0073e9SAndroid Build Coastguard Worker         const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
7252*da0073e9SAndroid Build Coastguard Worker         mz_zip_array new_ext_block;
7253*da0073e9SAndroid Build Coastguard Worker 
7254*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
7255*da0073e9SAndroid Build Coastguard Worker 
7256*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7257*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7258*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
7259*da0073e9SAndroid Build Coastguard Worker 
7260*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL))
7261*da0073e9SAndroid Build Coastguard Worker         {
7262*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_clear(pZip, &new_ext_block);
7263*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
7264*da0073e9SAndroid Build Coastguard Worker         }
7265*da0073e9SAndroid Build Coastguard Worker 
7266*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
7267*da0073e9SAndroid Build Coastguard Worker 
7268*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7269*da0073e9SAndroid Build Coastguard Worker         {
7270*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_clear(pZip, &new_ext_block);
7271*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7272*da0073e9SAndroid Build Coastguard Worker         }
7273*da0073e9SAndroid Build Coastguard Worker 
7274*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
7275*da0073e9SAndroid Build Coastguard Worker         {
7276*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_clear(pZip, &new_ext_block);
7277*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7278*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7279*da0073e9SAndroid Build Coastguard Worker         }
7280*da0073e9SAndroid Build Coastguard Worker 
7281*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
7282*da0073e9SAndroid Build Coastguard Worker         {
7283*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_clear(pZip, &new_ext_block);
7284*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7285*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7286*da0073e9SAndroid Build Coastguard Worker         }
7287*da0073e9SAndroid Build Coastguard Worker 
7288*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len))
7289*da0073e9SAndroid Build Coastguard Worker         {
7290*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_clear(pZip, &new_ext_block);
7291*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7292*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7293*da0073e9SAndroid Build Coastguard Worker         }
7294*da0073e9SAndroid Build Coastguard Worker 
7295*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_clear(pZip, &new_ext_block);
7296*da0073e9SAndroid Build Coastguard Worker     }
7297*da0073e9SAndroid Build Coastguard Worker     else
7298*da0073e9SAndroid Build Coastguard Worker     {
7299*da0073e9SAndroid Build Coastguard Worker         /* sanity checks */
7300*da0073e9SAndroid Build Coastguard Worker         if (cur_dst_file_ofs > MZ_UINT32_MAX)
7301*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7302*da0073e9SAndroid Build Coastguard Worker 
7303*da0073e9SAndroid Build Coastguard Worker         if (local_dir_header_ofs >= MZ_UINT32_MAX)
7304*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7305*da0073e9SAndroid Build Coastguard Worker 
7306*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
7307*da0073e9SAndroid Build Coastguard Worker 
7308*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7309*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7310*da0073e9SAndroid Build Coastguard Worker 
7311*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size))
7312*da0073e9SAndroid Build Coastguard Worker         {
7313*da0073e9SAndroid Build Coastguard Worker             mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7314*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7315*da0073e9SAndroid Build Coastguard Worker         }
7316*da0073e9SAndroid Build Coastguard Worker     }
7317*da0073e9SAndroid Build Coastguard Worker 
7318*da0073e9SAndroid Build Coastguard Worker     /* This shouldn't trigger unless we screwed up during the initial sanity checks */
7319*da0073e9SAndroid Build Coastguard Worker     if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7320*da0073e9SAndroid Build Coastguard Worker     {
7321*da0073e9SAndroid Build Coastguard Worker         /* TODO: Support central dirs >= 32-bits in size */
7322*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7323*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7324*da0073e9SAndroid Build Coastguard Worker     }
7325*da0073e9SAndroid Build Coastguard Worker 
7326*da0073e9SAndroid Build Coastguard Worker     n = (mz_uint32)orig_central_dir_size;
7327*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
7328*da0073e9SAndroid Build Coastguard Worker     {
7329*da0073e9SAndroid Build Coastguard Worker         mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7330*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7331*da0073e9SAndroid Build Coastguard Worker     }
7332*da0073e9SAndroid Build Coastguard Worker 
7333*da0073e9SAndroid Build Coastguard Worker     pZip->m_total_files++;
7334*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size = cur_dst_file_ofs;
7335*da0073e9SAndroid Build Coastguard Worker 
7336*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
7337*da0073e9SAndroid Build Coastguard Worker }
7338*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_finalize_archive(mz_zip_archive * pZip)7339*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
7340*da0073e9SAndroid Build Coastguard Worker {
7341*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7342*da0073e9SAndroid Build Coastguard Worker     mz_zip_internal_state *pState;
7343*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7344*da0073e9SAndroid Build Coastguard Worker     mz_uint64 central_dir_ofs, central_dir_size;
7345*da0073e9SAndroid Build Coastguard Worker     mz_uint8 hdr[256];
7346*da0073e9SAndroid Build Coastguard Worker 
7347*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
7348*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7349*da0073e9SAndroid Build Coastguard Worker 
7350*da0073e9SAndroid Build Coastguard Worker     pState = pZip->m_pState;
7351*da0073e9SAndroid Build Coastguard Worker 
7352*da0073e9SAndroid Build Coastguard Worker     if (pState->m_zip64)
7353*da0073e9SAndroid Build Coastguard Worker     {
7354*da0073e9SAndroid Build Coastguard Worker         if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX))
7355*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7356*da0073e9SAndroid Build Coastguard Worker     }
7357*da0073e9SAndroid Build Coastguard Worker     else
7358*da0073e9SAndroid Build Coastguard Worker     {
7359*da0073e9SAndroid Build Coastguard Worker         if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX))
7360*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7361*da0073e9SAndroid Build Coastguard Worker     }
7362*da0073e9SAndroid Build Coastguard Worker 
7363*da0073e9SAndroid Build Coastguard Worker     central_dir_ofs = 0;
7364*da0073e9SAndroid Build Coastguard Worker     central_dir_size = 0;
7365*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_total_files)
7366*da0073e9SAndroid Build Coastguard Worker     {
7367*da0073e9SAndroid Build Coastguard Worker         /* Write central directory */
7368*da0073e9SAndroid Build Coastguard Worker         central_dir_ofs = pZip->m_archive_size;
7369*da0073e9SAndroid Build Coastguard Worker         central_dir_size = pState->m_central_dir.m_size;
7370*da0073e9SAndroid Build Coastguard Worker         pZip->m_central_directory_file_ofs = central_dir_ofs;
7371*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
7372*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7373*da0073e9SAndroid Build Coastguard Worker 
7374*da0073e9SAndroid Build Coastguard Worker         pZip->m_archive_size += central_dir_size;
7375*da0073e9SAndroid Build Coastguard Worker     }
7376*da0073e9SAndroid Build Coastguard Worker 
7377*da0073e9SAndroid Build Coastguard Worker     if (pState->m_zip64)
7378*da0073e9SAndroid Build Coastguard Worker     {
7379*da0073e9SAndroid Build Coastguard Worker         /* Write zip64 end of central directory header */
7380*da0073e9SAndroid Build Coastguard Worker         mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
7381*da0073e9SAndroid Build Coastguard Worker 
7382*da0073e9SAndroid Build Coastguard Worker         MZ_CLEAR_OBJ(hdr);
7383*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);
7384*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - sizeof(mz_uint32) - sizeof(mz_uint64));
7385*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */
7386*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);
7387*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
7388*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
7389*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
7390*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
7391*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
7392*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7393*da0073e9SAndroid Build Coastguard Worker 
7394*da0073e9SAndroid Build Coastguard Worker         pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
7395*da0073e9SAndroid Build Coastguard Worker 
7396*da0073e9SAndroid Build Coastguard Worker         /* Write zip64 end of central directory locator */
7397*da0073e9SAndroid Build Coastguard Worker         MZ_CLEAR_OBJ(hdr);
7398*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);
7399*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
7400*da0073e9SAndroid Build Coastguard Worker         MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);
7401*da0073e9SAndroid Build Coastguard Worker         if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
7402*da0073e9SAndroid Build Coastguard Worker             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7403*da0073e9SAndroid Build Coastguard Worker 
7404*da0073e9SAndroid Build Coastguard Worker         pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
7405*da0073e9SAndroid Build Coastguard Worker     }
7406*da0073e9SAndroid Build Coastguard Worker 
7407*da0073e9SAndroid Build Coastguard Worker     /* Write end of central directory record */
7408*da0073e9SAndroid Build Coastguard Worker     MZ_CLEAR_OBJ(hdr);
7409*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
7410*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7411*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7412*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size));
7413*da0073e9SAndroid Build Coastguard Worker     MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));
7414*da0073e9SAndroid Build Coastguard Worker 
7415*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
7416*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7417*da0073e9SAndroid Build Coastguard Worker 
7418*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
7419*da0073e9SAndroid Build Coastguard Worker     if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
7420*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
7421*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
7422*da0073e9SAndroid Build Coastguard Worker 
7423*da0073e9SAndroid Build Coastguard Worker     pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;
7424*da0073e9SAndroid Build Coastguard Worker 
7425*da0073e9SAndroid Build Coastguard Worker     pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
7426*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
7427*da0073e9SAndroid Build Coastguard Worker }
7428*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_finalize_heap_archive(mz_zip_archive * pZip,void ** ppBuf,size_t * pSize)7429*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)
7430*da0073e9SAndroid Build Coastguard Worker {
7431*da0073e9SAndroid Build Coastguard Worker     if ((!ppBuf) || (!pSize))
7432*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7433*da0073e9SAndroid Build Coastguard Worker 
7434*da0073e9SAndroid Build Coastguard Worker     *ppBuf = NULL;
7435*da0073e9SAndroid Build Coastguard Worker     *pSize = 0;
7436*da0073e9SAndroid Build Coastguard Worker 
7437*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState))
7438*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7439*da0073e9SAndroid Build Coastguard Worker 
7440*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_pWrite != mz_zip_heap_write_func)
7441*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7442*da0073e9SAndroid Build Coastguard Worker 
7443*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_finalize_archive(pZip))
7444*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
7445*da0073e9SAndroid Build Coastguard Worker 
7446*da0073e9SAndroid Build Coastguard Worker     *ppBuf = pZip->m_pState->m_pMem;
7447*da0073e9SAndroid Build Coastguard Worker     *pSize = pZip->m_pState->m_mem_size;
7448*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_pMem = NULL;
7449*da0073e9SAndroid Build Coastguard Worker     pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
7450*da0073e9SAndroid Build Coastguard Worker 
7451*da0073e9SAndroid Build Coastguard Worker     return MZ_TRUE;
7452*da0073e9SAndroid Build Coastguard Worker }
7453*da0073e9SAndroid Build Coastguard Worker 
mz_zip_writer_end(mz_zip_archive * pZip)7454*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
7455*da0073e9SAndroid Build Coastguard Worker {
7456*da0073e9SAndroid Build Coastguard Worker     return mz_zip_writer_end_internal(pZip, MZ_TRUE);
7457*da0073e9SAndroid Build Coastguard Worker }
7458*da0073e9SAndroid Build Coastguard Worker 
7459*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_STDIO
mz_zip_add_mem_to_archive_file_in_place(const char * pZip_filename,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags)7460*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
7461*da0073e9SAndroid Build Coastguard Worker {
7462*da0073e9SAndroid Build Coastguard Worker     return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL);
7463*da0073e9SAndroid Build Coastguard Worker }
7464*da0073e9SAndroid Build Coastguard Worker 
mz_zip_add_mem_to_archive_file_in_place_v2(const char * pZip_filename,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,mz_zip_error * pErr)7465*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)
7466*da0073e9SAndroid Build Coastguard Worker {
7467*da0073e9SAndroid Build Coastguard Worker     mz_bool status, created_new_archive = MZ_FALSE;
7468*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive zip_archive;
7469*da0073e9SAndroid Build Coastguard Worker     struct MZ_FILE_STAT_STRUCT file_stat;
7470*da0073e9SAndroid Build Coastguard Worker     mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7471*da0073e9SAndroid Build Coastguard Worker 
7472*da0073e9SAndroid Build Coastguard Worker     mz_zip_zero_struct(&zip_archive);
7473*da0073e9SAndroid Build Coastguard Worker     if ((int)level_and_flags < 0)
7474*da0073e9SAndroid Build Coastguard Worker         level_and_flags = MZ_DEFAULT_LEVEL;
7475*da0073e9SAndroid Build Coastguard Worker 
7476*da0073e9SAndroid Build Coastguard Worker     if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
7477*da0073e9SAndroid Build Coastguard Worker     {
7478*da0073e9SAndroid Build Coastguard Worker         if (pErr)
7479*da0073e9SAndroid Build Coastguard Worker             *pErr = MZ_ZIP_INVALID_PARAMETER;
7480*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
7481*da0073e9SAndroid Build Coastguard Worker     }
7482*da0073e9SAndroid Build Coastguard Worker 
7483*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_validate_archive_name(pArchive_name))
7484*da0073e9SAndroid Build Coastguard Worker     {
7485*da0073e9SAndroid Build Coastguard Worker         if (pErr)
7486*da0073e9SAndroid Build Coastguard Worker             *pErr = MZ_ZIP_INVALID_FILENAME;
7487*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
7488*da0073e9SAndroid Build Coastguard Worker     }
7489*da0073e9SAndroid Build Coastguard Worker 
7490*da0073e9SAndroid Build Coastguard Worker     /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */
7491*da0073e9SAndroid Build Coastguard Worker     /* So be sure to compile with _LARGEFILE64_SOURCE 1 */
7492*da0073e9SAndroid Build Coastguard Worker     if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
7493*da0073e9SAndroid Build Coastguard Worker     {
7494*da0073e9SAndroid Build Coastguard Worker         /* Create a new archive. */
7495*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
7496*da0073e9SAndroid Build Coastguard Worker         {
7497*da0073e9SAndroid Build Coastguard Worker             if (pErr)
7498*da0073e9SAndroid Build Coastguard Worker                 *pErr = zip_archive.m_last_error;
7499*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
7500*da0073e9SAndroid Build Coastguard Worker         }
7501*da0073e9SAndroid Build Coastguard Worker 
7502*da0073e9SAndroid Build Coastguard Worker         created_new_archive = MZ_TRUE;
7503*da0073e9SAndroid Build Coastguard Worker     }
7504*da0073e9SAndroid Build Coastguard Worker     else
7505*da0073e9SAndroid Build Coastguard Worker     {
7506*da0073e9SAndroid Build Coastguard Worker         /* Append to an existing archive. */
7507*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7508*da0073e9SAndroid Build Coastguard Worker         {
7509*da0073e9SAndroid Build Coastguard Worker             if (pErr)
7510*da0073e9SAndroid Build Coastguard Worker                 *pErr = zip_archive.m_last_error;
7511*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
7512*da0073e9SAndroid Build Coastguard Worker         }
7513*da0073e9SAndroid Build Coastguard Worker 
7514*da0073e9SAndroid Build Coastguard Worker         if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))
7515*da0073e9SAndroid Build Coastguard Worker         {
7516*da0073e9SAndroid Build Coastguard Worker             if (pErr)
7517*da0073e9SAndroid Build Coastguard Worker                 *pErr = zip_archive.m_last_error;
7518*da0073e9SAndroid Build Coastguard Worker 
7519*da0073e9SAndroid Build Coastguard Worker             mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
7520*da0073e9SAndroid Build Coastguard Worker 
7521*da0073e9SAndroid Build Coastguard Worker             return MZ_FALSE;
7522*da0073e9SAndroid Build Coastguard Worker         }
7523*da0073e9SAndroid Build Coastguard Worker     }
7524*da0073e9SAndroid Build Coastguard Worker 
7525*da0073e9SAndroid Build Coastguard Worker     status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
7526*da0073e9SAndroid Build Coastguard Worker     actual_err = zip_archive.m_last_error;
7527*da0073e9SAndroid Build Coastguard Worker 
7528*da0073e9SAndroid Build Coastguard Worker     /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */
7529*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_finalize_archive(&zip_archive))
7530*da0073e9SAndroid Build Coastguard Worker     {
7531*da0073e9SAndroid Build Coastguard Worker         if (!actual_err)
7532*da0073e9SAndroid Build Coastguard Worker             actual_err = zip_archive.m_last_error;
7533*da0073e9SAndroid Build Coastguard Worker 
7534*da0073e9SAndroid Build Coastguard Worker         status = MZ_FALSE;
7535*da0073e9SAndroid Build Coastguard Worker     }
7536*da0073e9SAndroid Build Coastguard Worker 
7537*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_writer_end_internal(&zip_archive, status))
7538*da0073e9SAndroid Build Coastguard Worker     {
7539*da0073e9SAndroid Build Coastguard Worker         if (!actual_err)
7540*da0073e9SAndroid Build Coastguard Worker             actual_err = zip_archive.m_last_error;
7541*da0073e9SAndroid Build Coastguard Worker 
7542*da0073e9SAndroid Build Coastguard Worker         status = MZ_FALSE;
7543*da0073e9SAndroid Build Coastguard Worker     }
7544*da0073e9SAndroid Build Coastguard Worker 
7545*da0073e9SAndroid Build Coastguard Worker     if ((!status) && (created_new_archive))
7546*da0073e9SAndroid Build Coastguard Worker     {
7547*da0073e9SAndroid Build Coastguard Worker         /* It's a new archive and something went wrong, so just delete it. */
7548*da0073e9SAndroid Build Coastguard Worker         int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
7549*da0073e9SAndroid Build Coastguard Worker         (void)ignoredStatus;
7550*da0073e9SAndroid Build Coastguard Worker     }
7551*da0073e9SAndroid Build Coastguard Worker 
7552*da0073e9SAndroid Build Coastguard Worker     if (pErr)
7553*da0073e9SAndroid Build Coastguard Worker         *pErr = actual_err;
7554*da0073e9SAndroid Build Coastguard Worker 
7555*da0073e9SAndroid Build Coastguard Worker     return status;
7556*da0073e9SAndroid Build Coastguard Worker }
7557*da0073e9SAndroid Build Coastguard Worker 
mz_zip_extract_archive_file_to_heap_v2(const char * pZip_filename,const char * pArchive_name,const char * pComment,size_t * pSize,mz_uint flags,mz_zip_error * pErr)7558*da0073e9SAndroid Build Coastguard Worker void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)
7559*da0073e9SAndroid Build Coastguard Worker {
7560*da0073e9SAndroid Build Coastguard Worker     mz_uint32 file_index;
7561*da0073e9SAndroid Build Coastguard Worker     mz_zip_archive zip_archive;
7562*da0073e9SAndroid Build Coastguard Worker     void *p = NULL;
7563*da0073e9SAndroid Build Coastguard Worker 
7564*da0073e9SAndroid Build Coastguard Worker     if (pSize)
7565*da0073e9SAndroid Build Coastguard Worker         *pSize = 0;
7566*da0073e9SAndroid Build Coastguard Worker 
7567*da0073e9SAndroid Build Coastguard Worker     if ((!pZip_filename) || (!pArchive_name))
7568*da0073e9SAndroid Build Coastguard Worker     {
7569*da0073e9SAndroid Build Coastguard Worker         if (pErr)
7570*da0073e9SAndroid Build Coastguard Worker             *pErr = MZ_ZIP_INVALID_PARAMETER;
7571*da0073e9SAndroid Build Coastguard Worker 
7572*da0073e9SAndroid Build Coastguard Worker         return NULL;
7573*da0073e9SAndroid Build Coastguard Worker     }
7574*da0073e9SAndroid Build Coastguard Worker 
7575*da0073e9SAndroid Build Coastguard Worker     mz_zip_zero_struct(&zip_archive);
7576*da0073e9SAndroid Build Coastguard Worker     if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7577*da0073e9SAndroid Build Coastguard Worker     {
7578*da0073e9SAndroid Build Coastguard Worker         if (pErr)
7579*da0073e9SAndroid Build Coastguard Worker             *pErr = zip_archive.m_last_error;
7580*da0073e9SAndroid Build Coastguard Worker 
7581*da0073e9SAndroid Build Coastguard Worker         return NULL;
7582*da0073e9SAndroid Build Coastguard Worker     }
7583*da0073e9SAndroid Build Coastguard Worker 
7584*da0073e9SAndroid Build Coastguard Worker     if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
7585*da0073e9SAndroid Build Coastguard Worker     {
7586*da0073e9SAndroid Build Coastguard Worker         p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
7587*da0073e9SAndroid Build Coastguard Worker     }
7588*da0073e9SAndroid Build Coastguard Worker 
7589*da0073e9SAndroid Build Coastguard Worker     mz_zip_reader_end_internal(&zip_archive, p != NULL);
7590*da0073e9SAndroid Build Coastguard Worker 
7591*da0073e9SAndroid Build Coastguard Worker     if (pErr)
7592*da0073e9SAndroid Build Coastguard Worker         *pErr = zip_archive.m_last_error;
7593*da0073e9SAndroid Build Coastguard Worker 
7594*da0073e9SAndroid Build Coastguard Worker     return p;
7595*da0073e9SAndroid Build Coastguard Worker }
7596*da0073e9SAndroid Build Coastguard Worker 
mz_zip_extract_archive_file_to_heap(const char * pZip_filename,const char * pArchive_name,size_t * pSize,mz_uint flags)7597*da0073e9SAndroid Build Coastguard Worker void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
7598*da0073e9SAndroid Build Coastguard Worker {
7599*da0073e9SAndroid Build Coastguard Worker     return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
7600*da0073e9SAndroid Build Coastguard Worker }
7601*da0073e9SAndroid Build Coastguard Worker 
7602*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_STDIO */
7603*da0073e9SAndroid Build Coastguard Worker 
7604*da0073e9SAndroid Build Coastguard Worker #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
7605*da0073e9SAndroid Build Coastguard Worker 
7606*da0073e9SAndroid Build Coastguard Worker /* ------------------- Misc utils */
7607*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_mode(mz_zip_archive * pZip)7608*da0073e9SAndroid Build Coastguard Worker mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
7609*da0073e9SAndroid Build Coastguard Worker {
7610*da0073e9SAndroid Build Coastguard Worker     return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
7611*da0073e9SAndroid Build Coastguard Worker }
7612*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_type(mz_zip_archive * pZip)7613*da0073e9SAndroid Build Coastguard Worker mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
7614*da0073e9SAndroid Build Coastguard Worker {
7615*da0073e9SAndroid Build Coastguard Worker     return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
7616*da0073e9SAndroid Build Coastguard Worker }
7617*da0073e9SAndroid Build Coastguard Worker 
mz_zip_set_last_error(mz_zip_archive * pZip,mz_zip_error err_num)7618*da0073e9SAndroid Build Coastguard Worker mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
7619*da0073e9SAndroid Build Coastguard Worker {
7620*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7621*da0073e9SAndroid Build Coastguard Worker     mz_zip_error prev_err;
7622*da0073e9SAndroid Build Coastguard Worker 
7623*da0073e9SAndroid Build Coastguard Worker     if (!pZip)
7624*da0073e9SAndroid Build Coastguard Worker         return MZ_ZIP_INVALID_PARAMETER;
7625*da0073e9SAndroid Build Coastguard Worker 
7626*da0073e9SAndroid Build Coastguard Worker     prev_err = pZip->m_last_error;
7627*da0073e9SAndroid Build Coastguard Worker 
7628*da0073e9SAndroid Build Coastguard Worker     pZip->m_last_error = err_num;
7629*da0073e9SAndroid Build Coastguard Worker     return prev_err;
7630*da0073e9SAndroid Build Coastguard Worker }
7631*da0073e9SAndroid Build Coastguard Worker 
mz_zip_peek_last_error(mz_zip_archive * pZip)7632*da0073e9SAndroid Build Coastguard Worker mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
7633*da0073e9SAndroid Build Coastguard Worker {
7634*da0073e9SAndroid Build Coastguard Worker     if (!pZip)
7635*da0073e9SAndroid Build Coastguard Worker         return MZ_ZIP_INVALID_PARAMETER;
7636*da0073e9SAndroid Build Coastguard Worker 
7637*da0073e9SAndroid Build Coastguard Worker     return pZip->m_last_error;
7638*da0073e9SAndroid Build Coastguard Worker }
7639*da0073e9SAndroid Build Coastguard Worker 
mz_zip_clear_last_error(mz_zip_archive * pZip)7640*da0073e9SAndroid Build Coastguard Worker mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
7641*da0073e9SAndroid Build Coastguard Worker {
7642*da0073e9SAndroid Build Coastguard Worker     return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
7643*da0073e9SAndroid Build Coastguard Worker }
7644*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_last_error(mz_zip_archive * pZip)7645*da0073e9SAndroid Build Coastguard Worker mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
7646*da0073e9SAndroid Build Coastguard Worker {
7647*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7648*da0073e9SAndroid Build Coastguard Worker     mz_zip_error prev_err;
7649*da0073e9SAndroid Build Coastguard Worker 
7650*da0073e9SAndroid Build Coastguard Worker     if (!pZip)
7651*da0073e9SAndroid Build Coastguard Worker         return MZ_ZIP_INVALID_PARAMETER;
7652*da0073e9SAndroid Build Coastguard Worker 
7653*da0073e9SAndroid Build Coastguard Worker     prev_err = pZip->m_last_error;
7654*da0073e9SAndroid Build Coastguard Worker 
7655*da0073e9SAndroid Build Coastguard Worker     pZip->m_last_error = MZ_ZIP_NO_ERROR;
7656*da0073e9SAndroid Build Coastguard Worker     return prev_err;
7657*da0073e9SAndroid Build Coastguard Worker }
7658*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_error_string(mz_zip_error mz_err)7659*da0073e9SAndroid Build Coastguard Worker const char *mz_zip_get_error_string(mz_zip_error mz_err)
7660*da0073e9SAndroid Build Coastguard Worker {
7661*da0073e9SAndroid Build Coastguard Worker     switch (mz_err)
7662*da0073e9SAndroid Build Coastguard Worker     {
7663*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_NO_ERROR:
7664*da0073e9SAndroid Build Coastguard Worker             return "no error";
7665*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_UNDEFINED_ERROR:
7666*da0073e9SAndroid Build Coastguard Worker             return "undefined error";
7667*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_TOO_MANY_FILES:
7668*da0073e9SAndroid Build Coastguard Worker             return "too many files";
7669*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_TOO_LARGE:
7670*da0073e9SAndroid Build Coastguard Worker             return "file too large";
7671*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_UNSUPPORTED_METHOD:
7672*da0073e9SAndroid Build Coastguard Worker             return "unsupported method";
7673*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
7674*da0073e9SAndroid Build Coastguard Worker             return "unsupported encryption";
7675*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_UNSUPPORTED_FEATURE:
7676*da0073e9SAndroid Build Coastguard Worker             return "unsupported feature";
7677*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
7678*da0073e9SAndroid Build Coastguard Worker             return "failed finding central directory";
7679*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_NOT_AN_ARCHIVE:
7680*da0073e9SAndroid Build Coastguard Worker             return "not a ZIP archive";
7681*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
7682*da0073e9SAndroid Build Coastguard Worker             return "invalid header or archive is corrupted";
7683*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_UNSUPPORTED_MULTIDISK:
7684*da0073e9SAndroid Build Coastguard Worker             return "unsupported multidisk archive";
7685*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_DECOMPRESSION_FAILED:
7686*da0073e9SAndroid Build Coastguard Worker             return "decompression failed or archive is corrupted";
7687*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_COMPRESSION_FAILED:
7688*da0073e9SAndroid Build Coastguard Worker             return "compression failed";
7689*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
7690*da0073e9SAndroid Build Coastguard Worker             return "unexpected decompressed size";
7691*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_CRC_CHECK_FAILED:
7692*da0073e9SAndroid Build Coastguard Worker             return "CRC-32 check failed";
7693*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
7694*da0073e9SAndroid Build Coastguard Worker             return "unsupported central directory size";
7695*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_ALLOC_FAILED:
7696*da0073e9SAndroid Build Coastguard Worker             return "allocation failed";
7697*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_OPEN_FAILED:
7698*da0073e9SAndroid Build Coastguard Worker             return "file open failed";
7699*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_CREATE_FAILED:
7700*da0073e9SAndroid Build Coastguard Worker             return "file create failed";
7701*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_WRITE_FAILED:
7702*da0073e9SAndroid Build Coastguard Worker             return "file write failed";
7703*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_READ_FAILED:
7704*da0073e9SAndroid Build Coastguard Worker             return "file read failed";
7705*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_CLOSE_FAILED:
7706*da0073e9SAndroid Build Coastguard Worker             return "file close failed";
7707*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_SEEK_FAILED:
7708*da0073e9SAndroid Build Coastguard Worker             return "file seek failed";
7709*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_STAT_FAILED:
7710*da0073e9SAndroid Build Coastguard Worker             return "file stat failed";
7711*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_INVALID_PARAMETER:
7712*da0073e9SAndroid Build Coastguard Worker             return "invalid parameter";
7713*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_INVALID_FILENAME:
7714*da0073e9SAndroid Build Coastguard Worker             return "invalid filename";
7715*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_BUF_TOO_SMALL:
7716*da0073e9SAndroid Build Coastguard Worker             return "buffer too small";
7717*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_INTERNAL_ERROR:
7718*da0073e9SAndroid Build Coastguard Worker             return "internal error";
7719*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_FILE_NOT_FOUND:
7720*da0073e9SAndroid Build Coastguard Worker             return "file not found";
7721*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_ARCHIVE_TOO_LARGE:
7722*da0073e9SAndroid Build Coastguard Worker             return "archive is too large";
7723*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_VALIDATION_FAILED:
7724*da0073e9SAndroid Build Coastguard Worker             return "validation failed";
7725*da0073e9SAndroid Build Coastguard Worker         case MZ_ZIP_WRITE_CALLBACK_FAILED:
7726*da0073e9SAndroid Build Coastguard Worker             return "write calledback failed";
7727*da0073e9SAndroid Build Coastguard Worker         default:
7728*da0073e9SAndroid Build Coastguard Worker             break;
7729*da0073e9SAndroid Build Coastguard Worker     }
7730*da0073e9SAndroid Build Coastguard Worker 
7731*da0073e9SAndroid Build Coastguard Worker     return "unknown error";
7732*da0073e9SAndroid Build Coastguard Worker }
7733*da0073e9SAndroid Build Coastguard Worker 
7734*da0073e9SAndroid Build Coastguard Worker /* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
mz_zip_is_zip64(mz_zip_archive * pZip)7735*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
7736*da0073e9SAndroid Build Coastguard Worker {
7737*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState))
7738*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
7739*da0073e9SAndroid Build Coastguard Worker 
7740*da0073e9SAndroid Build Coastguard Worker     return pZip->m_pState->m_zip64;
7741*da0073e9SAndroid Build Coastguard Worker }
7742*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_central_dir_size(mz_zip_archive * pZip)7743*da0073e9SAndroid Build Coastguard Worker size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
7744*da0073e9SAndroid Build Coastguard Worker {
7745*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState))
7746*da0073e9SAndroid Build Coastguard Worker         return 0;
7747*da0073e9SAndroid Build Coastguard Worker 
7748*da0073e9SAndroid Build Coastguard Worker     return pZip->m_pState->m_central_dir.m_size;
7749*da0073e9SAndroid Build Coastguard Worker }
7750*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_get_num_files(mz_zip_archive * pZip)7751*da0073e9SAndroid Build Coastguard Worker mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
7752*da0073e9SAndroid Build Coastguard Worker {
7753*da0073e9SAndroid Build Coastguard Worker     return pZip ? pZip->m_total_files : 0;
7754*da0073e9SAndroid Build Coastguard Worker }
7755*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_archive_size(mz_zip_archive * pZip)7756*da0073e9SAndroid Build Coastguard Worker mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
7757*da0073e9SAndroid Build Coastguard Worker {
7758*da0073e9SAndroid Build Coastguard Worker     if (!pZip)
7759*da0073e9SAndroid Build Coastguard Worker         return 0;
7760*da0073e9SAndroid Build Coastguard Worker     return pZip->m_archive_size;
7761*da0073e9SAndroid Build Coastguard Worker }
7762*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_archive_file_start_offset(mz_zip_archive * pZip)7763*da0073e9SAndroid Build Coastguard Worker mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
7764*da0073e9SAndroid Build Coastguard Worker {
7765*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState))
7766*da0073e9SAndroid Build Coastguard Worker         return 0;
7767*da0073e9SAndroid Build Coastguard Worker     return pZip->m_pState->m_file_archive_start_ofs;
7768*da0073e9SAndroid Build Coastguard Worker }
7769*da0073e9SAndroid Build Coastguard Worker 
mz_zip_get_cfile(mz_zip_archive * pZip)7770*da0073e9SAndroid Build Coastguard Worker MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
7771*da0073e9SAndroid Build Coastguard Worker {
7772*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState))
7773*da0073e9SAndroid Build Coastguard Worker         return 0;
7774*da0073e9SAndroid Build Coastguard Worker     return pZip->m_pState->m_pFile;
7775*da0073e9SAndroid Build Coastguard Worker }
7776*da0073e9SAndroid Build Coastguard Worker 
mz_zip_read_archive_data(mz_zip_archive * pZip,mz_uint64 file_ofs,void * pBuf,size_t n)7777*da0073e9SAndroid Build Coastguard Worker size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
7778*da0073e9SAndroid Build Coastguard Worker {
7779*da0073e9SAndroid Build Coastguard Worker     if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
7780*da0073e9SAndroid Build Coastguard Worker         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7781*da0073e9SAndroid Build Coastguard Worker 
7782*da0073e9SAndroid Build Coastguard Worker     return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
7783*da0073e9SAndroid Build Coastguard Worker }
7784*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_get_filename(mz_zip_archive * pZip,mz_uint file_index,char * pFilename,mz_uint filename_buf_size)7785*da0073e9SAndroid Build Coastguard Worker mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
7786*da0073e9SAndroid Build Coastguard Worker {
7787*da0073e9SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7788*da0073e9SAndroid Build Coastguard Worker     mz_uint n;
7789*da0073e9SAndroid Build Coastguard Worker     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
7790*da0073e9SAndroid Build Coastguard Worker     if (!p)
7791*da0073e9SAndroid Build Coastguard Worker     {
7792*da0073e9SAndroid Build Coastguard Worker         if (filename_buf_size)
7793*da0073e9SAndroid Build Coastguard Worker             pFilename[0] = '\0';
7794*da0073e9SAndroid Build Coastguard Worker         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7795*da0073e9SAndroid Build Coastguard Worker         return 0;
7796*da0073e9SAndroid Build Coastguard Worker     }
7797*da0073e9SAndroid Build Coastguard Worker     n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7798*da0073e9SAndroid Build Coastguard Worker     if (filename_buf_size)
7799*da0073e9SAndroid Build Coastguard Worker     {
7800*da0073e9SAndroid Build Coastguard Worker         n = MZ_MIN(n, filename_buf_size - 1);
7801*da0073e9SAndroid Build Coastguard Worker         memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
7802*da0073e9SAndroid Build Coastguard Worker         pFilename[n] = '\0';
7803*da0073e9SAndroid Build Coastguard Worker     }
7804*da0073e9SAndroid Build Coastguard Worker     return n + 1;
7805*da0073e9SAndroid Build Coastguard Worker }
7806*da0073e9SAndroid Build Coastguard Worker 
mz_zip_reader_file_stat(mz_zip_archive * pZip,mz_uint file_index,mz_zip_archive_file_stat * pStat)7807*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
7808*da0073e9SAndroid Build Coastguard Worker {
7809*da0073e9SAndroid Build Coastguard Worker     return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
7810*da0073e9SAndroid Build Coastguard Worker }
7811*da0073e9SAndroid Build Coastguard Worker 
mz_zip_end(mz_zip_archive * pZip)7812*da0073e9SAndroid Build Coastguard Worker mz_bool mz_zip_end(mz_zip_archive *pZip)
7813*da0073e9SAndroid Build Coastguard Worker {
7814*da0073e9SAndroid Build Coastguard Worker     if (!pZip)
7815*da0073e9SAndroid Build Coastguard Worker         return MZ_FALSE;
7816*da0073e9SAndroid Build Coastguard Worker 
7817*da0073e9SAndroid Build Coastguard Worker     if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
7818*da0073e9SAndroid Build Coastguard Worker         return mz_zip_reader_end(pZip);
7819*da0073e9SAndroid Build Coastguard Worker #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7820*da0073e9SAndroid Build Coastguard Worker     else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))
7821*da0073e9SAndroid Build Coastguard Worker         return mz_zip_writer_end(pZip);
7822*da0073e9SAndroid Build Coastguard Worker #endif
7823*da0073e9SAndroid Build Coastguard Worker 
7824*da0073e9SAndroid Build Coastguard Worker     return MZ_FALSE;
7825*da0073e9SAndroid Build Coastguard Worker }
7826*da0073e9SAndroid Build Coastguard Worker 
7827*da0073e9SAndroid Build Coastguard Worker #ifdef __cplusplus
7828*da0073e9SAndroid Build Coastguard Worker }
7829*da0073e9SAndroid Build Coastguard Worker #endif
7830*da0073e9SAndroid Build Coastguard Worker 
7831*da0073e9SAndroid Build Coastguard Worker #endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/
7832