19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Provide access to a read-only asset.
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "asset"
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define NDEBUG 0
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/Asset.h>
25b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/StreamingZipInflater.h>
261f5762e646bed2290934280464832782766ee68eMathias Agopian#include <androidfw/ZipFileRO.h>
271f5762e646bed2290934280464832782766ee68eMathias Agopian#include <androidfw/ZipUtils.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/FileMap.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
3182e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn#include <utils/threads.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h>
34b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <errno.h>
35b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <fcntl.h>
36b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <memory.h>
37b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <string.h>
38ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#include <sys/stat.h>
39ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#include <sys/types.h>
40b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <unistd.h>
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifndef O_BINARY
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project# define O_BINARY 0
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
482204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampestatic const bool kIsDebug = false;
492204f0bf56af53b588a01701b8cf9cd05b1b3ff9Andreas Gampe
5082e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackbornstatic Mutex gAssetLock;
5182e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackbornstatic int32_t gCount = 0;
5282e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackbornstatic Asset* gHead = NULL;
5382e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackbornstatic Asset* gTail = NULL;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
552582465bb437d3700b846fe66416f1c650e9345cAdam Lesinskivoid Asset::registerAsset(Asset* asset)
562582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski{
572582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    AutoMutex _l(gAssetLock);
582582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    gCount++;
592582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    asset->mNext = asset->mPrev = NULL;
602582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    if (gTail == NULL) {
612582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        gHead = gTail = asset;
622582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    } else {
632582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        asset->mPrev = gTail;
642582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        gTail->mNext = asset;
652582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        gTail = asset;
662582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    }
672582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski
682582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    if (kIsDebug) {
692582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        ALOGI("Creating Asset %p #%d\n", asset, gCount);
702582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    }
712582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski}
722582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski
732582465bb437d3700b846fe66416f1c650e9345cAdam Lesinskivoid Asset::unregisterAsset(Asset* asset)
742582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski{
752582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    AutoMutex _l(gAssetLock);
762582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    gCount--;
772582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    if (gHead == asset) {
782582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        gHead = asset->mNext;
792582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    }
802582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    if (gTail == asset) {
812582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        gTail = asset->mPrev;
822582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    }
832582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    if (asset->mNext != NULL) {
842582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        asset->mNext->mPrev = asset->mPrev;
852582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    }
862582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    if (asset->mPrev != NULL) {
872582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        asset->mPrev->mNext = asset->mNext;
882582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    }
892582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    asset->mNext = asset->mPrev = NULL;
902582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski
912582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    if (kIsDebug) {
922582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski        ALOGI("Destroying Asset in %p #%d\n", asset, gCount);
932582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    }
942582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski}
952582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t Asset::getGlobalCount()
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
9882e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    AutoMutex _l(gAssetLock);
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return gCount;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10282e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne HackbornString8 Asset::getAssetAllocations()
10382e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn{
10482e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    AutoMutex _l(gAssetLock);
10582e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    String8 res;
10682e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    Asset* cur = gHead;
10782e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    while (cur != NULL) {
10882e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        if (cur->isAllocated()) {
10982e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            res.append("    ");
11082e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            res.append(cur->getAssetSource());
111ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root            off64_t size = (cur->getLength()+512)/1024;
11282e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            char buf[64];
11382e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            sprintf(buf, ": %dK\n", (int)size);
11482e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            res.append(buf);
11582e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        }
11682e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        cur = cur->mNext;
11782e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    }
11800adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn
11982e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    return res;
12082e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn}
12182e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset::Asset(void)
1232582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    : mAccessMode(ACCESS_UNKNOWN), mNext(NULL), mPrev(NULL)
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from a file on disk.  There is a fair chance that
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the file doesn't actually exist.
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can use "mode" to decide how we want to go about it.
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ Asset* Asset::createFromFile(const char* fileName, AccessMode mode)
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _FileAsset* pAsset;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
137ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t length;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fd = open(fileName, O_RDONLY | O_BINARY);
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd < 0)
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Under Linux, the lseek fails if we actually opened a directory.  To
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be correct we should test the file type explicitly, but since we
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * always open things read-only it doesn't really matter, so there's
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no value in incurring the extra overhead of an fstat() call.
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
150ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    // TODO(kroot): replace this with fstat despite the plea above.
151ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#if 1
152ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    length = lseek64(fd, 0, SEEK_END);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (length < 0) {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(fd);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
157ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    (void) lseek64(fd, 0, SEEK_SET);
158ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#else
159ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    struct stat st;
160ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (fstat(fd, &st) < 0) {
161ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        ::close(fd);
162ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return NULL;
163ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    }
164ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root
165ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (!S_ISREG(st.st_mode)) {
166ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        ::close(fd);
167ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return NULL;
168ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    }
169ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#endif
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _FileAsset;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(fileName, fd, 0, length);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete pAsset;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from a compressed file on disk.  There is a fair chance
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that the file doesn't actually exist.
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We currently support gzip files.  We might want to handle .bz2 someday.
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ Asset* Asset::createFromCompressedFile(const char* fileName,
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessMode mode)
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _CompressedAsset* pAsset;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
194ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t fileLen;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool scanResult;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long offset;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int method;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long uncompressedLen, compressedLen;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fd = open(fileName, O_RDONLY | O_BINARY);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd < 0)
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fileLen = lseek(fd, 0, SEEK_END);
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fileLen < 0) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(fd);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    (void) lseek(fd, 0, SEEK_SET);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* want buffered I/O for the file scan; must dup so fclose() is safe */
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE* fp = fdopen(dup(fd), "rb");
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fp == NULL) {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(fd);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned long crc32;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    scanResult = ZipUtils::examineGzip(fp, &method, &uncompressedLen,
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    &compressedLen, &crc32);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    offset = ftell(fp);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fclose(fp);
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!scanResult) {
2255baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("File '%s' is not in gzip format\n", fileName);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(fd);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _CompressedAsset;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(fd, offset, method, uncompressedLen,
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                compressedLen);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete pAsset;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from part of an open file.
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
247ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root/*static*/ Asset* Asset::createFromFileSegment(int fd, off64_t offset,
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t length, AccessMode mode)
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _FileAsset* pAsset;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _FileAsset;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(NULL, fd, offset, length);
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR)
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from compressed data in an open file.
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
265ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root/*static*/ Asset* Asset::createFromCompressedData(int fd, off64_t offset,
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int compressionMethod, size_t uncompressedLen, size_t compressedLen,
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessMode mode)
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _CompressedAsset* pAsset;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _CompressedAsset;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(fd, offset, compressionMethod,
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                uncompressedLen, compressedLen);
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR)
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from a memory mapping.
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ Asset* Asset::createFromUncompressedMap(FileMap* dataMap,
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessMode mode)
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _FileAsset* pAsset;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _FileAsset;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(dataMap);
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR)
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from compressed data in a memory mapping.
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ Asset* Asset::createFromCompressedMap(FileMap* dataMap,
3054600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath    size_t uncompressedLen, AccessMode mode)
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _CompressedAsset* pAsset;
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _CompressedAsset;
3114600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath    result = pAsset->openChunk(dataMap, uncompressedLen);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR)
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Do generic seek() housekeeping.  Pass in the offset/whence values from
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the seek request, along with the current chunk offset and the chunk
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * length.
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the new chunk offset, or -1 if the seek is illegal.
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
327ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootoff64_t Asset::handleSeek(off64_t offset, int whence, off64_t curPosn, off64_t maxPosn)
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
329ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t newOffset;
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    switch (whence) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    case SEEK_SET:
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        newOffset = offset;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        break;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    case SEEK_CUR:
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        newOffset = curPosn + offset;
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        break;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    case SEEK_END:
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        newOffset = maxPosn + offset;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        break;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    default:
3428564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("unexpected whence %d\n", whence);
343ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        // this was happening due to an off64_t size mismatch
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(false);
345ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return (off64_t) -1;
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (newOffset < 0 || newOffset > maxPosn) {
3498564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("seek out of range: want %ld, end=%ld\n",
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (long) newOffset, (long) maxPosn);
351ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return (off64_t) -1;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return newOffset;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      _FileAsset
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project_FileAsset::_FileAsset(void)
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mStart(0), mLength(0), mOffset(0), mFp(NULL), mFileName(NULL), mMap(NULL), mBuf(NULL)
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3702582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    // Register the Asset with the global list here after it is fully constructed and its
3712582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    // vtable pointer points to this concrete type. b/31113965
3722582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    registerAsset(this);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Destructor.  Release resources.
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project_FileAsset::~_FileAsset(void)
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close();
3812582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski
3822582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    // Unregister the Asset from the global list here before it is destructed and while its vtable
3832582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    // pointer still points to this concrete type. b/31113965
3842582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    unregisterAsset(this);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Operate on a chunk of an uncompressed file.
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Zero-length chunks are allowed.
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
392ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootstatus_t _FileAsset::openChunk(const char* fileName, int fd, off64_t offset, size_t length)
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFp == NULL);    // no reopen
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mMap == NULL);
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(fd >= 0);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(offset >= 0);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Seek to end to get file length.
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
402ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t fileLength;
403ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    fileLength = lseek64(fd, 0, SEEK_END);
404ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (fileLength == (off64_t) -1) {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // probably a bad file descriptor
4065baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("failed lseek (errno=%d)\n", errno);
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
410ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if ((off64_t) (offset + length) > fileLength) {
4115baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("start (%ld) + len (%ld) > end (%ld)\n",
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (long) offset, (long) length, (long) fileLength);
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return BAD_INDEX;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* after fdopen, the fd will be closed on fclose() */
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFp = fdopen(fd, "rb");
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFp == NULL)
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStart = offset;
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mLength = length;
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset == 0);
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* seek the FILE* to the start of chunk */
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fseek(mFp, mStart, SEEK_SET) != 0) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(false);
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFileName = fileName != NULL ? strdup(fileName) : NULL;
43100adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create the chunk from the map.
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t _FileAsset::openChunk(FileMap* dataMap)
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFp == NULL);    // no reopen
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mMap == NULL);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(dataMap != NULL);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mMap = dataMap;
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStart = -1;            // not used
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mLength = dataMap->getDataLength();
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset == 0);
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Read a chunk of data.
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectssize_t _FileAsset::read(void* buf, size_t count)
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t maxLen;
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t actual;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset >= 0 && mOffset <= mLength);
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (getAccessMode() == ACCESS_BUFFER) {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * On first access, read or map the entire file.  The caller has
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * requested buffer access, either because they're going to be
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * using the buffer or because what they're doing has appropriate
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * performance needs and access patterns.
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBuf == NULL)
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            getBuffer(false);
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* adjust count if we're near EOF */
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    maxLen = mLength - mOffset;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (count > maxLen)
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        count = maxLen;
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!count)
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* copy from mapped area */
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("map read\n");
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(buf, (char*)mMap->getDataPtr() + mOffset, count);
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        actual = count;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (mBuf != NULL) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* copy from buffer */
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("buf read\n");
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(buf, (char*)mBuf + mOffset, count);
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        actual = count;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* read from the file */
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("file read\n");
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ftell(mFp) != mStart + mOffset) {
4953762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("Hosed: %ld != %ld+%ld\n",
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ftell(mFp), (long) mStart, (long) mOffset);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            assert(false);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This returns 0 on error or eof.  We need to use ferror() or feof()
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to tell the difference, but we don't currently have those on the
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * device.  However, we know how much data is *supposed* to be in the
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * file, so if we don't read the full amount we know something is
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * hosed.
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        actual = fread(buf, 1, count, mFp);
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (actual == 0)        // something failed -- I/O error?
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(actual == count);
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mOffset += actual;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return actual;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Seek to a new position.
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
521ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootoff64_t _FileAsset::seek(off64_t offset, int whence)
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
523ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t newPosn;
524ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t actualOffset;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // compute new position within chunk
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    newPosn = handleSeek(offset, whence, mOffset, mLength);
528ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (newPosn == (off64_t) -1)
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return newPosn;
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
531ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    actualOffset = mStart + newPosn;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFp != NULL) {
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fseek(mFp, (long) actualOffset, SEEK_SET) != 0)
535ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root            return (off64_t) -1;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mOffset = actualOffset - mStart;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mOffset;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close the asset.
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid _FileAsset::close(void)
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
548688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath        delete mMap;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMap = NULL;
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mBuf != NULL) {
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete[] mBuf;
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBuf = NULL;
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFileName != NULL) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        free(mFileName);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFileName = NULL;
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
56000adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFp != NULL) {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // can only be NULL when called from destructor
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // (otherwise we would never return this object)
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fclose(mFp);
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFp = NULL;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a read-only pointer to a buffer.
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can either read the whole thing in or map the relevant piece of
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the source file.  Ideally a map would be established at a higher
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * level and we'd be using a different object, but we didn't, so we
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * deal with it here.
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst void* _FileAsset::getBuffer(bool wordAligned)
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* subsequent requests just use what we did previously */
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mBuf != NULL)
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBuf;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!wordAligned) {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return  mMap->getDataPtr();
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ensureAlignment(mMap);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFp != NULL);
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mLength < kReadVsMapThreshold) {
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unsigned char* buf;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long allocLen;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* zero-length files are allowed; not sure about zero-len allocs */
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* (works fine with gcc + x86linux) */
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        allocLen = mLength;
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLength == 0)
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            allocLen = 1;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        buf = new unsigned char[allocLen];
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (buf == NULL) {
6033762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("alloc of %ld bytes failed\n", (long) allocLen);
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NULL;
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
60771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Asset %p allocating buffer size %d (smaller than threshold)", this, (int)allocLen);
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLength > 0) {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long oldPosn = ftell(mFp);
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fseek(mFp, mStart, SEEK_SET);
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (fread(buf, 1, mLength, mFp) != (size_t) mLength) {
6123762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("failed reading %ld bytes\n", (long) mLength);
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delete[] buf;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return NULL;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fseek(mFp, oldPosn, SEEK_SET);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
61971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV(" getBuffer: loaded into buffer\n");
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBuf = buf;
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBuf;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FileMap* map;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        map = new FileMap;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!map->create(NULL, fileno(mFp), mStart, mLength, true)) {
628688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath            delete map;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NULL;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
63271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV(" getBuffer: mapped\n");
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMap = map;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!wordAligned) {
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return  mMap->getDataPtr();
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ensureAlignment(mMap);
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
642ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootint _FileAsset::openFileDescriptor(off64_t* outStart, off64_t* outLength) const
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* fname = mMap->getFileName();
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fname == NULL) {
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fname = mFileName;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fname == NULL) {
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *outStart = mMap->getDataOffset();
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *outLength = mMap->getDataLength();
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return open(fname, O_RDONLY | O_BINARY);
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFileName == NULL) {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *outStart = mStart;
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *outLength = mLength;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return open(mFileName, O_RDONLY | O_BINARY);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst void* _FileAsset::ensureAlignment(FileMap* map)
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* data = map->getDataPtr();
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((((size_t)data)&0x3) == 0) {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We can return this directly if it is aligned on a word
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // boundary.
67071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Returning aligned FileAsset %p (%s).", this,
67178c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                getAssetSource());
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return data;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // If not aligned on a word boundary, then we need to copy it into
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // our own buffer.
67671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Copying FileAsset %p (%s) to buffer size %d to make it aligned.", this,
67778c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            getAssetSource(), (int)mLength);
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned char* buf = new unsigned char[mLength];
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (buf == NULL) {
6803762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("alloc of %ld bytes failed\n", (long) mLength);
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memcpy(buf, data, mLength);
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mBuf = buf;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return buf;
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      _CompressedAsset
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor.
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project_CompressedAsset::_CompressedAsset(void)
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mStart(0), mCompressedLen(0), mUncompressedLen(0), mOffset(0),
699b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate      mMap(NULL), mFd(-1), mZipInflater(NULL), mBuf(NULL)
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7012582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    // Register the Asset with the global list here after it is fully constructed and its
7022582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    // vtable pointer points to this concrete type. b/31113965
7032582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    registerAsset(this);
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Destructor.  Release resources.
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project_CompressedAsset::~_CompressedAsset(void)
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close();
7122582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski
7132582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    // Unregister the Asset from the global list here before it is destructed and while its vtable
7142582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    // pointer still points to this concrete type. b/31113965
7152582465bb437d3700b846fe66416f1c650e9345cAdam Lesinski    unregisterAsset(this);
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a chunk of compressed data inside a file.
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This currently just sets up some values and returns.  On the first
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * read, we expand the entire file into a buffer and return data from it.
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
724ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootstatus_t _CompressedAsset::openChunk(int fd, off64_t offset,
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int compressionMethod, size_t uncompressedLen, size_t compressedLen)
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFd < 0);        // no re-open
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mMap == NULL);
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(fd >= 0);
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(offset >= 0);
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(compressedLen > 0);
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (compressionMethod != ZipFileRO::kCompressDeflated) {
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(false);
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStart = offset;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCompressedLen = compressedLen;
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mUncompressedLen = uncompressedLen;
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset == 0);
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFd = fd;
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mBuf == NULL);
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
745b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    if (uncompressedLen > StreamingZipInflater::OUTPUT_CHUNK_SIZE) {
746b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        mZipInflater = new StreamingZipInflater(mFd, offset, uncompressedLen, compressedLen);
747b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    }
748b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a chunk of compressed data in a mapped region.
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Nothing is expanded until the first read call.
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7574600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamathstatus_t _CompressedAsset::openChunk(FileMap* dataMap, size_t uncompressedLen)
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFd < 0);        // no re-open
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mMap == NULL);
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(dataMap != NULL);
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mMap = dataMap;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStart = -1;        // not used
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCompressedLen = dataMap->getDataLength();
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mUncompressedLen = uncompressedLen;
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset == 0);
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    if (uncompressedLen > StreamingZipInflater::OUTPUT_CHUNK_SIZE) {
770b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        mZipInflater = new StreamingZipInflater(dataMap, uncompressedLen);
771b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    }
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Read data from a chunk of compressed data.
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * [For now, that's just copying data out of a buffer.]
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectssize_t _CompressedAsset::read(void* buf, size_t count)
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t maxLen;
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t actual;
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset >= 0 && mOffset <= mUncompressedLen);
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
787b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    /* If we're relying on a streaming inflater, go through that */
788b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    if (mZipInflater) {
789b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        actual = mZipInflater->read(buf, count);
790b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    } else {
791b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        if (mBuf == NULL) {
792b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate            if (getBuffer(false) == NULL)
793b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate                return -1;
794b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        }
795b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        assert(mBuf != NULL);
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
797b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        /* adjust count if we're near EOF */
798b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        maxLen = mUncompressedLen - mOffset;
799b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        if (count > maxLen)
800b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate            count = maxLen;
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
802b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        if (!count)
803b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate            return 0;
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
805b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        /* copy from buffer */
806b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        //printf("comp buf read\n");
807b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        memcpy(buf, (char*)mBuf + mOffset, count);
808b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        actual = count;
809b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    }
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mOffset += actual;
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return actual;
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle a seek request.
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If we're working in a streaming mode, this is going to be fairly
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expensive, because it requires plowing through a bunch of compressed
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data.
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
822ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootoff64_t _CompressedAsset::seek(off64_t offset, int whence)
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
824ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t newPosn;
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // compute new position within chunk
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    newPosn = handleSeek(offset, whence, mOffset, mUncompressedLen);
828ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (newPosn == (off64_t) -1)
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return newPosn;
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
831b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    if (mZipInflater) {
832b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        mZipInflater->seekAbsolute(newPosn);
833b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    }
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mOffset = newPosn;
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mOffset;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close the asset.
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid _CompressedAsset::close(void)
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
844688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath        delete mMap;
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMap = NULL;
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
847b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate
848b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    delete[] mBuf;
849b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    mBuf = NULL;
850b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate
851b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    delete mZipInflater;
852b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    mZipInflater = NULL;
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFd > 0) {
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(mFd);
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFd = -1;
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a pointer to a read-only buffer of data.
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The first time this is called, we expand the compressed data into a
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * buffer.
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
866afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathconst void* _CompressedAsset::getBuffer(bool)
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned char* buf = NULL;
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mBuf != NULL)
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBuf;
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Allocate a buffer and read the file into it.
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf = new unsigned char[mUncompressedLen];
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (buf == NULL) {
8788564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("alloc %ld bytes failed\n", (long) mUncompressedLen);
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
883afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        if (!ZipUtils::inflateToBuffer(mMap->getDataPtr(), buf,
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mUncompressedLen, mCompressedLen))
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(mFd >= 0);
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Seek to the start of the compressed data.
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lseek(mFd, mStart, SEEK_SET) != mStart)
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Expand the data into it.
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ZipUtils::inflateToBuffer(mFd, buf, mUncompressedLen,
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCompressedLen))
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
903b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    /*
904b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate     * Success - now that we have the full asset in RAM we
905b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate     * no longer need the streaming inflater
906b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate     */
907b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    delete mZipInflater;
908b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    mZipInflater = NULL;
909b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mBuf = buf;
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf = NULL;
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete[] buf;
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mBuf;
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
918