1769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 2769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Copyright (C) 2006 The Android Open Source Project 3769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 4769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * you may not use this file except in compliance with the License. 6769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * You may obtain a copy of the License at 7769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 8769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 10769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * See the License for the specific language governing permissions and 14769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * limitations under the License. 15769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 16769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 17769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski// 18769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski// Access to Zip archives. 19769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski// 20769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 21769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#define LOG_TAG "zip" 22769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 23769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include <androidfw/ZipUtils.h> 24769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include <utils/Log.h> 25769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 26769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include "ZipFile.h" 27769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include "Util.h" 28769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 29769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include <zlib.h> 30769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#define DEF_MEM_LEVEL 8 // normally in zutil.h? 31769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 32769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include <memory.h> 33769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include <sys/stat.h> 34769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include <errno.h> 35769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#include <assert.h> 36769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 37769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskinamespace aapt { 38769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 39769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskiusing namespace android; 40769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 41769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 42769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Some environments require the "b", some choke on it. 43769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 44769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#define FILE_OPEN_RO "rb" 45769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#define FILE_OPEN_RW "r+b" 46769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#define FILE_OPEN_RW_CREATE "w+b" 47769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 48769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* should live somewhere else? */ 49769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatic status_t errnoToStatus(int err) 50769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 51769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (err == ENOENT) 52769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NAME_NOT_FOUND; 53769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski else if (err == EACCES) 54769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return PERMISSION_DENIED; 55769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski else 56769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 57769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 58769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 59769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 60769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Open a file and parse its guts. 61769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 62769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::open(const char* zipFileName, int flags) 63769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 64769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski bool newArchive = false; 65769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 66769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mZipFp == NULL); // no reopen 67769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 68769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if ((flags & kOpenTruncate)) 69769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski flags |= kOpenCreate; // trunc implies create 70769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 71769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if ((flags & kOpenReadOnly) && (flags & kOpenReadWrite)) 72769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return INVALID_OPERATION; // not both 73769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!((flags & kOpenReadOnly) || (flags & kOpenReadWrite))) 74769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return INVALID_OPERATION; // not neither 75769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if ((flags & kOpenCreate) && !(flags & kOpenReadWrite)) 76769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return INVALID_OPERATION; // create requires write 77769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 78769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (flags & kOpenTruncate) { 79769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski newArchive = true; 80769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 81769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski newArchive = (access(zipFileName, F_OK) != 0); 82769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!(flags & kOpenCreate) && newArchive) { 83769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* not creating, must already exist */ 84769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("File %s does not exist", zipFileName); 85769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NAME_NOT_FOUND; 86769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 87769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 88769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 89769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* open the file */ 90769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski const char* openflags; 91769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (flags & kOpenReadWrite) { 92769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (newArchive) 93769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski openflags = FILE_OPEN_RW_CREATE; 94769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski else 95769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski openflags = FILE_OPEN_RW; 96769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 97769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski openflags = FILE_OPEN_RO; 98769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 99769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mZipFp = fopen(zipFileName, openflags); 100769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (mZipFp == NULL) { 101769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int err = errno; 102769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("fopen failed: %d\n", err); 103769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return errnoToStatus(err); 104769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 105769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 106769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski status_t result; 107769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!newArchive) { 108769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 109769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Load the central directory. If that fails, then this probably 110769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * isn't a Zip archive. 111769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 112769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = readCentralDir(); 113769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 114769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 115769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Newly-created. The EndOfCentralDir constructor actually 116769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * sets everything to be the way we want it (all zeroes). We 117769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * set mNeedCDRewrite so that we create *something* if the 118769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * caller doesn't add any files. (We could also just unlink 119769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * the file if it's brand new and nothing was added, but that's 120769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * probably doing more than we really should -- the user might 121769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * have a need for empty zip files.) 122769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 123769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mNeedCDRewrite = true; 124769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = NO_ERROR; 125769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 126769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 127769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (flags & kOpenReadOnly) 128769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mReadOnly = true; 129769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski else 130769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(!mReadOnly); 131769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 132769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return result; 133769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 134769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 135769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 136769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Return the Nth entry in the archive. 137769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 138769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiZipEntry* ZipFile::getEntryByIndex(int idx) const 139769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 140769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (idx < 0 || idx >= (int) mEntries.size()) 141769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NULL; 142769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 143769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return mEntries[idx]; 144769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 145769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 146769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 147769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Find an entry by name. 148769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 149769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiZipEntry* ZipFile::getEntryByName(const char* fileName) const 150769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 151769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 152769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Do a stupid linear string-compare search. 153769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 154769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * There are various ways to speed this up, especially since it's rare 155769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * to intermingle changes to the archive with "get by name" calls. We 156769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * don't want to sort the mEntries vector itself, however, because 157769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * it's used to recreate the Central Directory. 158769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 159769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * (Hash table works, parallel list of pointers in sorted order is good.) 160769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 161769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int idx; 162769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 163769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (idx = mEntries.size()-1; idx >= 0; idx--) { 164769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry* pEntry = mEntries[idx]; 165769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!pEntry->getDeleted() && 166769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski strcmp(fileName, pEntry->getFileName()) == 0) 167769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 168769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return pEntry; 169769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 170769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 171769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 172769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NULL; 173769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 174769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 175769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 176769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Empty the mEntries vector. 177769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 178769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskivoid ZipFile::discardEntries(void) 179769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 180769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int count = mEntries.size(); 181769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 182769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski while (--count >= 0) 183769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delete mEntries[count]; 184769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 185769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEntries.clear(); 186769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 187769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 188769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 189769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 190769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Find the central directory and read the contents. 191769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 192769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * The fun thing about ZIP archives is that they may or may not be 193769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * readable from start to end. In some cases, notably for archives 194769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * that were written to stdout, the only length information is in the 195769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * central directory at the end of the file. 196769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 197769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Of course, the central directory can be followed by a variable-length 198769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * comment field, so we have to scan through it backwards. The comment 199769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff 200769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * itself, plus apparently sometimes people throw random junk on the end 201769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * just for the fun of it. 202769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 203769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * This is all a little wobbly. If the wrong value ends up in the EOCD 204769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * area, we're hosed. This appears to be the way that everbody handles 205769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * it though, so we're in pretty good company if this fails. 206769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 207769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::readCentralDir(void) 208769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 209769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski status_t result = NO_ERROR; 210769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned char* buf = NULL; 211769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski off_t fileLength, seekStart; 212769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long readAmount; 213769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int i; 214769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 215769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski fseek(mZipFp, 0, SEEK_END); 216769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski fileLength = ftell(mZipFp); 217769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski rewind(mZipFp); 218769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 219769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* too small to be a ZIP archive? */ 220769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fileLength < EndOfCentralDir::kEOCDLen) { 221769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("Length is %ld -- too small\n", (long)fileLength); 222769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = INVALID_OPERATION; 223769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 224769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 225769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 226769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski buf = new unsigned char[EndOfCentralDir::kMaxEOCDSearch]; 227769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (buf == NULL) { 228769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("Failure allocating %d bytes for EOCD search", 229769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski EndOfCentralDir::kMaxEOCDSearch); 230769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = NO_MEMORY; 231769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 232769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 233769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 234769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fileLength > EndOfCentralDir::kMaxEOCDSearch) { 235769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski seekStart = fileLength - EndOfCentralDir::kMaxEOCDSearch; 236769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski readAmount = EndOfCentralDir::kMaxEOCDSearch; 237769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 238769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski seekStart = 0; 239769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski readAmount = (long) fileLength; 240769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 241769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(mZipFp, seekStart, SEEK_SET) != 0) { 242769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("Failure seeking to end of zip at %ld", (long) seekStart); 243769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 244769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 245769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 246769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 247769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* read the last part of the file into the buffer */ 248769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fread(buf, 1, readAmount, mZipFp) != (size_t) readAmount) { 249769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("short file? wanted %ld\n", readAmount); 250769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 251769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 252769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 253769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 254769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* find the end-of-central-dir magic */ 255769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (i = readAmount - 4; i >= 0; i--) { 256769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (buf[i] == 0x50 && 257769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::getLongLE(&buf[i]) == EndOfCentralDir::kSignature) 258769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 259769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGV("+++ Found EOCD at buf+%d\n", i); 260769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski break; 261769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 262769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 263769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (i < 0) { 264769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("EOCD not found, not Zip\n"); 265769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = INVALID_OPERATION; 266769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 267769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 268769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 269769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* extract eocd values */ 270769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = mEOCD.readBuf(buf + i, readAmount - i); 271769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (result != NO_ERROR) { 272769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("Failure reading %ld bytes of EOCD values", readAmount - i); 273769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 274769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 275769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski //mEOCD.dump(); 276769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 277769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (mEOCD.mDiskNumber != 0 || mEOCD.mDiskWithCentralDir != 0 || 278769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mNumEntries != mEOCD.mTotalNumEntries) 279769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 280769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("Archive spanning not supported\n"); 281769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = INVALID_OPERATION; 282769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 283769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 284769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 285769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 286769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * So far so good. "mCentralDirSize" is the size in bytes of the 287769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * central directory, so we can just seek back that far to find it. 288769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * We can also seek forward mCentralDirOffset bytes from the 289769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * start of the file. 290769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 291769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * We're not guaranteed to have the rest of the central dir in the 292769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * buffer, nor are we guaranteed that the central dir will have any 293769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * sort of convenient size. We need to skip to the start of it and 294769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * read the header, then the other goodies. 295769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 296769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * The only thing we really need right now is the file comment, which 297769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * we're hoping to preserve. 298769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 299769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { 300769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("Failure seeking to central dir offset %ld\n", 301769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mCentralDirOffset); 302769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 303769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 304769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 305769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 306769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 307769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Loop through and read the central dir entries. 308769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 309769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGV("Scanning %d entries...\n", mEOCD.mTotalNumEntries); 310769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int entry; 311769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (entry = 0; entry < mEOCD.mTotalNumEntries; entry++) { 312769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry* pEntry = new ZipEntry; 313769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 314769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = pEntry->initFromCDE(mZipFp); 315769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (result != NO_ERROR) { 316769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("initFromCDE failed\n"); 317769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delete pEntry; 318769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 319769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 320769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 321769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEntries.push_back(pEntry); 322769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 323769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 324769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 325769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 326769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * If all went well, we should now be back at the EOCD. 327769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 328769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 329769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned char checkBuf[4]; 330769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fread(checkBuf, 1, 4, mZipFp) != 4) { 331769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("EOCD check read failed\n"); 332769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = INVALID_OPERATION; 333769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 334769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 335769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (ZipEntry::getLongLE(checkBuf) != EndOfCentralDir::kSignature) { 336769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("EOCD read check failed\n"); 337769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 338769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 339769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 340769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGV("+++ EOCD read check passed\n"); 341769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 342769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 343769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskibail: 344769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delete[] buf; 345769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return result; 346769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 347769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 348769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::add(const BigBuffer& buffer, const char* storageName, int compressionMethod, 349769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry** ppEntry) { 350769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski std::unique_ptr<uint8_t[]> data = util::copy(buffer); 351769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return add(data.get(), buffer.size(), storageName, compressionMethod, ppEntry); 352769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 353769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 354769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 355769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 356769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Add a new file to the archive. 357769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 358769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * This requires creating and populating a ZipEntry structure, and copying 359769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * the data into the file at the appropriate position. The "appropriate 360769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * position" is the current location of the central directory, which we 361769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * casually overwrite (we can put it back later). 362769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 363769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * If we were concerned about safety, we would want to make all changes 364769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * in a temp file and then overwrite the original after everything was 365769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * safely written. Not really a concern for us. 366769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 367769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::addCommon(const char* fileName, const void* data, size_t size, 368769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski const char* storageName, int sourceType, int compressionMethod, 369769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry** ppEntry) 370769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 371769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry* pEntry = NULL; 372769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski status_t result = NO_ERROR; 373769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long lfhPosn, startPosn, endPosn, uncompressedLen; 374769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski FILE* inputFp = NULL; 375769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned long crc; 376769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski time_t modWhen; 377769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 378769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (mReadOnly) 379769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return INVALID_OPERATION; 380769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 381769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(compressionMethod == ZipEntry::kCompressDeflated || 382769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski compressionMethod == ZipEntry::kCompressStored); 383769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 384769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* make sure we're in a reasonable state */ 385769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mZipFp != NULL); 386769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mEntries.size() == mEOCD.mTotalNumEntries); 387769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 388769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* make sure it doesn't already exist */ 389769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (getEntryByName(storageName) != NULL) 390769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return ALREADY_EXISTS; 391769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 392769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!data) { 393769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski inputFp = fopen(fileName, FILE_OPEN_RO); 394769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (inputFp == NULL) 395769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return errnoToStatus(errno); 396769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 397769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 398769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { 399769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 400769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 401769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 402769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 403769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry = new ZipEntry; 404769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->initNew(storageName, NULL); 405769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 406769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 407769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * From here on out, failures are more interesting. 408769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 409769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mNeedCDRewrite = true; 410769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 411769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 412769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Write the LFH, even though it's still mostly blank. We need it 413769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * as a place-holder. In theory the LFH isn't necessary, but in 414769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * practice some utilities demand it. 415769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 416769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski lfhPosn = ftell(mZipFp); 417769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->mLFH.write(mZipFp); 418769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski startPosn = ftell(mZipFp); 419769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 420769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 421769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Copy the data in, possibly compressing it as we go. 422769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 423769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (sourceType == ZipEntry::kCompressStored) { 424769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (compressionMethod == ZipEntry::kCompressDeflated) { 425769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski bool failed = false; 426769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = compressFpToFp(mZipFp, inputFp, data, size, &crc); 427769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (result != NO_ERROR) { 428769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("compression failed, storing\n"); 429769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski failed = true; 430769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 431769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 432769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Make sure it has compressed "enough". This probably ought 433769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * to be set through an API call, but I don't expect our 434769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * criteria to change over time. 435769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 436769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long src = inputFp ? ftell(inputFp) : size; 437769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long dst = ftell(mZipFp) - startPosn; 438769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (dst + (dst / 10) > src) { 439769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("insufficient compression (src=%ld dst=%ld), storing\n", 440769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski src, dst); 441769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski failed = true; 442769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 443769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 444769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 445769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (failed) { 446769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski compressionMethod = ZipEntry::kCompressStored; 447769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (inputFp) rewind(inputFp); 448769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski fseek(mZipFp, startPosn, SEEK_SET); 449769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* fall through to kCompressStored case */ 450769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 451769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 452769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* handle "no compression" request, or failed compression from above */ 453769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (compressionMethod == ZipEntry::kCompressStored) { 454769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (inputFp) { 455769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = copyFpToFp(mZipFp, inputFp, &crc); 456769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 457769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = copyDataToFp(mZipFp, data, size, &crc); 458769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 459769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (result != NO_ERROR) { 460769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski // don't need to truncate; happens in CDE rewrite 461769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("failed copying data in\n"); 462769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 463769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 464769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 465769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 466769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski // currently seeked to end of file 467769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski uncompressedLen = inputFp ? ftell(inputFp) : size; 468769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else if (sourceType == ZipEntry::kCompressDeflated) { 469769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* we should support uncompressed-from-compressed, but it's not 470769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * important right now */ 471769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(compressionMethod == ZipEntry::kCompressDeflated); 472769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 473769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski bool scanResult; 474769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int method; 475769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long compressedLen; 476769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 477769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski scanResult = ZipUtils::examineGzip(inputFp, &method, &uncompressedLen, 478769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski &compressedLen, &crc); 479769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!scanResult || method != ZipEntry::kCompressDeflated) { 480769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("this isn't a deflated gzip file?"); 481769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 482769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 483769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 484769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 485769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = copyPartialFpToFp(mZipFp, inputFp, compressedLen, NULL); 486769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (result != NO_ERROR) { 487769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("failed copying gzip data in\n"); 488769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 489769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 490769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 491769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(false); 492769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 493769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 494769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 495769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 496769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 497769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * We could write the "Data Descriptor", but there doesn't seem to 498769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * be any point since we're going to go back and write the LFH. 499769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 500769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Update file offsets. 501769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 502769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski endPosn = ftell(mZipFp); // seeked to end of compressed data 503769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 504769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 505769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Success! Fill out new values. 506769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 507769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->setDataInfo(uncompressedLen, endPosn - startPosn, crc, 508769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski compressionMethod); 509769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski modWhen = getModTime(inputFp ? fileno(inputFp) : fileno(mZipFp)); 510769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->setModWhen(modWhen); 511769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->setLFHOffset(lfhPosn); 512769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mNumEntries++; 513769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mTotalNumEntries++; 514769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() 515769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mCentralDirOffset = endPosn; 516769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 517769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 518769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Go back and write the LFH. 519769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 520769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(mZipFp, lfhPosn, SEEK_SET) != 0) { 521769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 522769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 523769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 524769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->mLFH.write(mZipFp); 525769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 526769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 527769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Add pEntry to the list. 528769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 529769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEntries.push_back(pEntry); 530769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (ppEntry != NULL) 531769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *ppEntry = pEntry; 532769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry = NULL; 533769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 534769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskibail: 535769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (inputFp != NULL) 536769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski fclose(inputFp); 537769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delete pEntry; 538769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return result; 539769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 540769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 541769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 542769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Add an entry by copying it from another zip file. If "padding" is 543769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * nonzero, the specified number of bytes will be added to the "extra" 544769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * field in the header. 545769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 546769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. 547769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 548769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry, 549d5c4f8723c2b2c85b588fa07a5d4e7afb671d257Adam Lesinski const char* storageName, int padding, ZipEntry** ppEntry) 550769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 551769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry* pEntry = NULL; 552769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski status_t result; 553769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long lfhPosn, endPosn; 554769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 555769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (mReadOnly) 556769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return INVALID_OPERATION; 557769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 558769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* make sure we're in a reasonable state */ 559769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mZipFp != NULL); 560769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mEntries.size() == mEOCD.mTotalNumEntries); 561769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 562769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { 563769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 564769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 565769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 566769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 567769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry = new ZipEntry; 568769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (pEntry == NULL) { 569769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = NO_MEMORY; 570769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 571769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 572769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 573d5c4f8723c2b2c85b588fa07a5d4e7afb671d257Adam Lesinski result = pEntry->initFromExternal(pSourceZip, pSourceEntry, storageName); 574d5c4f8723c2b2c85b588fa07a5d4e7afb671d257Adam Lesinski if (result != NO_ERROR) { 575769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 576d5c4f8723c2b2c85b588fa07a5d4e7afb671d257Adam Lesinski } 577769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (padding != 0) { 578769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = pEntry->addPadding(padding); 579769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (result != NO_ERROR) 580769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 581769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 582769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 583769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 584769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * From here on out, failures are more interesting. 585769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 586769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mNeedCDRewrite = true; 587769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 588769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 589769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Write the LFH. Since we're not recompressing the data, we already 590769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * have all of the fields filled out. 591769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 592769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski lfhPosn = ftell(mZipFp); 593769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->mLFH.write(mZipFp); 594769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 595769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 596769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Copy the data over. 597769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 598769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * If the "has data descriptor" flag is set, we want to copy the DD 599769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * fields as well. This is a fixed-size area immediately following 600769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * the data. 601769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 602769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(pSourceZip->mZipFp, pSourceEntry->getFileOffset(), SEEK_SET) != 0) 603769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 604769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 605769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 606769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 607769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 608769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski off_t copyLen; 609769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski copyLen = pSourceEntry->getCompressedLen(); 610769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if ((pSourceEntry->mLFH.mGPBitFlag & ZipEntry::kUsesDataDescr) != 0) 611769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski copyLen += ZipEntry::kDataDescriptorLen; 612769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 613769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (copyPartialFpToFp(mZipFp, pSourceZip->mZipFp, copyLen, NULL) 614769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski != NO_ERROR) 615769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 616769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGW("copy of '%s' failed\n", pEntry->mCDE.mFileName); 617769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 618769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 619769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 620769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 621769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 622769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Update file offsets. 623769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 624769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski endPosn = ftell(mZipFp); 625769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 626769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 627769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Success! Fill out new values. 628769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 629769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->setLFHOffset(lfhPosn); // sets mCDE.mLocalHeaderRelOffset 630769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mNumEntries++; 631769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mTotalNumEntries++; 632769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() 633769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mCentralDirOffset = endPosn; 634769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 635769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 636769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Add pEntry to the list. 637769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 638769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEntries.push_back(pEntry); 639769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (ppEntry != NULL) 640769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *ppEntry = pEntry; 641769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry = NULL; 642769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 643769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = NO_ERROR; 644769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 645769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskibail: 646769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delete pEntry; 647769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return result; 648769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 649769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 650769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 651769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Copy all of the bytes in "src" to "dst". 652769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 653769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" 654769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * will be seeked immediately past the data. 655769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 656769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32) 657769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 658769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned char tmpBuf[32768]; 659769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski size_t count; 660769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 661769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *pCRC32 = crc32(0L, Z_NULL, 0); 662769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 663769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski while (1) { 664769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski count = fread(tmpBuf, 1, sizeof(tmpBuf), srcFp); 665769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (ferror(srcFp) || ferror(dstFp)) 666769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return errnoToStatus(errno); 667769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (count == 0) 668769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski break; 669769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 670769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *pCRC32 = crc32(*pCRC32, tmpBuf, count); 671769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 672769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fwrite(tmpBuf, 1, count, dstFp) != count) { 673769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("fwrite %d bytes failed\n", (int) count); 674769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 675769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 676769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 677769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 678769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 679769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 680769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 681769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 682769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Copy all of the bytes in "src" to "dst". 683769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 684769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * On exit, "dstFp" will be seeked immediately past the data. 685769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 686769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::copyDataToFp(FILE* dstFp, 687769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski const void* data, size_t size, unsigned long* pCRC32) 688769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 689769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *pCRC32 = crc32(0L, Z_NULL, 0); 690769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (size > 0) { 691769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *pCRC32 = crc32(*pCRC32, (const unsigned char*)data, size); 692769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fwrite(data, 1, size, dstFp) != size) { 693769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("fwrite %d bytes failed\n", (int) size); 694769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 695769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 696769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 697769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 698769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 699769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 700769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 701769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 702769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Copy some of the bytes in "src" to "dst". 703769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 704769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * If "pCRC32" is NULL, the CRC will not be computed. 705769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 706769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" 707769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * will be seeked immediately past the data just written. 708769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 709769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length, 710769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned long* pCRC32) 711769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 712769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned char tmpBuf[32768]; 713769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski size_t count; 714769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 715769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (pCRC32 != NULL) 716769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *pCRC32 = crc32(0L, Z_NULL, 0); 717769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 718769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski while (length) { 719769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long readSize; 720769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 721769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski readSize = sizeof(tmpBuf); 722769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (readSize > length) 723769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski readSize = length; 724769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 725769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski count = fread(tmpBuf, 1, readSize, srcFp); 726769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if ((long) count != readSize) { // error or unexpected EOF 727769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("fread %d bytes failed\n", (int) readSize); 728769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 729769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 730769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 731769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (pCRC32 != NULL) 732769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *pCRC32 = crc32(*pCRC32, tmpBuf, count); 733769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 734769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fwrite(tmpBuf, 1, count, dstFp) != count) { 735769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("fwrite %d bytes failed\n", (int) count); 736769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 737769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 738769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 739769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski length -= readSize; 740769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 741769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 742769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 743769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 744769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 745769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 746769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Compress all of the data in "srcFp" and write it to "dstFp". 747769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 748769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" 749769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * will be seeked immediately past the compressed data. 750769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 751769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::compressFpToFp(FILE* dstFp, FILE* srcFp, 752769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski const void* data, size_t size, unsigned long* pCRC32) 753769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 754769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski status_t result = NO_ERROR; 755769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski const size_t kBufSize = 32768; 756769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned char* inBuf = NULL; 757769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned char* outBuf = NULL; 758769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski z_stream zstream; 759769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski bool atEof = false; // no feof() aviailable yet 760769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned long crc; 761769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int zerr; 762769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 763769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 764769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Create an input buffer and an output buffer. 765769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 766769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski inBuf = new unsigned char[kBufSize]; 767769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski outBuf = new unsigned char[kBufSize]; 768769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (inBuf == NULL || outBuf == NULL) { 769769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = NO_MEMORY; 770769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 771769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 772769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 773769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 774769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Initialize the zlib stream. 775769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 776769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski memset(&zstream, 0, sizeof(zstream)); 777769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.zalloc = Z_NULL; 778769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.zfree = Z_NULL; 779769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.opaque = Z_NULL; 780769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.next_in = NULL; 781769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.avail_in = 0; 782769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.next_out = outBuf; 783769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.avail_out = kBufSize; 784769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.data_type = Z_UNKNOWN; 785769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 786769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION, 787769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); 788769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (zerr != Z_OK) { 789769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 790769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (zerr == Z_VERSION_ERROR) { 791769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGE("Installed zlib is not compatible with linked version (%s)\n", 792769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZLIB_VERSION); 793769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 794769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("Call to deflateInit2 failed (zerr=%d)\n", zerr); 795769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 796769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 797769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 798769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 799769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski crc = crc32(0L, Z_NULL, 0); 800769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 801769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 802769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Loop while we have data. 803769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 804769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski do { 805769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski size_t getSize; 806769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int flush; 807769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 808769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* only read if the input buffer is empty */ 809769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (zstream.avail_in == 0 && !atEof) { 810769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGV("+++ reading %d bytes\n", (int)kBufSize); 811769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (data) { 812769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski getSize = size > kBufSize ? kBufSize : size; 813769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski memcpy(inBuf, data, getSize); 814769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski data = ((const char*)data) + getSize; 815769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski size -= getSize; 816769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 817769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski getSize = fread(inBuf, 1, kBufSize, srcFp); 818769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (ferror(srcFp)) { 819769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("deflate read failed (errno=%d)\n", errno); 820769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto z_bail; 821769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 822769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 823769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (getSize < kBufSize) { 824769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGV("+++ got %d bytes, EOF reached\n", 825769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski (int)getSize); 826769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski atEof = true; 827769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 828769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 829769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski crc = crc32(crc, inBuf, getSize); 830769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 831769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.next_in = inBuf; 832769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.avail_in = getSize; 833769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 834769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 835769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (atEof) 836769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski flush = Z_FINISH; /* tell zlib that we're done */ 837769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski else 838769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski flush = Z_NO_FLUSH; /* more to come! */ 839769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 840769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zerr = deflate(&zstream, flush); 841769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (zerr != Z_OK && zerr != Z_STREAM_END) { 842769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("zlib deflate call failed (zerr=%d)\n", zerr); 843769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = UNKNOWN_ERROR; 844769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto z_bail; 845769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 846769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 847769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* write when we're full or when we're done */ 848769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (zstream.avail_out == 0 || 849769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski (zerr == Z_STREAM_END && zstream.avail_out != (uInt) kBufSize)) 850769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 851769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGV("+++ writing %d bytes\n", (int) (zstream.next_out - outBuf)); 852769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fwrite(outBuf, 1, zstream.next_out - outBuf, dstFp) != 853769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski (size_t)(zstream.next_out - outBuf)) 854769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 855769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("write %d failed in deflate\n", 856769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski (int) (zstream.next_out - outBuf)); 857769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto z_bail; 858769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 859769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 860769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.next_out = outBuf; 861769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski zstream.avail_out = kBufSize; 862769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 863769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } while (zerr == Z_OK); 864769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 865769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(zerr == Z_STREAM_END); /* other errors should've been caught */ 866769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 867769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski *pCRC32 = crc; 868769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 869769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskiz_bail: 870769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski deflateEnd(&zstream); /* free up any allocated structures */ 871769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 872769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskibail: 873769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delete[] inBuf; 874769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delete[] outBuf; 875769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 876769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return result; 877769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 878769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 879769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 880769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Mark an entry as deleted. 881769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 882769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * We will eventually need to crunch the file down, but if several files 883769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * are being removed (perhaps as part of an "update" process) we can make 884769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * things considerably faster by deferring the removal to "flush" time. 885769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 886769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::remove(ZipEntry* pEntry) 887769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 888769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 889769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Should verify that pEntry is actually part of this archive, and 890769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * not some stray ZipEntry from a different file. 891769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 892769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 893769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* mark entry as deleted, and mark archive as dirty */ 894769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->setDeleted(); 895769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mNeedCDRewrite = true; 896769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 897769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 898769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 899769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 900769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Flush any pending writes. 901769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 902769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * In particular, this will crunch out deleted entries, and write the 903769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Central Directory and EOCD if we have stomped on them. 904769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 905769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::flush(void) 906769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 907769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski status_t result = NO_ERROR; 908769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long eocdPosn; 909769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int i, count; 910769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 911769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (mReadOnly) 912769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return INVALID_OPERATION; 913769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!mNeedCDRewrite) 914769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 915769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 916769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mZipFp != NULL); 917769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 918769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = crunchArchive(); 919769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (result != NO_ERROR) 920769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return result; 921769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 922769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) 923769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 924769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 925769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski count = mEntries.size(); 926769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (i = 0; i < count; i++) { 927769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry* pEntry = mEntries[i]; 928769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->mCDE.write(mZipFp); 929769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 930769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 931769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski eocdPosn = ftell(mZipFp); 932769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mCentralDirSize = eocdPosn - mEOCD.mCentralDirOffset; 933769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 934769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.write(mZipFp); 935769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 936769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 937769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * If we had some stuff bloat up during compression and get replaced 938769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * with plain files, or if we deleted some entries, there's a lot 939769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * of wasted space at the end of the file. Remove it now. 940769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 941769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (ftruncate(fileno(mZipFp), ftell(mZipFp)) != 0) { 942769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGW("ftruncate failed %ld: %s\n", ftell(mZipFp), strerror(errno)); 943769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski // not fatal 944769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 945769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 946769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* should we clear the "newly added" flag in all entries now? */ 947769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 948769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mNeedCDRewrite = false; 949769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 950769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 951769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 952769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 953769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Crunch deleted files out of an archive by shifting the later files down. 954769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 955769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Because we're not using a temp file, we do the operation inside the 956769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * current file. 957769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 958769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::crunchArchive(void) 959769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 960769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski status_t result = NO_ERROR; 961769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int i, count; 962769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long delCount, adjust; 963769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 964769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#if 0 965769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski printf("CONTENTS:\n"); 966769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (i = 0; i < (int) mEntries.size(); i++) { 967769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski printf(" %d: lfhOff=%ld del=%d\n", 968769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski i, mEntries[i]->getLFHOffset(), mEntries[i]->getDeleted()); 969769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 970769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski printf(" END is %ld\n", (long) mEOCD.mCentralDirOffset); 971769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#endif 972769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 973769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 974769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Roll through the set of files, shifting them as appropriate. We 975769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * could probably get a slight performance improvement by sliding 976769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * multiple files down at once (because we could use larger reads 977769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * when operating on batches of small files), but it's not that useful. 978769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 979769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski count = mEntries.size(); 980769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delCount = adjust = 0; 981769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (i = 0; i < count; i++) { 982769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry* pEntry = mEntries[i]; 983769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long span; 984769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 985769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (pEntry->getLFHOffset() != 0) { 986769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski long nextOffset; 987769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 988769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* Get the length of this entry by finding the offset 989769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * of the next entry. Directory entries don't have 990769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * file offsets, so we need to find the next non-directory 991769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * entry. 992769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 993769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski nextOffset = 0; 994769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (int ii = i+1; nextOffset == 0 && ii < count; ii++) 995769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski nextOffset = mEntries[ii]->getLFHOffset(); 996769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (nextOffset == 0) 997769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski nextOffset = mEOCD.mCentralDirOffset; 998769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski span = nextOffset - pEntry->getLFHOffset(); 999769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1000769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(span >= ZipEntry::LocalFileHeader::kLFHLen); 1001769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 1002769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* This is a directory entry. It doesn't have 1003769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * any actual file contents, so there's no need to 1004769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * move anything. 1005769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1006769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski span = 0; 1007769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1008769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1009769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski //printf("+++ %d: off=%ld span=%ld del=%d [count=%d]\n", 1010769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski // i, pEntry->getLFHOffset(), span, pEntry->getDeleted(), count); 1011769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1012769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (pEntry->getDeleted()) { 1013769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski adjust += span; 1014769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delCount++; 1015769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1016769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski delete pEntry; 1017769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEntries.erase(mEntries.begin() + i); 1018769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1019769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* adjust loop control */ 1020769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski count--; 1021769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski i--; 1022769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else if (span != 0 && adjust > 0) { 1023769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* shuffle this entry back */ 1024769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski //printf("+++ Shuffling '%s' back %ld\n", 1025769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski // pEntry->getFileName(), adjust); 1026769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski result = filemove(mZipFp, pEntry->getLFHOffset() - adjust, 1027769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->getLFHOffset(), span); 1028769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (result != NO_ERROR) { 1029769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* this is why you use a temp file */ 1030769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGE("error during crunch - archive is toast\n"); 1031769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return result; 1032769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1033769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1034769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski pEntry->setLFHOffset(pEntry->getLFHOffset() - adjust); 1035769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1036769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1037769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1038769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* 1039769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Fix EOCD info. We have to wait until the end to do some of this 1040769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * because we use mCentralDirOffset to determine "span" for the 1041769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * last entry. 1042769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1043769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mCentralDirOffset -= adjust; 1044769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mNumEntries -= delCount; 1045769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mTotalNumEntries -= delCount; 1046769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() 1047769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1048769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mEOCD.mNumEntries == mEOCD.mTotalNumEntries); 1049769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mEOCD.mNumEntries == count); 1050769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1051769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return result; 1052769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1053769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1054769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 1055769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Works like memmove(), but on pieces of a file. 1056769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1057769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::filemove(FILE* fp, off_t dst, off_t src, size_t n) 1058769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 1059769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (dst == src || n <= 0) 1060769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 1061769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1062769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned char readBuf[32768]; 1063769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1064769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (dst < src) { 1065769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* shift stuff toward start of file; must read from start */ 1066769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski while (n != 0) { 1067769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski size_t getSize = sizeof(readBuf); 1068769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (getSize > n) 1069769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski getSize = n; 1070769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1071769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(fp, (long) src, SEEK_SET) != 0) { 1072769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("filemove src seek %ld failed\n", (long) src); 1073769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1074769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1075769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1076769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fread(readBuf, 1, getSize, fp) != getSize) { 1077769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("filemove read %ld off=%ld failed\n", 1078769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski (long) getSize, (long) src); 1079769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1080769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1081769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1082769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(fp, (long) dst, SEEK_SET) != 0) { 1083769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("filemove dst seek %ld failed\n", (long) dst); 1084769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1085769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1086769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1087769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fwrite(readBuf, 1, getSize, fp) != getSize) { 1088769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("filemove write %ld off=%ld failed\n", 1089769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski (long) getSize, (long) dst); 1090769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1091769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1092769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1093769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski src += getSize; 1094769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski dst += getSize; 1095769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski n -= getSize; 1096769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1097769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } else { 1098769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* shift stuff toward end of file; must read from end */ 1099769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(false); // write this someday, maybe 1100769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1101769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1102769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1103769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 1104769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1105769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1106769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1107769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 1108769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Get the modification time from a file descriptor. 1109769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1110769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskitime_t ZipFile::getModTime(int fd) 1111769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 1112769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski struct stat sb; 1113769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1114769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fstat(fd, &sb) < 0) { 1115769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("HEY: fstat on fd %d failed\n", fd); 1116769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return (time_t) -1; 1117769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1118769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1119769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return sb.st_mtime; 1120769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1121769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1122769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1123769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#if 0 /* this is a bad idea */ 1124769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 1125769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Get a copy of the Zip file descriptor. 1126769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 1127769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * We don't allow this if the file was opened read-write because we tend 1128769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * to leave the file contents in an uncertain state between calls to 1129769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * flush(). The duplicated file descriptor should only be valid for reads. 1130769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1131769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskiint ZipFile::getZipFd(void) const 1132769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 1133769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!mReadOnly) 1134769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return INVALID_OPERATION; 1135769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mZipFp != NULL); 1136769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1137769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski int fd; 1138769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski fd = dup(fileno(mZipFp)); 1139769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fd < 0) { 1140769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("didn't work, errno=%d\n", errno); 1141769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1142769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1143769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return fd; 1144769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1145769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#endif 1146769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1147769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1148769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#if 0 1149769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 1150769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Expand data. 1151769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1152769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskibool ZipFile::uncompress(const ZipEntry* pEntry, void* buf) const 1153769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 1154769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return false; 1155769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1156769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#endif 1157769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1158769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski// free the memory when you're done 1159769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskivoid* ZipFile::uncompress(const ZipEntry* entry) 1160769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 1161769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski size_t unlen = entry->getUncompressedLen(); 1162769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski size_t clen = entry->getCompressedLen(); 1163769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1164769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski void* buf = malloc(unlen); 1165769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (buf == NULL) { 1166769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NULL; 1167769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1168769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1169769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski fseek(mZipFp, 0, SEEK_SET); 1170769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1171769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski off_t offset = entry->getFileOffset(); 1172769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fseek(mZipFp, offset, SEEK_SET) != 0) { 1173769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 1174769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1175769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1176769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski switch (entry->getCompressionMethod()) 1177769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski { 1178769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski case ZipEntry::kCompressStored: { 1179769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ssize_t amt = fread(buf, 1, unlen, mZipFp); 1180769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (amt != (ssize_t)unlen) { 1181769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 1182769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1183769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#if 0 1184769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski printf("data...\n"); 1185769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski const unsigned char* p = (unsigned char*)buf; 1186769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski const unsigned char* end = p+unlen; 1187769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (int i=0; i<32 && p < end; i++) { 1188769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski printf("0x%08x ", (int)(offset+(i*0x10))); 1189769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski for (int j=0; j<0x10 && p < end; j++) { 1190769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski printf(" %02x", *p); 1191769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski p++; 1192769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1193769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski printf("\n"); 1194769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1195769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski#endif 1196769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1197769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1198769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski break; 1199769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski case ZipEntry::kCompressDeflated: { 1200769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (!ZipUtils::inflateToBuffer(mZipFp, buf, unlen, clen)) { 1201769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 1202769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1203769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1204769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski break; 1205769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski default: 1206769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski goto bail; 1207769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1208769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return buf; 1209769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1210769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskibail: 1211769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski free(buf); 1212769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NULL; 1213769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1214769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1215769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1216769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 1217769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * =========================================================================== 1218769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * ZipFile::EndOfCentralDir 1219769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * =========================================================================== 1220769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1221769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1222769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 1223769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Read the end-of-central-dir fields. 1224769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * 1225769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * "buf" should be positioned at the EOCD signature, and should contain 1226769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * the entire EOCD area including the comment. 1227769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1228769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::EndOfCentralDir::readBuf(const unsigned char* buf, int len) 1229769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 1230769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* don't allow re-use */ 1231769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mComment == NULL); 1232769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1233769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (len < kEOCDLen) { 1234769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* looks like ZIP file got truncated */ 1235769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD(" Zip EOCD: expected >= %d bytes, found %d\n", 1236769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski kEOCDLen, len); 1237769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return INVALID_OPERATION; 1238769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1239769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1240769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski /* this should probably be an assert() */ 1241769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) 1242769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1243769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1244769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mDiskNumber = ZipEntry::getShortLE(&buf[0x04]); 1245769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mDiskWithCentralDir = ZipEntry::getShortLE(&buf[0x06]); 1246769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mNumEntries = ZipEntry::getShortLE(&buf[0x08]); 1247769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mTotalNumEntries = ZipEntry::getShortLE(&buf[0x0a]); 1248769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mCentralDirSize = ZipEntry::getLongLE(&buf[0x0c]); 1249769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mCentralDirOffset = ZipEntry::getLongLE(&buf[0x10]); 1250769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mCommentLen = ZipEntry::getShortLE(&buf[0x14]); 1251769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1252769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski // TODO: validate mCentralDirOffset 1253769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1254769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (mCommentLen > 0) { 1255769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (kEOCDLen + mCommentLen > len) { 1256769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD("EOCD(%d) + comment(%d) exceeds len (%d)\n", 1257769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski kEOCDLen, mCommentLen, len); 1258769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1259769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1260769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mComment = new unsigned char[mCommentLen]; 1261769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski memcpy(mComment, buf + kEOCDLen, mCommentLen); 1262769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1263769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1264769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 1265769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1266769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1267769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 1268769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Write an end-of-central-directory section. 1269769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1270769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskistatus_t ZipFile::EndOfCentralDir::write(FILE* fp) 1271769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 1272769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski unsigned char buf[kEOCDLen]; 1273769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1274769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::putLongLE(&buf[0x00], kSignature); 1275769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::putShortLE(&buf[0x04], mDiskNumber); 1276769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::putShortLE(&buf[0x06], mDiskWithCentralDir); 1277769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::putShortLE(&buf[0x08], mNumEntries); 1278769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::putShortLE(&buf[0x0a], mTotalNumEntries); 1279769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::putLongLE(&buf[0x0c], mCentralDirSize); 1280769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::putLongLE(&buf[0x10], mCentralDirOffset); 1281769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ZipEntry::putShortLE(&buf[0x14], mCommentLen); 1282769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1283769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fwrite(buf, 1, kEOCDLen, fp) != kEOCDLen) 1284769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1285769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (mCommentLen > 0) { 1286769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski assert(mComment != NULL); 1287769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (fwrite(mComment, mCommentLen, 1, fp) != mCommentLen) 1288769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return UNKNOWN_ERROR; 1289769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 1290769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1291769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return NO_ERROR; 1292769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1293769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1294769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski/* 1295769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski * Dump the contents of an EndOfCentralDir object. 1296769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski */ 1297769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskivoid ZipFile::EndOfCentralDir::dump(void) const 1298769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski{ 1299769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD(" EndOfCentralDir contents:\n"); 1300769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD(" diskNum=%u diskWCD=%u numEnt=%u totalNumEnt=%u\n", 1301769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mDiskNumber, mDiskWithCentralDir, mNumEntries, mTotalNumEntries); 1302769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ALOGD(" centDirSize=%lu centDirOff=%lu commentLen=%u\n", 1303769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski mCentralDirSize, mCentralDirOffset, mCommentLen); 1304769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 1305769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 1306769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} // namespace aapt 1307