1163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross/*
2163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * Copyright (C) 2007 The Android Open Source Project
3163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *
4163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * Licensed under the Apache License, Version 2.0 (the "License");
5163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * you may not use this file except in compliance with the License.
6163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * You may obtain a copy of the License at
7163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *
8163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *      http://www.apache.org/licenses/LICENSE-2.0
9163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *
10163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * Unless required by applicable law or agreed to in writing, software
11163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * distributed under the License is distributed on an "AS IS" BASIS,
12163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * See the License for the specific language governing permissions and
14163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * limitations under the License.
15163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross */
16163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
17163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross//
18163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross// Misc zip/gzip utility functions.
19163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross//
20163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
21163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross#define LOG_TAG "ziputil"
22163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
23163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross#include <utils/Log.h>
24163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross#include <utils/ZipUtils.h>
25163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross#include <utils/ZipFileRO.h>
26163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
27163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross#include <stdlib.h>
28163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross#include <string.h>
29163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross#include <assert.h>
30163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
31163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross#include <zlib.h>
32163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
33163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Crossusing namespace android;
34163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
35163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross/*
36163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * Utility function that expands zip/gzip "deflate" compressed data
37163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * into a buffer.
38163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *
39163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * "fd" is an open file positioned at the start of the "deflate" data
40163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * "buf" must hold at least "uncompressedLen" bytes.
41163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross */
42163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross/*static*/ bool ZipUtils::inflateToBuffer(int fd, void* buf,
43163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    long uncompressedLen, long compressedLen)
44163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross{
45163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    bool result = false;
46163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	const unsigned long kReadBufSize = 32768;
47163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	unsigned char* readBuf = NULL;
48163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    z_stream zstream;
49163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    int zerr;
50163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    unsigned long compRemaining;
51163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
52163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    assert(uncompressedLen >= 0);
53163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    assert(compressedLen >= 0);
54163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
55163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	readBuf = new unsigned char[kReadBufSize];
56163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	if (readBuf == NULL)
57163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        goto bail;
58163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    compRemaining = compressedLen;
59163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
60163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /*
61163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross     * Initialize the zlib stream.
62163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross     */
63163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	memset(&zstream, 0, sizeof(zstream));
64163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.zalloc = Z_NULL;
65163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.zfree = Z_NULL;
66163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.opaque = Z_NULL;
67163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.next_in = NULL;
68163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.avail_in = 0;
69163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.next_out = (Bytef*) buf;
70163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.avail_out = uncompressedLen;
71163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.data_type = Z_UNKNOWN;
72163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
73163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	/*
74163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	 * Use the undocumented "negative window bits" feature to tell zlib
75163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	 * that there's no zlib header waiting for it.
76163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	 */
77163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zerr = inflateInit2(&zstream, -MAX_WBITS);
78163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if (zerr != Z_OK) {
79163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        if (zerr == Z_VERSION_ERROR) {
80163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
81163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                ZLIB_VERSION);
82163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        } else {
83163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
84163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        }
85163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        goto bail;
86163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    }
87163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
88163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /*
89163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross     * Loop while we have data.
90163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross     */
91163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    do {
92163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        unsigned long getSize;
93163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
94163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        /* read as much as we can */
95163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        if (zstream.avail_in == 0) {
96163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            getSize = (compRemaining > kReadBufSize) ?
97163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                        kReadBufSize : compRemaining;
98163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ALOGV("+++ reading %ld bytes (%ld left)\n",
99163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                getSize, compRemaining);
100163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
101163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            int cc = read(fd, readBuf, getSize);
102163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            if (cc != (int) getSize) {
103163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                ALOGD("inflate read failed (%d vs %ld)\n",
104163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                    cc, getSize);
105163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                goto z_bail;
106163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            }
107163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
108163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            compRemaining -= getSize;
109163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
110163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            zstream.next_in = readBuf;
111163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            zstream.avail_in = getSize;
112163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        }
113163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
114163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        /* uncompress the data */
115163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        zerr = inflate(&zstream, Z_NO_FLUSH);
116163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        if (zerr != Z_OK && zerr != Z_STREAM_END) {
117163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ALOGD("zlib inflate call failed (zerr=%d)\n", zerr);
118163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            goto z_bail;
119163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        }
120163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
121163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross		/* output buffer holds all, so no need to write the output */
122163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    } while (zerr == Z_OK);
123163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
124163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
125163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
126163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if ((long) zstream.total_out != uncompressedLen) {
127163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        ALOGW("Size mismatch on inflated file (%ld vs %ld)\n",
128163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            zstream.total_out, uncompressedLen);
129163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        goto z_bail;
130163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    }
131163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
132163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    // success!
133163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    result = true;
134163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
135163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Crossz_bail:
136163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    inflateEnd(&zstream);        /* free up any allocated structures */
137163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
138163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Crossbail:
139163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	delete[] readBuf;
140163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    return result;
141163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross}
142163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
143163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross/*
144163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * Utility function that expands zip/gzip "deflate" compressed data
145163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * into a buffer.
146163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *
147163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * (This is a clone of the previous function, but it takes a FILE* instead
148163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * of an fd.  We could pass fileno(fd) to the above, but we can run into
149163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * trouble when "fp" has a different notion of what fd's file position is.)
150163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *
151163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * "fp" is an open file positioned at the start of the "deflate" data
152163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * "buf" must hold at least "uncompressedLen" bytes.
153163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross */
154163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross/*static*/ bool ZipUtils::inflateToBuffer(FILE* fp, void* buf,
155163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    long uncompressedLen, long compressedLen)
156163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross{
157163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    bool result = false;
158163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	const unsigned long kReadBufSize = 32768;
159163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	unsigned char* readBuf = NULL;
160163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    z_stream zstream;
161163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    int zerr;
162163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    unsigned long compRemaining;
163163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
164163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    assert(uncompressedLen >= 0);
165163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    assert(compressedLen >= 0);
166163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
167163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	readBuf = new unsigned char[kReadBufSize];
168163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	if (readBuf == NULL)
169163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        goto bail;
170163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    compRemaining = compressedLen;
171163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
172163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /*
173163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross     * Initialize the zlib stream.
174163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross     */
175163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	memset(&zstream, 0, sizeof(zstream));
176163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.zalloc = Z_NULL;
177163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.zfree = Z_NULL;
178163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.opaque = Z_NULL;
179163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.next_in = NULL;
180163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.avail_in = 0;
181163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.next_out = (Bytef*) buf;
182163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.avail_out = uncompressedLen;
183163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zstream.data_type = Z_UNKNOWN;
184163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
185163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	/*
186163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	 * Use the undocumented "negative window bits" feature to tell zlib
187163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	 * that there's no zlib header waiting for it.
188163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	 */
189163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    zerr = inflateInit2(&zstream, -MAX_WBITS);
190163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if (zerr != Z_OK) {
191163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        if (zerr == Z_VERSION_ERROR) {
192163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
193163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                ZLIB_VERSION);
194163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        } else {
195163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
196163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        }
197163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        goto bail;
198163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    }
199163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
200163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /*
201163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross     * Loop while we have data.
202163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross     */
203163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    do {
204163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        unsigned long getSize;
205163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
206163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        /* read as much as we can */
207163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        if (zstream.avail_in == 0) {
208163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            getSize = (compRemaining > kReadBufSize) ?
209163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                        kReadBufSize : compRemaining;
210163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ALOGV("+++ reading %ld bytes (%ld left)\n",
211163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                getSize, compRemaining);
212163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
213163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            int cc = fread(readBuf, 1, getSize, fp);
214163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            if (cc != (int) getSize) {
215163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                ALOGD("inflate read failed (%d vs %ld)\n",
216163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                    cc, getSize);
217163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross                goto z_bail;
218163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            }
219163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
220163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            compRemaining -= getSize;
221163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
222163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            zstream.next_in = readBuf;
223163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            zstream.avail_in = getSize;
224163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        }
225163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
226163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        /* uncompress the data */
227163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        zerr = inflate(&zstream, Z_NO_FLUSH);
228163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        if (zerr != Z_OK && zerr != Z_STREAM_END) {
229163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ALOGD("zlib inflate call failed (zerr=%d)\n", zerr);
230163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            goto z_bail;
231163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        }
232163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
233163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross		/* output buffer holds all, so no need to write the output */
234163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    } while (zerr == Z_OK);
235163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
236163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
237163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
238163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if ((long) zstream.total_out != uncompressedLen) {
239163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        ALOGW("Size mismatch on inflated file (%ld vs %ld)\n",
240163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            zstream.total_out, uncompressedLen);
241163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        goto z_bail;
242163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    }
243163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
244163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    // success!
245163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    result = true;
246163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
247163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Crossz_bail:
248163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    inflateEnd(&zstream);        /* free up any allocated structures */
249163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
250163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Crossbail:
251163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross	delete[] readBuf;
252163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    return result;
253163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross}
254163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
255163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross/*
256163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * Look at the contents of a gzip archive.  We want to know where the
257163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * data starts, and how long it will be after it is uncompressed.
258163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *
259163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * We expect to find the CRC and length as the last 8 bytes on the file.
260163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * This is a pretty reasonable thing to expect for locally-compressed
261163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * files, but there's a small chance that some extra padding got thrown
262163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * on (the man page talks about compressed data written to tape).  We
263163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * don't currently deal with that here.  If "gzip -l" whines, we're going
264163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * to fail too.
265163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross *
266163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross * On exit, "fp" is pointing at the start of the compressed data.
267163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross */
268163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross/*static*/ bool ZipUtils::examineGzip(FILE* fp, int* pCompressionMethod,
269163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32)
270163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross{
271163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    enum {  // flags
272163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        FTEXT       = 0x01,
273163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        FHCRC       = 0x02,
274163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        FEXTRA      = 0x04,
275163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        FNAME       = 0x08,
276163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        FCOMMENT    = 0x10,
277163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    };
278163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    int ic;
279163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    int method, flags;
280163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    int i;
281163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
282163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    ic = getc(fp);
283163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if (ic != 0x1f || getc(fp) != 0x8b)
284163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        return false;       // not gzip
285163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    method = getc(fp);
286163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    flags = getc(fp);
287163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
288163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /* quick sanity checks */
289163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if (method == EOF || flags == EOF)
290163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        return false;
291163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if (method != ZipFileRO::kCompressDeflated)
292163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        return false;
293163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
294163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /* skip over 4 bytes of mod time, 1 byte XFL, 1 byte OS */
295163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    for (i = 0; i < 6; i++)
296163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        (void) getc(fp);
297163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /* consume "extra" field, if present */
298163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if ((flags & FEXTRA) != 0) {
299163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        int len;
300163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
301163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        len = getc(fp);
302163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        len |= getc(fp) << 8;
303163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        while (len-- && getc(fp) != EOF)
304163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ;
305163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    }
306163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /* consume filename, if present */
307163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if ((flags & FNAME) != 0) {
308163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        do {
309163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ic = getc(fp);
310163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        } while (ic != 0 && ic != EOF);
311163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    }
312163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /* consume comment, if present */
313163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if ((flags & FCOMMENT) != 0) {
314163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        do {
315163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross            ic = getc(fp);
316163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        } while (ic != 0 && ic != EOF);
317163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    }
318163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /* consume 16-bit header CRC, if present */
319163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if ((flags & FHCRC) != 0) {
320163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        (void) getc(fp);
321163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        (void) getc(fp);
322163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    }
323163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
324163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if (feof(fp) || ferror(fp))
325163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        return false;
326163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
327163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /* seek to the end; CRC and length are in the last 8 bytes */
328163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    long curPosn = ftell(fp);
329163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    unsigned char buf[8];
330163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    fseek(fp, -8, SEEK_END);
331163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    *pCompressedLen = ftell(fp) - curPosn;
332163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
333163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    if (fread(buf, 1, 8, fp) != 8)
334163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross        return false;
335163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    /* seek back to start of compressed data */
336163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    fseek(fp, curPosn, SEEK_SET);
337163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
338163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    *pCompressionMethod = method;
339163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    *pCRC32 = ZipFileRO::get4LE(&buf[0]);
340163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    *pUncompressedLen = ZipFileRO::get4LE(&buf[4]);
341163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross
342163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross    return true;
343163d5a9fa742e6a39f058fb9ed726fc31f4ecb28Colin Cross}
344