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, ¢ral_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