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;
42f162faaa1266ad38c293e1e54911e389f39c2654Yusuke Sato    ZipString 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
83f162faaa1266ad38c293e1e54911e389f39c2654Yusuke Sato    data->name = ZipString(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 */
1004600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamathbool ZipFileRO::getEntryInfo(ZipEntryRO entry, uint16_t* pMethod,
1014600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath    uint32_t* pUncompLen, uint32_t* pCompLen, off64_t* pOffset,
1024600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath    uint32_t* pModWhen, uint32_t* pCrc32) const
1031f5762e646bed2290934280464832782766ee68eMathias Agopian{
104afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
105afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    const ZipEntry& ze = zipEntry->entry;
1061f5762e646bed2290934280464832782766ee68eMathias Agopian
107afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (pMethod != NULL) {
108afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        *pMethod = ze.method;
1091f5762e646bed2290934280464832782766ee68eMathias Agopian    }
110afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (pUncompLen != NULL) {
111afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        *pUncompLen = ze.uncompressed_length;
1121f5762e646bed2290934280464832782766ee68eMathias Agopian    }
113afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (pCompLen != NULL) {
114afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        *pCompLen = ze.compressed_length;
1151f5762e646bed2290934280464832782766ee68eMathias Agopian    }
116afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (pOffset != NULL) {
117afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        *pOffset = ze.offset;
1181f5762e646bed2290934280464832782766ee68eMathias Agopian    }
119afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (pModWhen != NULL) {
120afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        *pModWhen = ze.mod_time;
1211f5762e646bed2290934280464832782766ee68eMathias Agopian    }
122afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (pCrc32 != NULL) {
123afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        *pCrc32 = ze.crc32;
1241f5762e646bed2290934280464832782766ee68eMathias Agopian    }
1251f5762e646bed2290934280464832782766ee68eMathias Agopian
1261f5762e646bed2290934280464832782766ee68eMathias Agopian    return true;
1271f5762e646bed2290934280464832782766ee68eMathias Agopian}
1281f5762e646bed2290934280464832782766ee68eMathias Agopian
12934fe3df8519523dbb4bc27010fa57f259d5e868dYusuke Satobool ZipFileRO::startIteration(void** cookie) {
13034fe3df8519523dbb4bc27010fa57f259d5e868dYusuke Sato  return startIteration(cookie, NULL, NULL);
13134fe3df8519523dbb4bc27010fa57f259d5e868dYusuke Sato}
13234fe3df8519523dbb4bc27010fa57f259d5e868dYusuke Sato
13334fe3df8519523dbb4bc27010fa57f259d5e868dYusuke Satobool ZipFileRO::startIteration(void** cookie, const char* prefix, const char* suffix)
1341f5762e646bed2290934280464832782766ee68eMathias Agopian{
135afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    _ZipEntryRO* ze = new _ZipEntryRO;
13653a19bb967f45ddfb80699865dc30094024343f6Yusuke Sato    ZipString pe(prefix ? prefix : "");
13753a19bb967f45ddfb80699865dc30094024343f6Yusuke Sato    ZipString se(suffix ? suffix : "");
13834fe3df8519523dbb4bc27010fa57f259d5e868dYusuke Sato    int32_t error = StartIteration(mHandle, &(ze->cookie),
13934fe3df8519523dbb4bc27010fa57f259d5e868dYusuke Sato                                   prefix ? &pe : NULL,
14034fe3df8519523dbb4bc27010fa57f259d5e868dYusuke Sato                                   suffix ? &se : NULL);
141afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (error) {
142afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        ALOGW("Could not start iteration over %s: %s", mFileName, ErrorCodeString(error));
143afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        delete ze;
144afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        return false;
1451f5762e646bed2290934280464832782766ee68eMathias Agopian    }
1461f5762e646bed2290934280464832782766ee68eMathias Agopian
147afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    *cookie = ze;
148afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    return true;
1491f5762e646bed2290934280464832782766ee68eMathias Agopian}
1501f5762e646bed2290934280464832782766ee68eMathias Agopian
151afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan KamathZipEntryRO ZipFileRO::nextEntry(void* cookie)
1521f5762e646bed2290934280464832782766ee68eMathias Agopian{
153afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    _ZipEntryRO* ze = reinterpret_cast<_ZipEntryRO*>(cookie);
154afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    int32_t error = Next(ze->cookie, &(ze->entry), &(ze->name));
155afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (error) {
156afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        if (error != -1) {
157afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath            ALOGW("Error iteration over %s: %s", mFileName, ErrorCodeString(error));
1581f5762e646bed2290934280464832782766ee68eMathias Agopian        }
159afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        return NULL;
1601f5762e646bed2290934280464832782766ee68eMathias Agopian    }
1611f5762e646bed2290934280464832782766ee68eMathias Agopian
162afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    return &(ze->entry);
1631f5762e646bed2290934280464832782766ee68eMathias Agopian}
1641f5762e646bed2290934280464832782766ee68eMathias Agopian
165afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathvoid ZipFileRO::endIteration(void* cookie)
1661f5762e646bed2290934280464832782766ee68eMathias Agopian{
167afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    delete reinterpret_cast<_ZipEntryRO*>(cookie);
1681f5762e646bed2290934280464832782766ee68eMathias Agopian}
1691f5762e646bed2290934280464832782766ee68eMathias Agopian
170afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathvoid ZipFileRO::releaseEntry(ZipEntryRO entry) const
1711f5762e646bed2290934280464832782766ee68eMathias Agopian{
172afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    delete reinterpret_cast<_ZipEntryRO*>(entry);
1731f5762e646bed2290934280464832782766ee68eMathias Agopian}
1741f5762e646bed2290934280464832782766ee68eMathias Agopian
1751f5762e646bed2290934280464832782766ee68eMathias Agopian/*
1761f5762e646bed2290934280464832782766ee68eMathias Agopian * Copy the entry's filename to the buffer.
1771f5762e646bed2290934280464832782766ee68eMathias Agopian */
1784600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamathint ZipFileRO::getEntryFileName(ZipEntryRO entry, char* buffer, size_t bufLen)
1791f5762e646bed2290934280464832782766ee68eMathias Agopian    const
1801f5762e646bed2290934280464832782766ee68eMathias Agopian{
181afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
182afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    const uint16_t requiredSize = zipEntry->name.name_length + 1;
1831f5762e646bed2290934280464832782766ee68eMathias Agopian
184afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (bufLen < requiredSize) {
185afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        ALOGW("Buffer too short, requires %d bytes for entry name", requiredSize);
186afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        return requiredSize;
187afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    }
188afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
189afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    memcpy(buffer, zipEntry->name.name, requiredSize - 1);
190afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    buffer[requiredSize - 1] = '\0';
1911f5762e646bed2290934280464832782766ee68eMathias Agopian
1921f5762e646bed2290934280464832782766ee68eMathias Agopian    return 0;
1931f5762e646bed2290934280464832782766ee68eMathias Agopian}
1941f5762e646bed2290934280464832782766ee68eMathias Agopian
1951f5762e646bed2290934280464832782766ee68eMathias Agopian/*
1961f5762e646bed2290934280464832782766ee68eMathias Agopian * Create a new FileMap object that spans the data in "entry".
1971f5762e646bed2290934280464832782766ee68eMathias Agopian */
1981f5762e646bed2290934280464832782766ee68eMathias AgopianFileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const
1991f5762e646bed2290934280464832782766ee68eMathias Agopian{
200afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    const _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
201afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    const ZipEntry& ze = zipEntry->entry;
202afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    int fd = GetFileDescriptor(mHandle);
203afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    size_t actualLen = 0;
2040d6c2d7b9db209d740992045dd3b842e52306598Kenny Root
205afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (ze.method == kCompressStored) {
206afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        actualLen = ze.uncompressed_length;
2070d6c2d7b9db209d740992045dd3b842e52306598Kenny Root    } else {
208afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        actualLen = ze.compressed_length;
2090d6c2d7b9db209d740992045dd3b842e52306598Kenny Root    }
2101f5762e646bed2290934280464832782766ee68eMathias Agopian
211afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    FileMap* newMap = new FileMap();
212afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (!newMap->create(mFileName, fd, ze.offset, actualLen, true)) {
213688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath        delete newMap;
2141f5762e646bed2290934280464832782766ee68eMathias Agopian        return NULL;
2151f5762e646bed2290934280464832782766ee68eMathias Agopian    }
2161f5762e646bed2290934280464832782766ee68eMathias Agopian
2171f5762e646bed2290934280464832782766ee68eMathias Agopian    return newMap;
2181f5762e646bed2290934280464832782766ee68eMathias Agopian}
2191f5762e646bed2290934280464832782766ee68eMathias Agopian
2201f5762e646bed2290934280464832782766ee68eMathias Agopian/*
2211f5762e646bed2290934280464832782766ee68eMathias Agopian * Uncompress an entry, in its entirety, into the provided output buffer.
2221f5762e646bed2290934280464832782766ee68eMathias Agopian *
2231f5762e646bed2290934280464832782766ee68eMathias Agopian * This doesn't verify the data's CRC, which might be useful for
2241f5762e646bed2290934280464832782766ee68eMathias Agopian * uncompressed data.  The caller should be able to manage it.
2251f5762e646bed2290934280464832782766ee68eMathias Agopian */
226afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathbool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer, size_t size) const
2271f5762e646bed2290934280464832782766ee68eMathias Agopian{
228afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
229afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    const int32_t error = ExtractToMemory(mHandle, &(zipEntry->entry),
230afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        (uint8_t*) buffer, size);
231afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (error) {
232afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error));
2330d6c2d7b9db209d740992045dd3b842e52306598Kenny Root        return false;
2340d6c2d7b9db209d740992045dd3b842e52306598Kenny Root    }
2351f5762e646bed2290934280464832782766ee68eMathias Agopian
236afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    return true;
2371f5762e646bed2290934280464832782766ee68eMathias Agopian}
2381f5762e646bed2290934280464832782766ee68eMathias Agopian
2391f5762e646bed2290934280464832782766ee68eMathias Agopian/*
2401f5762e646bed2290934280464832782766ee68eMathias Agopian * Uncompress an entry, in its entirety, to an open file descriptor.
2411f5762e646bed2290934280464832782766ee68eMathias Agopian *
2421f5762e646bed2290934280464832782766ee68eMathias Agopian * This doesn't verify the data's CRC, but probably should.
2431f5762e646bed2290934280464832782766ee68eMathias Agopian */
2441f5762e646bed2290934280464832782766ee68eMathias Agopianbool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const
2451f5762e646bed2290934280464832782766ee68eMathias Agopian{
246afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
247afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    const int32_t error = ExtractEntryToFile(mHandle, &(zipEntry->entry), fd);
248afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (error) {
249afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error));
2500d6c2d7b9db209d740992045dd3b842e52306598Kenny Root        return false;
2510d6c2d7b9db209d740992045dd3b842e52306598Kenny Root    }
2521f5762e646bed2290934280464832782766ee68eMathias Agopian
253afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    return true;
2541f5762e646bed2290934280464832782766ee68eMathias Agopian}
255