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