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
4882e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackbornstatic Mutex gAssetLock;
4982e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackbornstatic int32_t gCount = 0;
5082e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackbornstatic Asset* gHead = NULL;
5182e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackbornstatic Asset* gTail = NULL;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t Asset::getGlobalCount()
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5582e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    AutoMutex _l(gAssetLock);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return gCount;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5982e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne HackbornString8 Asset::getAssetAllocations()
6082e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn{
6182e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    AutoMutex _l(gAssetLock);
6282e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    String8 res;
6382e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    Asset* cur = gHead;
6482e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    while (cur != NULL) {
6582e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        if (cur->isAllocated()) {
6682e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            res.append("    ");
6782e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            res.append(cur->getAssetSource());
68ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root            off64_t size = (cur->getLength()+512)/1024;
6982e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            char buf[64];
7082e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            sprintf(buf, ": %dK\n", (int)size);
7182e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn            res.append(buf);
7282e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        }
7382e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        cur = cur->mNext;
7482e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    }
7500adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn
7682e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    return res;
7782e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn}
7882e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset::Asset(void)
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mAccessMode(ACCESS_UNKNOWN)
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8282e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    AutoMutex _l(gAssetLock);
8382e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    gCount++;
8482e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    mNext = mPrev = NULL;
8582e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    if (gTail == NULL) {
8682e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        gHead = gTail = this;
8700adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn    } else {
8800adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn        mPrev = gTail;
8900adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn        gTail->mNext = this;
9000adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn        gTail = this;
9100adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn    }
926215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Creating Asset %p #%d\n", this, gCount);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAsset::~Asset(void)
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
9782e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    AutoMutex _l(gAssetLock);
9800adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn    gCount--;
9982e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    if (gHead == this) {
10082e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        gHead = mNext;
10182e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    }
10282e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    if (gTail == this) {
10382e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        gTail = mPrev;
10482e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    }
10582e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    if (mNext != NULL) {
10682e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        mNext->mPrev = mPrev;
10782e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    }
10882e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    if (mPrev != NULL) {
10982e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn        mPrev->mNext = mNext;
11082e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    }
11182e1ee93eece8fb0aec6acc3ef4ee7b1c86feec7Dianne Hackborn    mNext = mPrev = NULL;
1126215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    //ALOGI("Destroying Asset in %p #%d\n", this, gCount);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from a file on disk.  There is a fair chance that
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the file doesn't actually exist.
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can use "mode" to decide how we want to go about it.
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ Asset* Asset::createFromFile(const char* fileName, AccessMode mode)
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _FileAsset* pAsset;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
125ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t length;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fd = open(fileName, O_RDONLY | O_BINARY);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd < 0)
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Under Linux, the lseek fails if we actually opened a directory.  To
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be correct we should test the file type explicitly, but since we
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * always open things read-only it doesn't really matter, so there's
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no value in incurring the extra overhead of an fstat() call.
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
138ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    // TODO(kroot): replace this with fstat despite the plea above.
139ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#if 1
140ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    length = lseek64(fd, 0, SEEK_END);
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (length < 0) {
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(fd);
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
145ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    (void) lseek64(fd, 0, SEEK_SET);
146ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#else
147ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    struct stat st;
148ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (fstat(fd, &st) < 0) {
149ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        ::close(fd);
150ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return NULL;
151ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    }
152ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root
153ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (!S_ISREG(st.st_mode)) {
154ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        ::close(fd);
155ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return NULL;
156ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    }
157ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#endif
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _FileAsset;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(fileName, fd, 0, length);
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete pAsset;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from a compressed file on disk.  There is a fair chance
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that the file doesn't actually exist.
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We currently support gzip files.  We might want to handle .bz2 someday.
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ Asset* Asset::createFromCompressedFile(const char* fileName,
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessMode mode)
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _CompressedAsset* pAsset;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
182ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t fileLen;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool scanResult;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long offset;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int method;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long uncompressedLen, compressedLen;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fd = open(fileName, O_RDONLY | O_BINARY);
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd < 0)
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fileLen = lseek(fd, 0, SEEK_END);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fileLen < 0) {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(fd);
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    (void) lseek(fd, 0, SEEK_SET);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* want buffered I/O for the file scan; must dup so fclose() is safe */
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE* fp = fdopen(dup(fd), "rb");
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fp == NULL) {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(fd);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned long crc32;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    scanResult = ZipUtils::examineGzip(fp, &method, &uncompressedLen,
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    &compressedLen, &crc32);
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    offset = ftell(fp);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fclose(fp);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!scanResult) {
2135baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("File '%s' is not in gzip format\n", fileName);
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(fd);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _CompressedAsset;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(fd, offset, method, uncompressedLen,
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                compressedLen);
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR) {
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete pAsset;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from part of an open file.
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
235ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root/*static*/ Asset* Asset::createFromFileSegment(int fd, off64_t offset,
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t length, AccessMode mode)
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _FileAsset* pAsset;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _FileAsset;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(NULL, fd, offset, length);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR)
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from compressed data in an open file.
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
253ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root/*static*/ Asset* Asset::createFromCompressedData(int fd, off64_t offset,
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int compressionMethod, size_t uncompressedLen, size_t compressedLen,
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessMode mode)
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _CompressedAsset* pAsset;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _CompressedAsset;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(fd, offset, compressionMethod,
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                uncompressedLen, compressedLen);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR)
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from a memory mapping.
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ Asset* Asset::createFromUncompressedMap(FileMap* dataMap,
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessMode mode)
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _FileAsset* pAsset;
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _FileAsset;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(dataMap);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR)
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new Asset from compressed data in a memory mapping.
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*static*/ Asset* Asset::createFromCompressedMap(FileMap* dataMap,
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int method, size_t uncompressedLen, AccessMode mode)
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    _CompressedAsset* pAsset;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset = new _CompressedAsset;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = pAsset->openChunk(dataMap, method, uncompressedLen);
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR)
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pAsset->mAccessMode = mode;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pAsset;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Do generic seek() housekeeping.  Pass in the offset/whence values from
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the seek request, along with the current chunk offset and the chunk
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * length.
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the new chunk offset, or -1 if the seek is illegal.
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
315ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootoff64_t Asset::handleSeek(off64_t offset, int whence, off64_t curPosn, off64_t maxPosn)
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
317ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t newOffset;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    switch (whence) {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    case SEEK_SET:
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        newOffset = offset;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        break;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    case SEEK_CUR:
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        newOffset = curPosn + offset;
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        break;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    case SEEK_END:
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        newOffset = maxPosn + offset;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        break;
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    default:
3308564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("unexpected whence %d\n", whence);
331ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        // this was happening due to an off64_t size mismatch
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(false);
333ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return (off64_t) -1;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (newOffset < 0 || newOffset > maxPosn) {
3378564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("seek out of range: want %ld, end=%ld\n",
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (long) newOffset, (long) maxPosn);
339ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return (off64_t) -1;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return newOffset;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      _FileAsset
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor.
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project_FileAsset::_FileAsset(void)
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mStart(0), mLength(0), mOffset(0), mFp(NULL), mFileName(NULL), mMap(NULL), mBuf(NULL)
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Destructor.  Release resources.
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project_FileAsset::~_FileAsset(void)
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close();
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Operate on a chunk of an uncompressed file.
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Zero-length chunks are allowed.
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
373ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootstatus_t _FileAsset::openChunk(const char* fileName, int fd, off64_t offset, size_t length)
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFp == NULL);    // no reopen
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mMap == NULL);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(fd >= 0);
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(offset >= 0);
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Seek to end to get file length.
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
383ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t fileLength;
384ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    fileLength = lseek64(fd, 0, SEEK_END);
385ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (fileLength == (off64_t) -1) {
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // probably a bad file descriptor
3875baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("failed lseek (errno=%d)\n", errno);
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
391ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if ((off64_t) (offset + length) > fileLength) {
3925baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("start (%ld) + len (%ld) > end (%ld)\n",
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (long) offset, (long) length, (long) fileLength);
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return BAD_INDEX;
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* after fdopen, the fd will be closed on fclose() */
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFp = fdopen(fd, "rb");
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFp == NULL)
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStart = offset;
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mLength = length;
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset == 0);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* seek the FILE* to the start of chunk */
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fseek(mFp, mStart, SEEK_SET) != 0) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(false);
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFileName = fileName != NULL ? strdup(fileName) : NULL;
41200adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create the chunk from the map.
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t _FileAsset::openChunk(FileMap* dataMap)
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFp == NULL);    // no reopen
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mMap == NULL);
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(dataMap != NULL);
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mMap = dataMap;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStart = -1;            // not used
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mLength = dataMap->getDataLength();
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset == 0);
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Read a chunk of data.
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectssize_t _FileAsset::read(void* buf, size_t count)
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t maxLen;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t actual;
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset >= 0 && mOffset <= mLength);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (getAccessMode() == ACCESS_BUFFER) {
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * On first access, read or map the entire file.  The caller has
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * requested buffer access, either because they're going to be
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * using the buffer or because what they're doing has appropriate
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * performance needs and access patterns.
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBuf == NULL)
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            getBuffer(false);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* adjust count if we're near EOF */
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    maxLen = mLength - mOffset;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (count > maxLen)
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        count = maxLen;
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!count)
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* copy from mapped area */
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("map read\n");
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(buf, (char*)mMap->getDataPtr() + mOffset, count);
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        actual = count;
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (mBuf != NULL) {
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* copy from buffer */
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("buf read\n");
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(buf, (char*)mBuf + mOffset, count);
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        actual = count;
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* read from the file */
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //printf("file read\n");
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ftell(mFp) != mStart + mOffset) {
4763762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("Hosed: %ld != %ld+%ld\n",
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ftell(mFp), (long) mStart, (long) mOffset);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            assert(false);
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This returns 0 on error or eof.  We need to use ferror() or feof()
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to tell the difference, but we don't currently have those on the
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * device.  However, we know how much data is *supposed* to be in the
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * file, so if we don't read the full amount we know something is
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * hosed.
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        actual = fread(buf, 1, count, mFp);
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (actual == 0)        // something failed -- I/O error?
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(actual == count);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mOffset += actual;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return actual;
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Seek to a new position.
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
502ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootoff64_t _FileAsset::seek(off64_t offset, int whence)
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
504ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t newPosn;
505ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t actualOffset;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // compute new position within chunk
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    newPosn = handleSeek(offset, whence, mOffset, mLength);
509ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (newPosn == (off64_t) -1)
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return newPosn;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
512ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    actualOffset = mStart + newPosn;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFp != NULL) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fseek(mFp, (long) actualOffset, SEEK_SET) != 0)
516ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root            return (off64_t) -1;
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mOffset = actualOffset - mStart;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mOffset;
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close the asset.
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid _FileAsset::close(void)
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMap->release();
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMap = NULL;
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mBuf != NULL) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete[] mBuf;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBuf = NULL;
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFileName != NULL) {
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        free(mFileName);
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFileName = NULL;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
54100adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFp != NULL) {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // can only be NULL when called from destructor
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // (otherwise we would never return this object)
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fclose(mFp);
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFp = NULL;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a read-only pointer to a buffer.
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can either read the whole thing in or map the relevant piece of
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the source file.  Ideally a map would be established at a higher
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * level and we'd be using a different object, but we didn't, so we
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * deal with it here.
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst void* _FileAsset::getBuffer(bool wordAligned)
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* subsequent requests just use what we did previously */
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mBuf != NULL)
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBuf;
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!wordAligned) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return  mMap->getDataPtr();
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ensureAlignment(mMap);
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFp != NULL);
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mLength < kReadVsMapThreshold) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unsigned char* buf;
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long allocLen;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* zero-length files are allowed; not sure about zero-len allocs */
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* (works fine with gcc + x86linux) */
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        allocLen = mLength;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLength == 0)
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            allocLen = 1;
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        buf = new unsigned char[allocLen];
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (buf == NULL) {
5843762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("alloc of %ld bytes failed\n", (long) allocLen);
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NULL;
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
58871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Asset %p allocating buffer size %d (smaller than threshold)", this, (int)allocLen);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLength > 0) {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long oldPosn = ftell(mFp);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fseek(mFp, mStart, SEEK_SET);
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (fread(buf, 1, mLength, mFp) != (size_t) mLength) {
5933762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("failed reading %ld bytes\n", (long) mLength);
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delete[] buf;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return NULL;
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fseek(mFp, oldPosn, SEEK_SET);
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
60071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV(" getBuffer: loaded into buffer\n");
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBuf = buf;
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBuf;
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FileMap* map;
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        map = new FileMap;
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!map->create(NULL, fileno(mFp), mStart, mLength, true)) {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            map->release();
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NULL;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
61371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV(" getBuffer: mapped\n");
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMap = map;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!wordAligned) {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return  mMap->getDataPtr();
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ensureAlignment(mMap);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
623ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootint _FileAsset::openFileDescriptor(off64_t* outStart, off64_t* outLength) const
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* fname = mMap->getFileName();
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fname == NULL) {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fname = mFileName;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fname == NULL) {
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *outStart = mMap->getDataOffset();
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *outLength = mMap->getDataLength();
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return open(fname, O_RDONLY | O_BINARY);
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFileName == NULL) {
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *outStart = mStart;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *outLength = mLength;
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return open(mFileName, O_RDONLY | O_BINARY);
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst void* _FileAsset::ensureAlignment(FileMap* map)
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* data = map->getDataPtr();
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((((size_t)data)&0x3) == 0) {
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We can return this directly if it is aligned on a word
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // boundary.
65171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Returning aligned FileAsset %p (%s).", this,
65278c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn                getAssetSource());
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return data;
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // If not aligned on a word boundary, then we need to copy it into
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // our own buffer.
65771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Copying FileAsset %p (%s) to buffer size %d to make it aligned.", this,
65878c405178c57bb45e40f1e2839d6a18d91f7f02cDianne Hackborn            getAssetSource(), (int)mLength);
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned char* buf = new unsigned char[mLength];
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (buf == NULL) {
6613762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("alloc of %ld bytes failed\n", (long) mLength);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memcpy(buf, data, mLength);
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mBuf = buf;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return buf;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      _CompressedAsset
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ===========================================================================
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor.
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project_CompressedAsset::_CompressedAsset(void)
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mStart(0), mCompressedLen(0), mUncompressedLen(0), mOffset(0),
680b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate      mMap(NULL), mFd(-1), mZipInflater(NULL), mBuf(NULL)
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Destructor.  Release resources.
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project_CompressedAsset::~_CompressedAsset(void)
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close();
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a chunk of compressed data inside a file.
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This currently just sets up some values and returns.  On the first
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * read, we expand the entire file into a buffer and return data from it.
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
698ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootstatus_t _CompressedAsset::openChunk(int fd, off64_t offset,
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int compressionMethod, size_t uncompressedLen, size_t compressedLen)
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFd < 0);        // no re-open
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mMap == NULL);
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(fd >= 0);
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(offset >= 0);
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(compressedLen > 0);
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (compressionMethod != ZipFileRO::kCompressDeflated) {
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(false);
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStart = offset;
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCompressedLen = compressedLen;
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mUncompressedLen = uncompressedLen;
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset == 0);
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFd = fd;
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mBuf == NULL);
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    if (uncompressedLen > StreamingZipInflater::OUTPUT_CHUNK_SIZE) {
720b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        mZipInflater = new StreamingZipInflater(mFd, offset, uncompressedLen, compressedLen);
721b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    }
722b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a chunk of compressed data in a mapped region.
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Nothing is expanded until the first read call.
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t _CompressedAsset::openChunk(FileMap* dataMap, int compressionMethod,
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t uncompressedLen)
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mFd < 0);        // no re-open
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mMap == NULL);
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(dataMap != NULL);
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (compressionMethod != ZipFileRO::kCompressDeflated) {
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(false);
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mMap = dataMap;
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStart = -1;        // not used
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCompressedLen = dataMap->getDataLength();
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mUncompressedLen = uncompressedLen;
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset == 0);
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    if (uncompressedLen > StreamingZipInflater::OUTPUT_CHUNK_SIZE) {
750b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        mZipInflater = new StreamingZipInflater(dataMap, uncompressedLen);
751b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    }
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Read data from a chunk of compressed data.
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * [For now, that's just copying data out of a buffer.]
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectssize_t _CompressedAsset::read(void* buf, size_t count)
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t maxLen;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t actual;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assert(mOffset >= 0 && mOffset <= mUncompressedLen);
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
767b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    /* If we're relying on a streaming inflater, go through that */
768b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    if (mZipInflater) {
769b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        actual = mZipInflater->read(buf, count);
770b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    } else {
771b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        if (mBuf == NULL) {
772b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate            if (getBuffer(false) == NULL)
773b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate                return -1;
774b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        }
775b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        assert(mBuf != NULL);
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
777b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        /* adjust count if we're near EOF */
778b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        maxLen = mUncompressedLen - mOffset;
779b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        if (count > maxLen)
780b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate            count = maxLen;
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
782b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        if (!count)
783b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate            return 0;
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
785b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        /* copy from buffer */
786b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        //printf("comp buf read\n");
787b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        memcpy(buf, (char*)mBuf + mOffset, count);
788b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        actual = count;
789b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    }
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mOffset += actual;
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return actual;
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle a seek request.
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If we're working in a streaming mode, this is going to be fairly
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expensive, because it requires plowing through a bunch of compressed
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data.
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
802ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Rootoff64_t _CompressedAsset::seek(off64_t offset, int whence)
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
804ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    off64_t newPosn;
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // compute new position within chunk
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    newPosn = handleSeek(offset, whence, mOffset, mUncompressedLen);
808ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root    if (newPosn == (off64_t) -1)
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return newPosn;
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
811b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    if (mZipInflater) {
812b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate        mZipInflater->seekAbsolute(newPosn);
813b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    }
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mOffset = newPosn;
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mOffset;
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close the asset.
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid _CompressedAsset::close(void)
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMap->release();
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMap = NULL;
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
827b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate
828b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    delete[] mBuf;
829b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    mBuf = NULL;
830b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate
831b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    delete mZipInflater;
832b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    mZipInflater = NULL;
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mFd > 0) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ::close(mFd);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFd = -1;
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a pointer to a read-only buffer of data.
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The first time this is called, we expand the compressed data into a
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * buffer.
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
846afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathconst void* _CompressedAsset::getBuffer(bool)
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned char* buf = NULL;
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mBuf != NULL)
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBuf;
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Allocate a buffer and read the file into it.
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf = new unsigned char[mUncompressedLen];
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (buf == NULL) {
8588564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("alloc %ld bytes failed\n", (long) mUncompressedLen);
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mMap != NULL) {
863afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        if (!ZipUtils::inflateToBuffer(mMap->getDataPtr(), buf,
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mUncompressedLen, mCompressedLen))
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert(mFd >= 0);
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Seek to the start of the compressed data.
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lseek(mFd, mStart, SEEK_SET) != mStart)
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Expand the data into it.
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ZipUtils::inflateToBuffer(mFd, buf, mUncompressedLen,
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCompressedLen))
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
883b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    /*
884b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate     * Success - now that we have the full asset in RAM we
885b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate     * no longer need the streaming inflater
886b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate     */
887b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    delete mZipInflater;
888b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate    mZipInflater = NULL;
889b100cbf178e91d6652ebbad3ed36684cacb9d10eChristopher Tate
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mBuf = buf;
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf = NULL;
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete[] buf;
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mBuf;
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
898