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