ZipFileRO.cpp revision 5a7587fa90732c013bb9266f1bdae0a557455c15
11f5762e646bed2290934280464832782766ee68eMathias Agopian/* 21f5762e646bed2290934280464832782766ee68eMathias Agopian * Copyright (C) 2007 The Android Open Source Project 31f5762e646bed2290934280464832782766ee68eMathias Agopian * 41f5762e646bed2290934280464832782766ee68eMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License"); 51f5762e646bed2290934280464832782766ee68eMathias Agopian * you may not use this file except in compliance with the License. 61f5762e646bed2290934280464832782766ee68eMathias Agopian * You may obtain a copy of the License at 71f5762e646bed2290934280464832782766ee68eMathias Agopian * 81f5762e646bed2290934280464832782766ee68eMathias Agopian * http://www.apache.org/licenses/LICENSE-2.0 91f5762e646bed2290934280464832782766ee68eMathias Agopian * 101f5762e646bed2290934280464832782766ee68eMathias Agopian * Unless required by applicable law or agreed to in writing, software 111f5762e646bed2290934280464832782766ee68eMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS, 121f5762e646bed2290934280464832782766ee68eMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131f5762e646bed2290934280464832782766ee68eMathias Agopian * See the License for the specific language governing permissions and 141f5762e646bed2290934280464832782766ee68eMathias Agopian * limitations under the License. 151f5762e646bed2290934280464832782766ee68eMathias Agopian */ 161f5762e646bed2290934280464832782766ee68eMathias Agopian 171f5762e646bed2290934280464832782766ee68eMathias Agopian// 181f5762e646bed2290934280464832782766ee68eMathias Agopian// Read-only access to Zip archives, with minimal heap allocation. 191f5762e646bed2290934280464832782766ee68eMathias Agopian// 201f5762e646bed2290934280464832782766ee68eMathias Agopian#define LOG_TAG "zipro" 211f5762e646bed2290934280464832782766ee68eMathias Agopian//#define LOG_NDEBUG 0 221f5762e646bed2290934280464832782766ee68eMathias Agopian#include <androidfw/ZipFileRO.h> 231f5762e646bed2290934280464832782766ee68eMathias Agopian#include <utils/Log.h> 241f5762e646bed2290934280464832782766ee68eMathias Agopian#include <utils/Compat.h> 251f5762e646bed2290934280464832782766ee68eMathias Agopian#include <utils/misc.h> 261f5762e646bed2290934280464832782766ee68eMathias Agopian#include <utils/threads.h> 27afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath#include <ziparchive/zip_archive.h> 281f5762e646bed2290934280464832782766ee68eMathias Agopian 291f5762e646bed2290934280464832782766ee68eMathias Agopian#include <zlib.h> 301f5762e646bed2290934280464832782766ee68eMathias Agopian 311f5762e646bed2290934280464832782766ee68eMathias Agopian#include <string.h> 321f5762e646bed2290934280464832782766ee68eMathias Agopian#include <fcntl.h> 331f5762e646bed2290934280464832782766ee68eMathias Agopian#include <errno.h> 341f5762e646bed2290934280464832782766ee68eMathias Agopian#include <assert.h> 351f5762e646bed2290934280464832782766ee68eMathias Agopian#include <unistd.h> 361f5762e646bed2290934280464832782766ee68eMathias Agopian 371f5762e646bed2290934280464832782766ee68eMathias Agopianusing namespace android; 381f5762e646bed2290934280464832782766ee68eMathias Agopian 39afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathclass _ZipEntryRO { 40afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathpublic: 41afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ZipEntry entry; 42afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ZipEntryName name; 43afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath void *cookie; 441f5762e646bed2290934280464832782766ee68eMathias Agopian 45e2134a4b5dafc37f2de7e9b4190819f24aac207cPiotr Jastrzebski _ZipEntryRO() : cookie(NULL) {} 461f5762e646bed2290934280464832782766ee68eMathias Agopian 471a68b079d714b1de52775e1153359f2867340754Piotr Jastrzebski ~_ZipEntryRO() { 481a68b079d714b1de52775e1153359f2867340754Piotr Jastrzebski EndIteration(cookie); 491a68b079d714b1de52775e1153359f2867340754Piotr Jastrzebski } 501a68b079d714b1de52775e1153359f2867340754Piotr Jastrzebski 51afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathprivate: 52afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath _ZipEntryRO(const _ZipEntryRO& other); 53afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath _ZipEntryRO& operator=(const _ZipEntryRO& other); 54afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath}; 551f5762e646bed2290934280464832782766ee68eMathias Agopian 56afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan KamathZipFileRO::~ZipFileRO() { 57afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath CloseArchive(mHandle); 58afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath free(mFileName); 591f5762e646bed2290934280464832782766ee68eMathias Agopian} 601f5762e646bed2290934280464832782766ee68eMathias Agopian 611f5762e646bed2290934280464832782766ee68eMathias Agopian/* 621f5762e646bed2290934280464832782766ee68eMathias Agopian * Open the specified file read-only. We memory-map the entire thing and 631f5762e646bed2290934280464832782766ee68eMathias Agopian * close the file before returning. 641f5762e646bed2290934280464832782766ee68eMathias Agopian */ 65afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath/* static */ ZipFileRO* ZipFileRO::open(const char* zipFileName) 661f5762e646bed2290934280464832782766ee68eMathias Agopian{ 67afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ZipArchiveHandle handle; 68afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const int32_t error = OpenArchive(zipFileName, &handle); 69afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (error) { 70afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ALOGW("Error opening archive %s: %s", zipFileName, ErrorCodeString(error)); 715a7587fa90732c013bb9266f1bdae0a557455c15Narayan Kamath CloseArchive(handle); 72afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return NULL; 731f5762e646bed2290934280464832782766ee68eMathias Agopian } 741f5762e646bed2290934280464832782766ee68eMathias Agopian 75afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return new ZipFileRO(handle, strdup(zipFileName)); 76afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath} 771f5762e646bed2290934280464832782766ee68eMathias Agopian 781f5762e646bed2290934280464832782766ee68eMathias Agopian 79afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan KamathZipEntryRO ZipFileRO::findEntryByName(const char* entryName) const 80afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath{ 81afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath _ZipEntryRO* data = new _ZipEntryRO; 82e2134a4b5dafc37f2de7e9b4190819f24aac207cPiotr Jastrzebski 83e2134a4b5dafc37f2de7e9b4190819f24aac207cPiotr Jastrzebski data->name = ZipEntryName(entryName); 84e2134a4b5dafc37f2de7e9b4190819f24aac207cPiotr Jastrzebski 85e2134a4b5dafc37f2de7e9b4190819f24aac207cPiotr Jastrzebski const int32_t error = FindEntry(mHandle, data->name, &(data->entry)); 86afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (error) { 87afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath delete data; 88afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return NULL; 891f5762e646bed2290934280464832782766ee68eMathias Agopian } 901f5762e646bed2290934280464832782766ee68eMathias Agopian 91afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return (ZipEntryRO) data; 921f5762e646bed2290934280464832782766ee68eMathias Agopian} 931f5762e646bed2290934280464832782766ee68eMathias Agopian 941f5762e646bed2290934280464832782766ee68eMathias Agopian/* 95afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath * Get the useful fields from the zip entry. 96afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath * 97afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath * Returns "false" if the offsets to the fields or the contents of the fields 98afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath * appear to be bogus. 991f5762e646bed2290934280464832782766ee68eMathias Agopian */ 100afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathbool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, 101afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const 1021f5762e646bed2290934280464832782766ee68eMathias Agopian{ 103afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 104afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const ZipEntry& ze = zipEntry->entry; 1051f5762e646bed2290934280464832782766ee68eMathias Agopian 106afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (pMethod != NULL) { 107afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath *pMethod = ze.method; 1081f5762e646bed2290934280464832782766ee68eMathias Agopian } 109afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (pUncompLen != NULL) { 110afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath *pUncompLen = ze.uncompressed_length; 1111f5762e646bed2290934280464832782766ee68eMathias Agopian } 112afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (pCompLen != NULL) { 113afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath *pCompLen = ze.compressed_length; 1141f5762e646bed2290934280464832782766ee68eMathias Agopian } 115afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (pOffset != NULL) { 116afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath *pOffset = ze.offset; 1171f5762e646bed2290934280464832782766ee68eMathias Agopian } 118afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (pModWhen != NULL) { 119afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath *pModWhen = ze.mod_time; 1201f5762e646bed2290934280464832782766ee68eMathias Agopian } 121afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (pCrc32 != NULL) { 122afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath *pCrc32 = ze.crc32; 1231f5762e646bed2290934280464832782766ee68eMathias Agopian } 1241f5762e646bed2290934280464832782766ee68eMathias Agopian 1251f5762e646bed2290934280464832782766ee68eMathias Agopian return true; 1261f5762e646bed2290934280464832782766ee68eMathias Agopian} 1271f5762e646bed2290934280464832782766ee68eMathias Agopian 128afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathbool ZipFileRO::startIteration(void** cookie) 1291f5762e646bed2290934280464832782766ee68eMathias Agopian{ 130afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath _ZipEntryRO* ze = new _ZipEntryRO; 131afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath int32_t error = StartIteration(mHandle, &(ze->cookie), NULL /* prefix */); 132afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (error) { 133afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ALOGW("Could not start iteration over %s: %s", mFileName, ErrorCodeString(error)); 134afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath delete ze; 135afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return false; 1361f5762e646bed2290934280464832782766ee68eMathias Agopian } 1371f5762e646bed2290934280464832782766ee68eMathias Agopian 138afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath *cookie = ze; 139afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return true; 1401f5762e646bed2290934280464832782766ee68eMathias Agopian} 1411f5762e646bed2290934280464832782766ee68eMathias Agopian 142afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan KamathZipEntryRO ZipFileRO::nextEntry(void* cookie) 1431f5762e646bed2290934280464832782766ee68eMathias Agopian{ 144afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath _ZipEntryRO* ze = reinterpret_cast<_ZipEntryRO*>(cookie); 145afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath int32_t error = Next(ze->cookie, &(ze->entry), &(ze->name)); 146afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (error) { 147afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (error != -1) { 148afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ALOGW("Error iteration over %s: %s", mFileName, ErrorCodeString(error)); 1491f5762e646bed2290934280464832782766ee68eMathias Agopian } 150afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return NULL; 1511f5762e646bed2290934280464832782766ee68eMathias Agopian } 1521f5762e646bed2290934280464832782766ee68eMathias Agopian 153afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return &(ze->entry); 1541f5762e646bed2290934280464832782766ee68eMathias Agopian} 1551f5762e646bed2290934280464832782766ee68eMathias Agopian 156afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathvoid ZipFileRO::endIteration(void* cookie) 1571f5762e646bed2290934280464832782766ee68eMathias Agopian{ 158afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath delete reinterpret_cast<_ZipEntryRO*>(cookie); 1591f5762e646bed2290934280464832782766ee68eMathias Agopian} 1601f5762e646bed2290934280464832782766ee68eMathias Agopian 161afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathvoid ZipFileRO::releaseEntry(ZipEntryRO entry) const 1621f5762e646bed2290934280464832782766ee68eMathias Agopian{ 163afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath delete reinterpret_cast<_ZipEntryRO*>(entry); 1641f5762e646bed2290934280464832782766ee68eMathias Agopian} 1651f5762e646bed2290934280464832782766ee68eMathias Agopian 1661f5762e646bed2290934280464832782766ee68eMathias Agopian/* 1671f5762e646bed2290934280464832782766ee68eMathias Agopian * Copy the entry's filename to the buffer. 1681f5762e646bed2290934280464832782766ee68eMathias Agopian */ 1691f5762e646bed2290934280464832782766ee68eMathias Agopianint ZipFileRO::getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen) 1701f5762e646bed2290934280464832782766ee68eMathias Agopian const 1711f5762e646bed2290934280464832782766ee68eMathias Agopian{ 172afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 173afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const uint16_t requiredSize = zipEntry->name.name_length + 1; 1741f5762e646bed2290934280464832782766ee68eMathias Agopian 175afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (bufLen < requiredSize) { 176afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ALOGW("Buffer too short, requires %d bytes for entry name", requiredSize); 177afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return requiredSize; 178afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 179afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 180afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath memcpy(buffer, zipEntry->name.name, requiredSize - 1); 181afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath buffer[requiredSize - 1] = '\0'; 1821f5762e646bed2290934280464832782766ee68eMathias Agopian 1831f5762e646bed2290934280464832782766ee68eMathias Agopian return 0; 1841f5762e646bed2290934280464832782766ee68eMathias Agopian} 1851f5762e646bed2290934280464832782766ee68eMathias Agopian 1861f5762e646bed2290934280464832782766ee68eMathias Agopian/* 1871f5762e646bed2290934280464832782766ee68eMathias Agopian * Create a new FileMap object that spans the data in "entry". 1881f5762e646bed2290934280464832782766ee68eMathias Agopian */ 1891f5762e646bed2290934280464832782766ee68eMathias AgopianFileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const 1901f5762e646bed2290934280464832782766ee68eMathias Agopian{ 191afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 192afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const ZipEntry& ze = zipEntry->entry; 193afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath int fd = GetFileDescriptor(mHandle); 194afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath size_t actualLen = 0; 1950d6c2d7b9db209d740992045dd3b842e52306598Kenny Root 196afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (ze.method == kCompressStored) { 197afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath actualLen = ze.uncompressed_length; 1980d6c2d7b9db209d740992045dd3b842e52306598Kenny Root } else { 199afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath actualLen = ze.compressed_length; 2000d6c2d7b9db209d740992045dd3b842e52306598Kenny Root } 2011f5762e646bed2290934280464832782766ee68eMathias Agopian 202afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath FileMap* newMap = new FileMap(); 203afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (!newMap->create(mFileName, fd, ze.offset, actualLen, true)) { 204688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath delete newMap; 2051f5762e646bed2290934280464832782766ee68eMathias Agopian return NULL; 2061f5762e646bed2290934280464832782766ee68eMathias Agopian } 2071f5762e646bed2290934280464832782766ee68eMathias Agopian 2081f5762e646bed2290934280464832782766ee68eMathias Agopian return newMap; 2091f5762e646bed2290934280464832782766ee68eMathias Agopian} 2101f5762e646bed2290934280464832782766ee68eMathias Agopian 2111f5762e646bed2290934280464832782766ee68eMathias Agopian/* 2121f5762e646bed2290934280464832782766ee68eMathias Agopian * Uncompress an entry, in its entirety, into the provided output buffer. 2131f5762e646bed2290934280464832782766ee68eMathias Agopian * 2141f5762e646bed2290934280464832782766ee68eMathias Agopian * This doesn't verify the data's CRC, which might be useful for 2151f5762e646bed2290934280464832782766ee68eMathias Agopian * uncompressed data. The caller should be able to manage it. 2161f5762e646bed2290934280464832782766ee68eMathias Agopian */ 217afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathbool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer, size_t size) const 2181f5762e646bed2290934280464832782766ee68eMathias Agopian{ 219afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 220afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const int32_t error = ExtractToMemory(mHandle, &(zipEntry->entry), 221afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath (uint8_t*) buffer, size); 222afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (error) { 223afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error)); 2240d6c2d7b9db209d740992045dd3b842e52306598Kenny Root return false; 2250d6c2d7b9db209d740992045dd3b842e52306598Kenny Root } 2261f5762e646bed2290934280464832782766ee68eMathias Agopian 227afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return true; 2281f5762e646bed2290934280464832782766ee68eMathias Agopian} 2291f5762e646bed2290934280464832782766ee68eMathias Agopian 2301f5762e646bed2290934280464832782766ee68eMathias Agopian/* 2311f5762e646bed2290934280464832782766ee68eMathias Agopian * Uncompress an entry, in its entirety, to an open file descriptor. 2321f5762e646bed2290934280464832782766ee68eMathias Agopian * 2331f5762e646bed2290934280464832782766ee68eMathias Agopian * This doesn't verify the data's CRC, but probably should. 2341f5762e646bed2290934280464832782766ee68eMathias Agopian */ 2351f5762e646bed2290934280464832782766ee68eMathias Agopianbool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const 2361f5762e646bed2290934280464832782766ee68eMathias Agopian{ 237afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry); 238afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const int32_t error = ExtractEntryToFile(mHandle, &(zipEntry->entry), fd); 239afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (error) { 240afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error)); 2410d6c2d7b9db209d740992045dd3b842e52306598Kenny Root return false; 2420d6c2d7b9db209d740992045dd3b842e52306598Kenny Root } 2431f5762e646bed2290934280464832782766ee68eMathias Agopian 244afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return true; 2451f5762e646bed2290934280464832782766ee68eMathias Agopian} 246