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