116c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Copyright (C) 2007 The Android Open Source Project 316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * you may not use this file except in compliance with the License. 616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * You may obtain a copy of the License at 716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 1016c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Unless required by applicable law or agreed to in writing, software 1116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 1216c4d154dca43c662571129af31b27433b919a32Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316c4d154dca43c662571129af31b27433b919a32Adam Lesinski * See the License for the specific language governing permissions and 1416c4d154dca43c662571129af31b27433b919a32Adam Lesinski * limitations under the License. 1516c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 1616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 1716c4d154dca43c662571129af31b27433b919a32Adam Lesinski// 1816c4d154dca43c662571129af31b27433b919a32Adam Lesinski// Read-only access to Zip archives, with minimal heap allocation. 1916c4d154dca43c662571129af31b27433b919a32Adam Lesinski// 2016c4d154dca43c662571129af31b27433b919a32Adam Lesinski#define LOG_TAG "zipro" 2116c4d154dca43c662571129af31b27433b919a32Adam Lesinski//#define LOG_NDEBUG 0 2216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <androidfw/ZipFileRO.h> 2316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/Log.h> 2416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/Compat.h> 2516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/misc.h> 2616c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <utils/threads.h> 27560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath#include <ziparchive/zip_archive.h> 2816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 2916c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <zlib.h> 3016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 3116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <string.h> 3216c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <fcntl.h> 3316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <errno.h> 3416c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <assert.h> 3516c4d154dca43c662571129af31b27433b919a32Adam Lesinski#include <unistd.h> 3616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 3716c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 3816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * We must open binary files using open(path, ... | O_BINARY) under Windows. 3916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Otherwise strange read errors will happen. 4016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 4116c4d154dca43c662571129af31b27433b919a32Adam Lesinski#ifndef O_BINARY 4216c4d154dca43c662571129af31b27433b919a32Adam Lesinski# define O_BINARY 0 4316c4d154dca43c662571129af31b27433b919a32Adam Lesinski#endif 4416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 4516c4d154dca43c662571129af31b27433b919a32Adam Lesinskiusing namespace android; 4616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 47560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamathclass _ZipEntryRO { 48560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamathpublic: 49560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ZipEntry entry; 50560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ZipEntryName name; 51560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath void *cookie; 5216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 53560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath _ZipEntryRO() : cookie(NULL) { 54560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath } 5516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 56560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamathprivate: 57560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath _ZipEntryRO(const _ZipEntryRO& other); 58560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath _ZipEntryRO& operator=(const _ZipEntryRO& other); 59560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath}; 6016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 61560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan KamathZipFileRO::~ZipFileRO() { 62560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath CloseArchive(mHandle); 63560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath free(mFileName); 6416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 6516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 6616c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 6716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Open the specified file read-only. We memory-map the entire thing and 6816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * close the file before returning. 6916c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 70560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath/* static */ ZipFileRO* ZipFileRO::open(const char* zipFileName) 7116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 72560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ZipArchiveHandle handle; 73560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const int32_t error = OpenArchive(zipFileName, &handle); 74560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (error) { 75560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ALOGW("Error opening archive %s: %s", zipFileName, ErrorCodeString(error)); 76560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return NULL; 7716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 7816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 79560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return new ZipFileRO(handle, strdup(zipFileName)); 80560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath} 8116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 8216c4d154dca43c662571129af31b27433b919a32Adam Lesinski 83560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan KamathZipEntryRO ZipFileRO::findEntryByName(const char* entryName) const 84560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath{ 85560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath _ZipEntryRO* data = new _ZipEntryRO; 86560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const int32_t error = FindEntry(mHandle, entryName, &(data->entry)); 87560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (error) { 88560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath delete data; 89560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return NULL; 9016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 9116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 92560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath data->name.name = entryName; 93560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath data->name.name_length = strlen(entryName); 9416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 95560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return (ZipEntryRO) data; 9616c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 9716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 9816c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 99560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath * Get the useful fields from the zip entry. 100560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath * 101560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath * Returns "false" if the offsets to the fields or the contents of the fields 102560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath * appear to be bogus. 10316c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 104560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamathbool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, 105560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const 10616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 107560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 108560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const ZipEntry& ze = zipEntry->entry; 10916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 110560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (pMethod != NULL) { 111560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath *pMethod = ze.method; 11216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 113560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (pUncompLen != NULL) { 114560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath *pUncompLen = ze.uncompressed_length; 11516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 116560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (pCompLen != NULL) { 117560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath *pCompLen = ze.compressed_length; 11816c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 119560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (pOffset != NULL) { 120560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath *pOffset = ze.offset; 12116c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 122560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (pModWhen != NULL) { 123560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath *pModWhen = ze.mod_time; 12416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 125560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (pCrc32 != NULL) { 126560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath *pCrc32 = ze.crc32; 12716c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 12816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 12916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return true; 13016c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 13116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 132560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamathbool ZipFileRO::startIteration(void** cookie) 13316c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 134560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath _ZipEntryRO* ze = new _ZipEntryRO; 135560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath int32_t error = StartIteration(mHandle, &(ze->cookie), NULL /* prefix */); 136560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (error) { 137560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ALOGW("Could not start iteration over %s: %s", mFileName, ErrorCodeString(error)); 138560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath delete ze; 139560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return false; 14016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 14116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 142560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath *cookie = ze; 143560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return true; 14416c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 14516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 146560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan KamathZipEntryRO ZipFileRO::nextEntry(void* cookie) 14716c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 148560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath _ZipEntryRO* ze = reinterpret_cast<_ZipEntryRO*>(cookie); 149560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath int32_t error = Next(ze->cookie, &(ze->entry), &(ze->name)); 150560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (error) { 151560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (error != -1) { 152560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ALOGW("Error iteration over %s: %s", mFileName, ErrorCodeString(error)); 15316c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 154560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return NULL; 15516c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 15616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 157560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return &(ze->entry); 15816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 15916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 160560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamathvoid ZipFileRO::endIteration(void* cookie) 16116c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 162560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath delete reinterpret_cast<_ZipEntryRO*>(cookie); 16316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 16416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 165560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamathvoid ZipFileRO::releaseEntry(ZipEntryRO entry) const 16616c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 167560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath delete reinterpret_cast<_ZipEntryRO*>(entry); 16816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 16916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 17016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 17116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Copy the entry's filename to the buffer. 17216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 17316c4d154dca43c662571129af31b27433b919a32Adam Lesinskiint ZipFileRO::getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen) 17416c4d154dca43c662571129af31b27433b919a32Adam Lesinski const 17516c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 176560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 177560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const uint16_t requiredSize = zipEntry->name.name_length + 1; 17816c4d154dca43c662571129af31b27433b919a32Adam Lesinski 179560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (bufLen < requiredSize) { 180560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ALOGW("Buffer too short, requires %d bytes for entry name", requiredSize); 181560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return requiredSize; 182560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath } 183560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath 184560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath memcpy(buffer, zipEntry->name.name, requiredSize - 1); 185560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath buffer[requiredSize - 1] = '\0'; 18616c4d154dca43c662571129af31b27433b919a32Adam Lesinski 18716c4d154dca43c662571129af31b27433b919a32Adam Lesinski return 0; 18816c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 18916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 19016c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 19116c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Create a new FileMap object that spans the data in "entry". 19216c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 19316c4d154dca43c662571129af31b27433b919a32Adam LesinskiFileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const 19416c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 195560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 196560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const ZipEntry& ze = zipEntry->entry; 197560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath int fd = GetFileDescriptor(mHandle); 198560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath size_t actualLen = 0; 19916c4d154dca43c662571129af31b27433b919a32Adam Lesinski 200560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (ze.method == kCompressStored) { 201560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath actualLen = ze.uncompressed_length; 20216c4d154dca43c662571129af31b27433b919a32Adam Lesinski } else { 203560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath actualLen = ze.compressed_length; 20416c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 20516c4d154dca43c662571129af31b27433b919a32Adam Lesinski 206560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath FileMap* newMap = new FileMap(); 207560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (!newMap->create(mFileName, fd, ze.offset, actualLen, true)) { 20816c4d154dca43c662571129af31b27433b919a32Adam Lesinski newMap->release(); 20916c4d154dca43c662571129af31b27433b919a32Adam Lesinski return NULL; 21016c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 21116c4d154dca43c662571129af31b27433b919a32Adam Lesinski 21216c4d154dca43c662571129af31b27433b919a32Adam Lesinski return newMap; 21316c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 21416c4d154dca43c662571129af31b27433b919a32Adam Lesinski 21516c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 21616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Uncompress an entry, in its entirety, into the provided output buffer. 21716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 21816c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This doesn't verify the data's CRC, which might be useful for 21916c4d154dca43c662571129af31b27433b919a32Adam Lesinski * uncompressed data. The caller should be able to manage it. 22016c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 221560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamathbool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer, size_t size) const 22216c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 223560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 224560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const int32_t error = ExtractToMemory(mHandle, &(zipEntry->entry), 225560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath (uint8_t*) buffer, size); 226560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (error) { 227560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error)); 22816c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 22916c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 23016c4d154dca43c662571129af31b27433b919a32Adam Lesinski 231560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return true; 23216c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 23316c4d154dca43c662571129af31b27433b919a32Adam Lesinski 23416c4d154dca43c662571129af31b27433b919a32Adam Lesinski/* 23516c4d154dca43c662571129af31b27433b919a32Adam Lesinski * Uncompress an entry, in its entirety, to an open file descriptor. 23616c4d154dca43c662571129af31b27433b919a32Adam Lesinski * 23716c4d154dca43c662571129af31b27433b919a32Adam Lesinski * This doesn't verify the data's CRC, but probably should. 23816c4d154dca43c662571129af31b27433b919a32Adam Lesinski */ 23916c4d154dca43c662571129af31b27433b919a32Adam Lesinskibool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const 24016c4d154dca43c662571129af31b27433b919a32Adam Lesinski{ 241560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 242560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath const int32_t error = ExtractEntryToFile(mHandle, &(zipEntry->entry), fd); 243560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath if (error) { 244560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error)); 24516c4d154dca43c662571129af31b27433b919a32Adam Lesinski return false; 24616c4d154dca43c662571129af31b27433b919a32Adam Lesinski } 24716c4d154dca43c662571129af31b27433b919a32Adam Lesinski 248560566d2915c03bed338fc532ac7f7aa3620cfdfNarayan Kamath return true; 24916c4d154dca43c662571129af31b27433b919a32Adam Lesinski} 250