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// Access to Zip archives. 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "zip" 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 238ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian#include <utils/Log.h> 24a982dc05d7ca919c07f50e446549ef9dceadf6bdColin Cross#include <utils/ZipUtils.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2655e3d60da5626752ffe1d15150d35ccb8fa644e7Mathias Agopian#include "ZipFile.h" 2755e3d60da5626752ffe1d15150d35ccb8fa644e7Mathias Agopian 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <zlib.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DEF_MEM_LEVEL 8 // normally in zutil.h? 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <memory.h> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h> 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Some environments require the "b", some choke on it. 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FILE_OPEN_RO "rb" 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FILE_OPEN_RW "r+b" 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FILE_OPEN_RW_CREATE "w+b" 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* should live somewhere else? */ 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic status_t errnoToStatus(int err) 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == ENOENT) 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NAME_NOT_FOUND; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (err == EACCES) 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return PERMISSION_DENIED; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open a file and parse its guts. 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::open(const char* zipFileName, int flags) 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool newArchive = false; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mZipFp == NULL); // no reopen 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & kOpenTruncate)) 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flags |= kOpenCreate; // trunc implies create 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & kOpenReadOnly) && (flags & kOpenReadWrite)) 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; // not both 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!((flags & kOpenReadOnly) || (flags & kOpenReadWrite))) 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; // not neither 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & kOpenCreate) && !(flags & kOpenReadWrite)) 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; // create requires write 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flags & kOpenTruncate) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newArchive = true; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newArchive = (access(zipFileName, F_OK) != 0); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!(flags & kOpenCreate) && newArchive) { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* not creating, must already exist */ 815baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("File %s does not exist", zipFileName); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NAME_NOT_FOUND; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* open the file */ 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* openflags; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flags & kOpenReadWrite) { 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newArchive) 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project openflags = FILE_OPEN_RW_CREATE; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project openflags = FILE_OPEN_RW; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project openflags = FILE_OPEN_RO; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mZipFp = fopen(zipFileName, openflags); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mZipFp == NULL) { 98e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen int err = errno; 995baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("fopen failed: %d\n", err); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return errnoToStatus(err); 101e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t result; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!newArchive) { 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Load the central directory. If that fails, then this probably 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * isn't a Zip archive. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = readCentralDir(); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Newly-created. The EndOfCentralDir constructor actually 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sets everything to be the way we want it (all zeroes). We 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * set mNeedCDRewrite so that we create *something* if the 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * caller doesn't add any files. (We could also just unlink 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the file if it's brand new and nothing was added, but that's 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * probably doing more than we really should -- the user might 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * have a need for empty zip files.) 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNeedCDRewrite = true; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = NO_ERROR; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flags & kOpenReadOnly) 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReadOnly = true; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(!mReadOnly); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the Nth entry in the archive. 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipEntry* ZipFile::getEntryByIndex(int idx) const 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (idx < 0 || idx >= (int) mEntries.size()) 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mEntries[idx]; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Find an entry by name. 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipEntry* ZipFile::getEntryByName(const char* fileName) const 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Do a stupid linear string-compare search. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * There are various ways to speed this up, especially since it's rare 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to intermingle changes to the archive with "get by name" calls. We 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * don't want to sort the mEntries vector itself, however, because 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it's used to recreate the Central Directory. 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (Hash table works, parallel list of pointers in sorted order is good.) 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int idx; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (idx = mEntries.size()-1; idx >= 0; idx--) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry* pEntry = mEntries[idx]; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!pEntry->getDeleted() && 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcmp(fileName, pEntry->getFileName()) == 0) 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return pEntry; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Empty the mEntries vector. 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid ZipFile::discardEntries(void) 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mEntries.size(); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (--count >= 0) 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete mEntries[count]; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEntries.clear(); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Find the central directory and read the contents. 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The fun thing about ZIP archives is that they may or may not be 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * readable from start to end. In some cases, notably for archives 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that were written to stdout, the only length information is in the 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * central directory at the end of the file. 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Of course, the central directory can be followed by a variable-length 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * comment field, so we have to scan through it backwards. The comment 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * itself, plus apparently sometimes people throw random junk on the end 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * just for the fun of it. 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is all a little wobbly. If the wrong value ends up in the EOCD 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * area, we're hosed. This appears to be the way that everbody handles 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it though, so we're in pretty good company if this fails. 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::readCentralDir(void) 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t result = NO_ERROR; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char* buf = NULL; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project off_t fileLength, seekStart; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long readAmount; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fseek(mZipFp, 0, SEEK_END); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fileLength = ftell(mZipFp); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rewind(mZipFp); 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* too small to be a ZIP archive? */ 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileLength < EndOfCentralDir::kEOCDLen) { 2185baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Length is %ld -- too small\n", (long)fileLength); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = INVALID_OPERATION; 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf = new unsigned char[EndOfCentralDir::kMaxEOCDSearch]; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buf == NULL) { 2255baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Failure allocating %d bytes for EOCD search", 226e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen EndOfCentralDir::kMaxEOCDSearch); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = NO_MEMORY; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileLength > EndOfCentralDir::kMaxEOCDSearch) { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project seekStart = fileLength - EndOfCentralDir::kMaxEOCDSearch; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readAmount = EndOfCentralDir::kMaxEOCDSearch; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project seekStart = 0; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readAmount = (long) fileLength; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(mZipFp, seekStart, SEEK_SET) != 0) { 2395baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Failure seeking to end of zip at %ld", (long) seekStart); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* read the last part of the file into the buffer */ 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fread(buf, 1, readAmount, mZipFp) != (size_t) readAmount) { 2465baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("short file? wanted %ld\n", readAmount); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* find the end-of-central-dir magic */ 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = readAmount - 4; i >= 0; i--) { 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buf[i] == 0x50 && 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::getLongLE(&buf[i]) == EndOfCentralDir::kSignature) 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 25671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("+++ Found EOCD at buf+%d\n", i); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i < 0) { 2615baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("EOCD not found, not Zip\n"); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = INVALID_OPERATION; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* extract eocd values */ 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = mEOCD.readBuf(buf + i, readAmount - i); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) { 2695baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Failure reading %ld bytes of EOCD values", readAmount - i); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 271e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //mEOCD.dump(); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEOCD.mDiskNumber != 0 || mEOCD.mDiskWithCentralDir != 0 || 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mNumEntries != mEOCD.mTotalNumEntries) 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2775baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Archive spanning not supported\n"); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = INVALID_OPERATION; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * So far so good. "mCentralDirSize" is the size in bytes of the 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * central directory, so we can just seek back that far to find it. 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can also seek forward mCentralDirOffset bytes from the 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * start of the file. 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We're not guaranteed to have the rest of the central dir in the 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * buffer, nor are we guaranteed that the central dir will have any 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sort of convenient size. We need to skip to the start of it and 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * read the header, then the other goodies. 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The only thing we really need right now is the file comment, which 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we're hoping to preserve. 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { 2975baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Failure seeking to central dir offset %ld\n", 298e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen mEOCD.mCentralDirOffset); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Loop through and read the central dir entries. 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 30671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Scanning %d entries...\n", mEOCD.mTotalNumEntries); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int entry; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (entry = 0; entry < mEOCD.mTotalNumEntries; entry++) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry* pEntry = new ZipEntry; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = pEntry->initFromCDE(mZipFp); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) { 3135baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("initFromCDE failed\n"); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete pEntry; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEntries.add(pEntry); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If all went well, we should now be back at the EOCD. 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char checkBuf[4]; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fread(checkBuf, 1, 4, mZipFp) != 4) { 3285baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("EOCD check read failed\n"); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = INVALID_OPERATION; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ZipEntry::getLongLE(checkBuf) != EndOfCentralDir::kSignature) { 3335baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("EOCD read check failed\n"); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("+++ EOCD read check passed\n"); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail: 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete[] buf; 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 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 * Add a new file to the archive. 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This requires creating and populating a ZipEntry structure, and copying 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the data into the file at the appropriate position. The "appropriate 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * position" is the current location of the central directory, which we 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * casually overwrite (we can put it back later). 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If we were concerned about safety, we would want to make all changes 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in a temp file and then overwrite the original after everything was 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * safely written. Not really a concern for us. 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::addCommon(const char* fileName, const void* data, size_t size, 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* storageName, int sourceType, int compressionMethod, 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry** ppEntry) 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry* pEntry = NULL; 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t result = NO_ERROR; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long lfhPosn, startPosn, endPosn, uncompressedLen; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FILE* inputFp = NULL; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned long crc; 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project time_t modWhen; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mReadOnly) 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(compressionMethod == ZipEntry::kCompressDeflated || 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project compressionMethod == ZipEntry::kCompressStored); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* make sure we're in a reasonable state */ 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mZipFp != NULL); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mEntries.size() == mEOCD.mTotalNumEntries); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* make sure it doesn't already exist */ 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getEntryByName(storageName) != NULL) 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ALREADY_EXISTS; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!data) { 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inputFp = fopen(fileName, FILE_OPEN_RO); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (inputFp == NULL) 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return errnoToStatus(errno); 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry = new ZipEntry; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->initNew(storageName, NULL); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * From here on out, failures are more interesting. 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNeedCDRewrite = true; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Write the LFH, even though it's still mostly blank. We need it 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as a place-holder. In theory the LFH isn't necessary, but in 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * practice some utilities demand it. 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lfhPosn = ftell(mZipFp); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->mLFH.write(mZipFp); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startPosn = ftell(mZipFp); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copy the data in, possibly compressing it as we go. 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sourceType == ZipEntry::kCompressStored) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (compressionMethod == ZipEntry::kCompressDeflated) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool failed = false; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = compressFpToFp(mZipFp, inputFp, data, size, &crc); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) { 4195baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("compression failed, storing\n"); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project failed = true; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Make sure it has compressed "enough". This probably ought 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to be set through an API call, but I don't expect our 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * criteria to change over time. 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long src = inputFp ? ftell(inputFp) : size; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long dst = ftell(mZipFp) - startPosn; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dst + (dst / 10) > src) { 4305baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("insufficient compression (src=%ld dst=%ld), storing\n", 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project src, dst); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project failed = true; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (failed) { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project compressionMethod = ZipEntry::kCompressStored; 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (inputFp) rewind(inputFp); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fseek(mZipFp, startPosn, SEEK_SET); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* fall through to kCompressStored case */ 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* handle "no compression" request, or failed compression from above */ 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (compressionMethod == ZipEntry::kCompressStored) { 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (inputFp) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = copyFpToFp(mZipFp, inputFp, &crc); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = copyDataToFp(mZipFp, data, size, &crc); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't need to truncate; happens in CDE rewrite 4525baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("failed copying data in\n"); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // currently seeked to end of file 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uncompressedLen = inputFp ? ftell(inputFp) : size; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sourceType == ZipEntry::kCompressDeflated) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* we should support uncompressed-from-compressed, but it's not 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * important right now */ 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(compressionMethod == ZipEntry::kCompressDeflated); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool scanResult; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int method; 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long compressedLen; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scanResult = ZipUtils::examineGzip(inputFp, &method, &uncompressedLen, 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project &compressedLen, &crc); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!scanResult || method != ZipEntry::kCompressDeflated) { 4715baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("this isn't a deflated gzip file?"); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = copyPartialFpToFp(mZipFp, inputFp, compressedLen, NULL); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) { 4785baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("failed copying gzip data in\n"); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(false); 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We could write the "Data Descriptor", but there doesn't seem to 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be any point since we're going to go back and write the LFH. 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Update file offsets. 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endPosn = ftell(mZipFp); // seeked to end of compressed data 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Success! Fill out new values. 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->setDataInfo(uncompressedLen, endPosn - startPosn, crc, 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project compressionMethod); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project modWhen = getModTime(inputFp ? fileno(inputFp) : fileno(mZipFp)); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->setModWhen(modWhen); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->setLFHOffset(lfhPosn); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mNumEntries++; 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mTotalNumEntries++; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mCentralDirOffset = endPosn; 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Go back and write the LFH. 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(mZipFp, lfhPosn, SEEK_SET) != 0) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->mLFH.write(mZipFp); 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add pEntry to the list. 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEntries.add(pEntry); 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ppEntry != NULL) 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *ppEntry = pEntry; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry = NULL; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail: 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (inputFp != NULL) 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fclose(inputFp); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete pEntry; 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add an entry by copying it from another zip file. If "padding" is 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * nonzero, the specified number of bytes will be added to the "extra" 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * field in the header. 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry, 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int padding, ZipEntry** ppEntry) 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry* pEntry = NULL; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t result; 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long lfhPosn, endPosn; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mReadOnly) 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* make sure we're in a reasonable state */ 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mZipFp != NULL); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mEntries.size() == mEOCD.mTotalNumEntries); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry = new ZipEntry; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pEntry == NULL) { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = NO_MEMORY; 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = pEntry->initFromExternal(pSourceZip, pSourceEntry); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (padding != 0) { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = pEntry->addPadding(padding); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * From here on out, failures are more interesting. 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNeedCDRewrite = true; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Write the LFH. Since we're not recompressing the data, we already 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * have all of the fields filled out. 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lfhPosn = ftell(mZipFp); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->mLFH.write(mZipFp); 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copy the data over. 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If the "has data descriptor" flag is set, we want to copy the DD 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fields as well. This is a fixed-size area immediately following 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the data. 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(pSourceZip->mZipFp, pSourceEntry->getFileOffset(), SEEK_SET) != 0) 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project off_t copyLen; 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project copyLen = pSourceEntry->getCompressedLen(); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((pSourceEntry->mLFH.mGPBitFlag & ZipEntry::kUsesDataDescr) != 0) 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project copyLen += ZipEntry::kDataDescriptorLen; 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (copyPartialFpToFp(mZipFp, pSourceZip->mZipFp, copyLen, NULL) 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != NO_ERROR) 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 6068564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("copy of '%s' failed\n", pEntry->mCDE.mFileName); 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = UNKNOWN_ERROR; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Update file offsets. 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endPosn = ftell(mZipFp); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Success! Fill out new values. 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->setLFHOffset(lfhPosn); // sets mCDE.mLocalHeaderRelOffset 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mNumEntries++; 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mTotalNumEntries++; 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mCentralDirOffset = endPosn; 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add pEntry to the list. 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEntries.add(pEntry); 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ppEntry != NULL) 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *ppEntry = pEntry; 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry = NULL; 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = NO_ERROR; 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail: 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete pEntry; 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copy all of the bytes in "src" to "dst". 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be seeked immediately past the data. 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32) 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char tmpBuf[32768]; 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t count; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *pCRC32 = crc32(0L, Z_NULL, 0); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (1) { 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count = fread(tmpBuf, 1, sizeof(tmpBuf), srcFp); 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ferror(srcFp) || ferror(dstFp)) 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return errnoToStatus(errno); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 0) 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *pCRC32 = crc32(*pCRC32, tmpBuf, count); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fwrite(tmpBuf, 1, count, dstFp) != count) { 6635baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("fwrite %d bytes failed\n", (int) count); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copy all of the bytes in "src" to "dst". 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * On exit, "dstFp" will be seeked immediately past the data. 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::copyDataToFp(FILE* dstFp, 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const void* data, size_t size, unsigned long* pCRC32) 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t count; 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *pCRC32 = crc32(0L, Z_NULL, 0); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (size > 0) { 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *pCRC32 = crc32(*pCRC32, (const unsigned char*)data, size); 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fwrite(data, 1, size, dstFp) != size) { 6855baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("fwrite %d bytes failed\n", (int) size); 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copy some of the bytes in "src" to "dst". 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If "pCRC32" is NULL, the CRC will not be computed. 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be seeked immediately past the data just written. 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length, 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned long* pCRC32) 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char tmpBuf[32768]; 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t count; 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pCRC32 != NULL) 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *pCRC32 = crc32(0L, Z_NULL, 0); 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (length) { 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long readSize; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readSize = sizeof(tmpBuf); 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (readSize > length) 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readSize = length; 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count = fread(tmpBuf, 1, readSize, srcFp); 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((long) count != readSize) { // error or unexpected EOF 7195baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("fread %d bytes failed\n", (int) readSize); 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pCRC32 != NULL) 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *pCRC32 = crc32(*pCRC32, tmpBuf, count); 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fwrite(tmpBuf, 1, count, dstFp) != count) { 7275baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("fwrite %d bytes failed\n", (int) count); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project length -= readSize; 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Compress all of the data in "srcFp" and write it to "dstFp". 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be seeked immediately past the compressed data. 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::compressFpToFp(FILE* dstFp, FILE* srcFp, 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const void* data, size_t size, unsigned long* pCRC32) 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t result = NO_ERROR; 747e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen const size_t kBufSize = 32768; 748e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen unsigned char* inBuf = NULL; 749e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen unsigned char* outBuf = NULL; 750e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen z_stream zstream; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool atEof = false; // no feof() aviailable yet 752e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen unsigned long crc; 753e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen int zerr; 754e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 755e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen /* 756e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen * Create an input buffer and an output buffer. 757e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen */ 758e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen inBuf = new unsigned char[kBufSize]; 759e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen outBuf = new unsigned char[kBufSize]; 760e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen if (inBuf == NULL || outBuf == NULL) { 761e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen result = NO_MEMORY; 762e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen goto bail; 763e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 764e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 765e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen /* 766e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen * Initialize the zlib stream. 767e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen */ 768e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen memset(&zstream, 0, sizeof(zstream)); 769e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.zalloc = Z_NULL; 770e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.zfree = Z_NULL; 771e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.opaque = Z_NULL; 772e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.next_in = NULL; 773e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.avail_in = 0; 774e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.next_out = outBuf; 775e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.avail_out = kBufSize; 776e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.data_type = Z_UNKNOWN; 777e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 778e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION, 779e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); 780e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen if (zerr != Z_OK) { 781e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen result = UNKNOWN_ERROR; 782e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen if (zerr == Z_VERSION_ERROR) { 7833762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Installed zlib is not compatible with linked version (%s)\n", 784e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen ZLIB_VERSION); 785e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } else { 7865baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Call to deflateInit2 failed (zerr=%d)\n", zerr); 787e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 788e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen goto bail; 789e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 790e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 791e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen crc = crc32(0L, Z_NULL, 0); 792e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 793e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen /* 794e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen * Loop while we have data. 795e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen */ 796e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen do { 797e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen size_t getSize; 798e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen int flush; 799e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 800e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen /* only read if the input buffer is empty */ 801e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen if (zstream.avail_in == 0 && !atEof) { 80271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("+++ reading %d bytes\n", (int)kBufSize); 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data) { 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getSize = size > kBufSize ? kBufSize : size; 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(inBuf, data, getSize); 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data = ((const char*)data) + getSize; 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size -= getSize; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getSize = fread(inBuf, 1, kBufSize, srcFp); 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ferror(srcFp)) { 8115baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("deflate read failed (errno=%d)\n", errno); 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto z_bail; 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getSize < kBufSize) { 81671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("+++ got %d bytes, EOF reached\n", 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int)getSize); 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project atEof = true; 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 821e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen crc = crc32(crc, inBuf, getSize); 822e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 823e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.next_in = inBuf; 824e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.avail_in = getSize; 825e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 826e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 827e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen if (atEof) 828e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen flush = Z_FINISH; /* tell zlib that we're done */ 829e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen else 830e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen flush = Z_NO_FLUSH; /* more to come! */ 831e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 832e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zerr = deflate(&zstream, flush); 833e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen if (zerr != Z_OK && zerr != Z_STREAM_END) { 8345baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("zlib deflate call failed (zerr=%d)\n", zerr); 835e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen result = UNKNOWN_ERROR; 836e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen goto z_bail; 837e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 838e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen 839e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen /* write when we're full or when we're done */ 840e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen if (zstream.avail_out == 0 || 841e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen (zerr == Z_STREAM_END && zstream.avail_out != (uInt) kBufSize)) 842e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen { 84371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("+++ writing %d bytes\n", (int) (zstream.next_out - outBuf)); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fwrite(outBuf, 1, zstream.next_out - outBuf, dstFp) != 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (size_t)(zstream.next_out - outBuf)) 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 8475baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("write %d failed in deflate\n", 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int) (zstream.next_out - outBuf)); 849e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen goto z_bail; 850e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 852e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.next_out = outBuf; 853e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen zstream.avail_out = kBufSize; 854e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } 855e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen } while (zerr == Z_OK); 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 857e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen assert(zerr == Z_STREAM_END); /* other errors should've been caught */ 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen *pCRC32 = crc; 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectz_bail: 862e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen deflateEnd(&zstream); /* free up any allocated structures */ 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail: 865e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen delete[] inBuf; 866e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen delete[] outBuf; 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 868e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen return result; 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Mark an entry as deleted. 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We will eventually need to crunch the file down, but if several files 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are being removed (perhaps as part of an "update" process) we can make 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * things considerably faster by deferring the removal to "flush" time. 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::remove(ZipEntry* pEntry) 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Should verify that pEntry is actually part of this archive, and 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not some stray ZipEntry from a different file. 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* mark entry as deleted, and mark archive as dirty */ 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->setDeleted(); 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNeedCDRewrite = true; 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Flush any pending writes. 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In particular, this will crunch out deleted entries, and write the 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Central Directory and EOCD if we have stomped on them. 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::flush(void) 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t result = NO_ERROR; 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long eocdPosn; 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i, count; 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mReadOnly) 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mNeedCDRewrite) 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mZipFp != NULL); 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = crunchArchive(); 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count = mEntries.size(); 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = 0; i < count; i++) { 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry* pEntry = mEntries[i]; 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->mCDE.write(mZipFp); 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eocdPosn = ftell(mZipFp); 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mCentralDirSize = eocdPosn - mEOCD.mCentralDirOffset; 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.write(mZipFp); 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If we had some stuff bloat up during compression and get replaced 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with plain files, or if we deleted some entries, there's a lot 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of wasted space at the end of the file. Remove it now. 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ftruncate(fileno(mZipFp), ftell(mZipFp)) != 0) { 9348564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("ftruncate failed %ld: %s\n", ftell(mZipFp), strerror(errno)); 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // not fatal 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* should we clear the "newly added" flag in all entries now? */ 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNeedCDRewrite = false; 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Crunch deleted files out of an archive by shifting the later files down. 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Because we're not using a temp file, we do the operation inside the 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * current file. 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::crunchArchive(void) 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t result = NO_ERROR; 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i, count; 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long delCount, adjust; 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project printf("CONTENTS:\n"); 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = 0; i < (int) mEntries.size(); i++) { 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project printf(" %d: lfhOff=%ld del=%d\n", 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i, mEntries[i]->getLFHOffset(), mEntries[i]->getDeleted()); 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project printf(" END is %ld\n", (long) mEOCD.mCentralDirOffset); 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Roll through the set of files, shifting them as appropriate. We 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * could probably get a slight performance improvement by sliding 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multiple files down at once (because we could use larger reads 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when operating on batches of small files), but it's not that useful. 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count = mEntries.size(); 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delCount = adjust = 0; 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = 0; i < count; i++) { 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry* pEntry = mEntries[i]; 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long span; 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pEntry->getLFHOffset() != 0) { 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long nextOffset; 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Get the length of this entry by finding the offset 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the next entry. Directory entries don't have 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * file offsets, so we need to find the next non-directory 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * entry. 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextOffset = 0; 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int ii = i+1; nextOffset == 0 && ii < count; ii++) 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextOffset = mEntries[ii]->getLFHOffset(); 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextOffset == 0) 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextOffset = mEOCD.mCentralDirOffset; 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span = nextOffset - pEntry->getLFHOffset(); 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(span >= ZipEntry::LocalFileHeader::kLFHLen); 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* This is a directory entry. It doesn't have 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * any actual file contents, so there's no need to 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * move anything. 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span = 0; 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //printf("+++ %d: off=%ld span=%ld del=%d [count=%d]\n", 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // i, pEntry->getLFHOffset(), span, pEntry->getDeleted(), count); 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pEntry->getDeleted()) { 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjust += span; 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delCount++; 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete pEntry; 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEntries.removeAt(i); 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* adjust loop control */ 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count--; 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i--; 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (span != 0 && adjust > 0) { 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* shuffle this entry back */ 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //printf("+++ Shuffling '%s' back %ld\n", 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pEntry->getFileName(), adjust); 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = filemove(mZipFp, pEntry->getLFHOffset() - adjust, 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->getLFHOffset(), span); 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) { 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* this is why you use a temp file */ 10223762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("error during crunch - archive is toast\n"); 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pEntry->setLFHOffset(pEntry->getLFHOffset() - adjust); 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fix EOCD info. We have to wait until the end to do some of this 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * because we use mCentralDirOffset to determine "span" for the 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * last entry. 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mCentralDirOffset -= adjust; 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mNumEntries -= delCount; 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mTotalNumEntries -= delCount; 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mEOCD.mNumEntries == mEOCD.mTotalNumEntries); 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mEOCD.mNumEntries == count); 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Works like memmove(), but on pieces of a file. 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::filemove(FILE* fp, off_t dst, off_t src, size_t n) 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dst == src || n <= 0) 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char readBuf[32768]; 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dst < src) { 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* shift stuff toward start of file; must read from start */ 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (n != 0) { 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t getSize = sizeof(readBuf); 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getSize > n) 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getSize = n; 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(fp, (long) src, SEEK_SET) != 0) { 10645baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("filemove src seek %ld failed\n", (long) src); 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fread(readBuf, 1, getSize, fp) != getSize) { 10695baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("filemove read %ld off=%ld failed\n", 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (long) getSize, (long) src); 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(fp, (long) dst, SEEK_SET) != 0) { 10755baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("filemove dst seek %ld failed\n", (long) dst); 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fwrite(readBuf, 1, getSize, fp) != getSize) { 10805baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("filemove write %ld off=%ld failed\n", 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (long) getSize, (long) dst); 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project src += getSize; 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dst += getSize; 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n -= getSize; 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* shift stuff toward end of file; must read from end */ 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(false); // write this someday, maybe 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the modification time from a file descriptor. 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttime_t ZipFile::getModTime(int fd) 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct stat sb; 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fstat(fd, &sb) < 0) { 11075baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("HEY: fstat on fd %d failed\n", fd); 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (time_t) -1; 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.st_mtime; 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0 /* this is a bad idea */ 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get a copy of the Zip file descriptor. 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We don't allow this if the file was opened read-write because we tend 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to leave the file contents in an uncertain state between calls to 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * flush(). The duplicated file descriptor should only be valid for reads. 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint ZipFile::getZipFd(void) const 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mReadOnly) 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mZipFp != NULL); 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = dup(fileno(mZipFp)); 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd < 0) { 11325baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("didn't work, errno=%d\n", errno); 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fd; 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Expand data. 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool ZipFile::uncompress(const ZipEntry* pEntry, void* buf) const 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// free the memory when you're done 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid* ZipFile::uncompress(const ZipEntry* entry) 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t unlen = entry->getUncompressedLen(); 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t clen = entry->getCompressedLen(); 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void* buf = malloc(unlen); 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buf == NULL) { 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fseek(mZipFp, 0, SEEK_SET); 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project off_t offset = entry->getFileOffset(); 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fseek(mZipFp, offset, SEEK_SET) != 0) { 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (entry->getCompressionMethod()) 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case ZipEntry::kCompressStored: { 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t amt = fread(buf, 1, unlen, mZipFp); 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (amt != (ssize_t)unlen) { 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project printf("data...\n"); 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const unsigned char* p = (unsigned char*)buf; 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const unsigned char* end = p+unlen; 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<32 && p < end; i++) { 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project printf("0x%08x ", (int)(offset+(i*0x10))); 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j=0; j<0x10 && p < end; j++) { 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project printf(" %02x", *p); 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p++; 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project printf("\n"); 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case ZipEntry::kCompressDeflated: { 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!ZipUtils::inflateToBuffer(mZipFp, buf, unlen, clen)) { 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto bail; 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return buf; 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail: 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(buf); 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * =========================================================================== 1210e38e90bf222515538281cc73c5e4a9f3c269c875Marco Nelissen * ZipFile::EndOfCentralDir 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * =========================================================================== 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Read the end-of-central-dir fields. 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "buf" should be positioned at the EOCD signature, and should contain 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the entire EOCD area including the comment. 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::EndOfCentralDir::readBuf(const unsigned char* buf, int len) 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* don't allow re-use */ 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mComment == NULL); 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len < kEOCDLen) { 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* looks like ZIP file got truncated */ 12275baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD(" Zip EOCD: expected >= %d bytes, found %d\n", 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kEOCDLen, len); 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* this should probably be an assert() */ 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDiskNumber = ZipEntry::getShortLE(&buf[0x04]); 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDiskWithCentralDir = ZipEntry::getShortLE(&buf[0x06]); 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNumEntries = ZipEntry::getShortLE(&buf[0x08]); 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalNumEntries = ZipEntry::getShortLE(&buf[0x0a]); 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCentralDirSize = ZipEntry::getLongLE(&buf[0x0c]); 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCentralDirOffset = ZipEntry::getLongLE(&buf[0x10]); 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCommentLen = ZipEntry::getShortLE(&buf[0x14]); 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: validate mCentralDirOffset 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCommentLen > 0) { 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (kEOCDLen + mCommentLen > len) { 12485baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("EOCD(%d) + comment(%d) exceeds len (%d)\n", 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kEOCDLen, mCommentLen, len); 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mComment = new unsigned char[mCommentLen]; 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(mComment, buf + kEOCDLen, mCommentLen); 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Write an end-of-central-directory section. 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t ZipFile::EndOfCentralDir::write(FILE* fp) 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char buf[kEOCDLen]; 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::putLongLE(&buf[0x00], kSignature); 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::putShortLE(&buf[0x04], mDiskNumber); 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::putShortLE(&buf[0x06], mDiskWithCentralDir); 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::putShortLE(&buf[0x08], mNumEntries); 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::putShortLE(&buf[0x0a], mTotalNumEntries); 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::putLongLE(&buf[0x0c], mCentralDirSize); 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::putLongLE(&buf[0x10], mCentralDirOffset); 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ZipEntry::putShortLE(&buf[0x14], mCommentLen); 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fwrite(buf, 1, kEOCDLen, fp) != kEOCDLen) 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCommentLen > 0) { 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(mComment != NULL); 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fwrite(mComment, mCommentLen, 1, fp) != mCommentLen) 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Dump the contents of an EndOfCentralDir object. 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid ZipFile::EndOfCentralDir::dump(void) const 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 12915baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD(" EndOfCentralDir contents:\n"); 12925baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD(" diskNum=%u diskWCD=%u numEnt=%u totalNumEnt=%u\n", 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDiskNumber, mDiskWithCentralDir, mNumEntries, mTotalNumEntries); 12945baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD(" centDirSize=%lu centDirOff=%lu commentLen=%u\n", 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCentralDirSize, mCentralDirOffset, mCommentLen); 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1298