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