13344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
23344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Copyright (C) 2006 The Android Open Source Project
33344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
43344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
53344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * you may not use this file except in compliance with the License.
63344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * You may obtain a copy of the License at
73344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
83344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
93344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
103344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Unless required by applicable law or agreed to in writing, software
113344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
123344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * See the License for the specific language governing permissions and
143344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * limitations under the License.
153344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
163344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
173344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian//
183344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian// Access to entries in a Zip archive.
193344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian//
203344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
213344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#define LOG_TAG "zip"
223344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
233344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#include "ZipEntry.h"
243344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#include <utils/Log.h>
253344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
263344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#include <stdio.h>
273344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#include <string.h>
283344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#include <assert.h>
293344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
303344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianusing namespace android;
313344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
323344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
333344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Initialize a new ZipEntry structure from a FILE* positioned at a
343344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * CentralDirectoryEntry.
353344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
363344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * On exit, the file pointer will be at the start of the next CDE or
373344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * at the EOCD.
383344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
393344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianstatus_t ZipEntry::initFromCDE(FILE* fp)
403344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
413344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    status_t result;
423344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    long posn;
433344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    bool hasDD;
443344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
452da72c6265bab1322876fa9702f7580bff7fd8beSteve Block    //ALOGV("initFromCDE ---\n");
463344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
473344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* read the CDE */
483344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    result = mCDE.read(fp);
493344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (result != NO_ERROR) {
5015fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        ALOGD("mCDE.read failed\n");
513344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return result;
523344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
533344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
543344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    //mCDE.dump();
553344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
563344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* using the info in the CDE, go load up the LFH */
573344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    posn = ftell(fp);
583344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (fseek(fp, mCDE.mLocalHeaderRelOffset, SEEK_SET) != 0) {
5915fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        ALOGD("local header seek failed (%ld)\n",
603344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            mCDE.mLocalHeaderRelOffset);
613344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return UNKNOWN_ERROR;
623344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
633344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
643344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    result = mLFH.read(fp);
653344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (result != NO_ERROR) {
6615fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        ALOGD("mLFH.read failed\n");
673344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return result;
683344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
693344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
703344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (fseek(fp, posn, SEEK_SET) != 0)
713344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return UNKNOWN_ERROR;
723344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
733344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    //mLFH.dump();
743344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
753344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /*
763344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * We *might* need to read the Data Descriptor at this point and
773344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * integrate it into the LFH.  If this bit is set, the CRC-32,
783344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * compressed size, and uncompressed size will be zero.  In practice
793344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * these seem to be rare.
803344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     */
813344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    hasDD = (mLFH.mGPBitFlag & kUsesDataDescr) != 0;
823344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (hasDD) {
833344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        // do something clever
8415fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        //ALOGD("+++ has data descriptor\n");
853344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
863344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
873344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /*
883344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * Sanity-check the LFH.  Note that this will fail if the "kUsesDataDescr"
893344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * flag is set, because the LFH is incomplete.  (Not a problem, since we
903344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * prefer the CDE values.)
913344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     */
923344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (!hasDD && !compareHeaders()) {
93c0b74df335aa99e3c3f6f752de531836faa0c7c5Steve Block        ALOGW("WARNING: header mismatch\n");
943344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        // keep going?
953344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
963344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
973344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /*
983344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * If the mVersionToExtract is greater than 20, we may have an
993344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * issue unpacking the record -- could be encrypted, compressed
1003344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * with something we don't support, or use Zip64 extensions.  We
1013344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * can defer worrying about that to when we're extracting data.
1023344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     */
1033344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1043344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return NO_ERROR;
1053344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
1063344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1073344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
1083344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Initialize a new entry.  Pass in the file name and an optional comment.
1093344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
1103344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Initializes the CDE and the LFH.
1113344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
1123344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianvoid ZipEntry::initNew(const char* fileName, const char* comment)
1133344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
1143344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    assert(fileName != NULL && *fileName != '\0');  // name required
1153344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1163344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* most fields are properly initialized by constructor */
1173344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mVersionMadeBy = kDefaultMadeBy;
1183344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mVersionToExtract = kDefaultVersion;
1193344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mCompressionMethod = kCompressStored;
1203344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mFileNameLength = strlen(fileName);
1213344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (comment != NULL)
1223344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCDE.mFileCommentLength = strlen(comment);
1233344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mExternalAttrs = 0x81b60020;   // matches what WinZip does
1243344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1253344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mFileNameLength > 0) {
1263344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1];
1273344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        strcpy((char*) mCDE.mFileName, fileName);
1283344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
1293344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mFileCommentLength > 0) {
1303344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        /* TODO: stop assuming null-terminated ASCII here? */
1313344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1];
1323344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        strcpy((char*) mCDE.mFileComment, comment);
1333344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
1343344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1353344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    copyCDEtoLFH();
1363344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
1373344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1383344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
1393344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Initialize a new entry, starting with the ZipEntry from a different
1403344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * archive.
1413344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
1423344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Initializes the CDE and the LFH.
1433344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
1443344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianstatus_t ZipEntry::initFromExternal(const ZipFile* pZipFile,
1453344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    const ZipEntry* pEntry)
1463344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
1473344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /*
1483344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * Copy everything in the CDE over, then fix up the hairy bits.
1493344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     */
1503344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    memcpy(&mCDE, &pEntry->mCDE, sizeof(mCDE));
1513344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1523344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mFileNameLength > 0) {
1533344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1];
1543344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mCDE.mFileName == NULL)
1553344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return NO_MEMORY;
1563344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        strcpy((char*) mCDE.mFileName, (char*)pEntry->mCDE.mFileName);
1573344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
1583344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mFileCommentLength > 0) {
1593344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1];
1603344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mCDE.mFileComment == NULL)
1613344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return NO_MEMORY;
1623344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        strcpy((char*) mCDE.mFileComment, (char*)pEntry->mCDE.mFileComment);
1633344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
1643344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mExtraFieldLength > 0) {
1653344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        /* we null-terminate this, though it may not be a string */
1663344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCDE.mExtraField = new unsigned char[mCDE.mExtraFieldLength+1];
1673344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mCDE.mExtraField == NULL)
1683344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return NO_MEMORY;
1693344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        memcpy(mCDE.mExtraField, pEntry->mCDE.mExtraField,
1703344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            mCDE.mExtraFieldLength+1);
1713344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
1723344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1733344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* construct the LFH from the CDE */
1743344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    copyCDEtoLFH();
1753344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1763344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /*
1773344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * The LFH "extra" field is independent of the CDE "extra", so we
1783344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     * handle it here.
1793344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian     */
1803344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    assert(mLFH.mExtraField == NULL);
1813344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mExtraFieldLength = pEntry->mLFH.mExtraFieldLength;
1823344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mLFH.mExtraFieldLength > 0) {
1833344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLFH.mExtraField = new unsigned char[mLFH.mExtraFieldLength+1];
1843344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mLFH.mExtraField == NULL)
1853344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return NO_MEMORY;
1863344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        memcpy(mLFH.mExtraField, pEntry->mLFH.mExtraField,
1873344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            mLFH.mExtraFieldLength+1);
1883344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
1893344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1903344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return NO_ERROR;
1913344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
1923344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
1933344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
1943344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Insert pad bytes in the LFH by tweaking the "extra" field.  This will
1953344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * potentially confuse something that put "extra" data in here earlier,
1963344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * but I can't find an actual problem.
1973344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
1983344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianstatus_t ZipEntry::addPadding(int padding)
1993344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
2003344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (padding <= 0)
2013344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return INVALID_OPERATION;
2023344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
203934443b2751691adc9b06026d79f50efe9365ce1Steve Block    //ALOGI("HEY: adding %d pad bytes to existing %d in %s\n",
2043344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    //    padding, mLFH.mExtraFieldLength, mCDE.mFileName);
2053344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
2063344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mLFH.mExtraFieldLength > 0) {
2073344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        /* extend existing field */
2083344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        unsigned char* newExtra;
2093344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
2103344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        newExtra = new unsigned char[mLFH.mExtraFieldLength + padding];
2113344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (newExtra == NULL)
2123344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return NO_MEMORY;
2133344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        memset(newExtra + mLFH.mExtraFieldLength, 0, padding);
2143344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        memcpy(newExtra, mLFH.mExtraField, mLFH.mExtraFieldLength);
2153344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
2163344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        delete[] mLFH.mExtraField;
2173344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLFH.mExtraField = newExtra;
2183344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLFH.mExtraFieldLength += padding;
2193344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    } else {
2203344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        /* create new field */
2213344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLFH.mExtraField = new unsigned char[padding];
2223344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        memset(mLFH.mExtraField, 0, padding);
2233344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLFH.mExtraFieldLength = padding;
2243344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
2253344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
2263344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return NO_ERROR;
2273344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
2283344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
2293344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
2303344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Set the fields in the LFH equal to the corresponding fields in the CDE.
2313344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
2323344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * This does not touch the LFH "extra" field.
2333344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
2343344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianvoid ZipEntry::copyCDEtoLFH(void)
2353344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
2363344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mVersionToExtract  = mCDE.mVersionToExtract;
2373344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mGPBitFlag         = mCDE.mGPBitFlag;
2383344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mCompressionMethod = mCDE.mCompressionMethod;
2393344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mLastModFileTime   = mCDE.mLastModFileTime;
2403344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mLastModFileDate   = mCDE.mLastModFileDate;
2413344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mCRC32             = mCDE.mCRC32;
2423344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mCompressedSize    = mCDE.mCompressedSize;
2433344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mUncompressedSize  = mCDE.mUncompressedSize;
2443344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLFH.mFileNameLength    = mCDE.mFileNameLength;
2453344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    // the "extra field" is independent
2463344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
2473344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    delete[] mLFH.mFileName;
2483344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mLFH.mFileNameLength > 0) {
2493344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLFH.mFileName = new unsigned char[mLFH.mFileNameLength+1];
2503344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        strcpy((char*) mLFH.mFileName, (const char*) mCDE.mFileName);
2513344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    } else {
2523344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLFH.mFileName = NULL;
2533344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
2543344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
2553344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
2563344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
2573344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Set some information about a file after we add it.
2583344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
2593344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianvoid ZipEntry::setDataInfo(long uncompLen, long compLen, unsigned long crc32,
2603344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    int compressionMethod)
2613344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
2623344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mCompressionMethod = compressionMethod;
2633344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mCRC32 = crc32;
2643344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mCompressedSize = compLen;
2653344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mUncompressedSize = uncompLen;
2663344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mCompressionMethod = compressionMethod;
2673344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (compressionMethod == kCompressDeflated) {
2683344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCDE.mGPBitFlag |= 0x0002;      // indicates maximum compression used
2693344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
2703344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    copyCDEtoLFH();
2713344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
2723344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
2733344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
2743344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * See if the data in mCDE and mLFH match up.  This is mostly useful for
2753344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * debugging these classes, but it can be used to identify damaged
2763344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * archives.
2773344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
2783344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Returns "false" if they differ.
2793344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
2803344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianbool ZipEntry::compareHeaders(void) const
2813344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
2823344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mVersionToExtract != mLFH.mVersionToExtract) {
2832da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: VersionToExtract\n");
2843344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
2853344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
2863344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mGPBitFlag != mLFH.mGPBitFlag) {
2872da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: GPBitFlag\n");
2883344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
2893344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
2903344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mCompressionMethod != mLFH.mCompressionMethod) {
2912da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: CompressionMethod\n");
2923344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
2933344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
2943344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mLastModFileTime != mLFH.mLastModFileTime) {
2952da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: LastModFileTime\n");
2963344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
2973344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
2983344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mLastModFileDate != mLFH.mLastModFileDate) {
2992da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: LastModFileDate\n");
3003344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
3013344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
3023344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mCRC32 != mLFH.mCRC32) {
3032da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: CRC32\n");
3043344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
3053344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
3063344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mCompressedSize != mLFH.mCompressedSize) {
3072da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: CompressedSize\n");
3083344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
3093344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
3103344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mUncompressedSize != mLFH.mUncompressedSize) {
3112da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: UncompressedSize\n");
3123344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
3133344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
3143344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mFileNameLength != mLFH.mFileNameLength) {
3152da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: FileNameLength\n");
3163344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
3173344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
3183344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#if 0       // this seems to be used for padding, not real data
3193344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mExtraFieldLength != mLFH.mExtraFieldLength) {
3202da72c6265bab1322876fa9702f7580bff7fd8beSteve Block        ALOGV("cmp: ExtraFieldLength\n");
3213344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return false;
3223344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
3233344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#endif
3243344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mCDE.mFileName != NULL) {
3253344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (strcmp((char*) mCDE.mFileName, (char*) mLFH.mFileName) != 0) {
3262da72c6265bab1322876fa9702f7580bff7fd8beSteve Block            ALOGV("cmp: FileName\n");
3273344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return false;
3283344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
3293344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
3303344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3313344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return true;
3323344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
3333344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3343344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3353344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
3363344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Convert the DOS date/time stamp into a UNIX time stamp.
3373344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
3383344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopiantime_t ZipEntry::getModWhen(void) const
3393344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
3403344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    struct tm parts;
3413344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3423344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    parts.tm_sec = (mCDE.mLastModFileTime & 0x001f) << 1;
3433344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    parts.tm_min = (mCDE.mLastModFileTime & 0x07e0) >> 5;
3443344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    parts.tm_hour = (mCDE.mLastModFileTime & 0xf800) >> 11;
3453344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    parts.tm_mday = (mCDE.mLastModFileDate & 0x001f);
3463344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    parts.tm_mon = ((mCDE.mLastModFileDate & 0x01e0) >> 5) -1;
3473344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    parts.tm_year = ((mCDE.mLastModFileDate & 0xfe00) >> 9) + 80;
3483344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    parts.tm_wday = parts.tm_yday = 0;
3493344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    parts.tm_isdst = -1;        // DST info "not available"
3503344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3513344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return mktime(&parts);
3523344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
3533344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3543344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
3553344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Set the CDE/LFH timestamp from UNIX time.
3563344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
3573344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianvoid ZipEntry::setModWhen(time_t when)
3583344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
3593344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#ifdef HAVE_LOCALTIME_R
3603344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    struct tm tmResult;
3613344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#endif
3623344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    time_t even;
3633344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    unsigned short zdate, ztime;
3643344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3653344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    struct tm* ptm;
3663344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3673344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* round up to an even number of seconds */
3683344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    even = (time_t)(((unsigned long)(when) + 1) & (~1));
3693344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3703344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* expand */
3713344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#ifdef HAVE_LOCALTIME_R
3723344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ptm = localtime_r(&even, &tmResult);
3733344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#else
3743344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ptm = localtime(&even);
3753344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian#endif
3763344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3773344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    int year;
3783344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    year = ptm->tm_year;
3793344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (year < 80)
3803344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        year = 80;
3813344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3823344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday;
3833344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
3843344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3853344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime;
3863344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate;
3873344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
3883344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3893344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3903344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
3913344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * ===========================================================================
3923344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *      ZipEntry::LocalFileHeader
3933344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * ===========================================================================
3943344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
3953344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
3963344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
3973344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Read a local file header.
3983344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
3993344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * On entry, "fp" points to the signature at the start of the header.
4003344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * On exit, "fp" points to the start of data.
4013344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
4023344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianstatus_t ZipEntry::LocalFileHeader::read(FILE* fp)
4033344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
4043344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    status_t result = NO_ERROR;
4053344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    unsigned char buf[kLFHLen];
4063344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4073344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    assert(mFileName == NULL);
4083344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    assert(mExtraField == NULL);
4093344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4103344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (fread(buf, 1, kLFHLen, fp) != kLFHLen) {
4113344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        result = UNKNOWN_ERROR;
4123344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        goto bail;
4133344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
4143344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4153344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) {
41615fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        ALOGD("whoops: didn't find expected signature\n");
4173344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        result = UNKNOWN_ERROR;
4183344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        goto bail;
4193344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
4203344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4213344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mVersionToExtract = ZipEntry::getShortLE(&buf[0x04]);
4223344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mGPBitFlag = ZipEntry::getShortLE(&buf[0x06]);
4233344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCompressionMethod = ZipEntry::getShortLE(&buf[0x08]);
4243344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLastModFileTime = ZipEntry::getShortLE(&buf[0x0a]);
4253344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLastModFileDate = ZipEntry::getShortLE(&buf[0x0c]);
4263344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCRC32 = ZipEntry::getLongLE(&buf[0x0e]);
4273344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCompressedSize = ZipEntry::getLongLE(&buf[0x12]);
4283344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mUncompressedSize = ZipEntry::getLongLE(&buf[0x16]);
4293344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mFileNameLength = ZipEntry::getShortLE(&buf[0x1a]);
4303344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1c]);
4313344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4323344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    // TODO: validate sizes
4333344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4343344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* grab filename */
4353344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileNameLength != 0) {
4363344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mFileName = new unsigned char[mFileNameLength+1];
4373344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mFileName == NULL) {
4383344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = NO_MEMORY;
4393344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
4403344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
4413344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) {
4423344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = UNKNOWN_ERROR;
4433344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
4443344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
4453344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mFileName[mFileNameLength] = '\0';
4463344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
4473344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4483344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* grab extra field */
4493344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mExtraFieldLength != 0) {
4503344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mExtraField = new unsigned char[mExtraFieldLength+1];
4513344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mExtraField == NULL) {
4523344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = NO_MEMORY;
4533344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
4543344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
4553344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) {
4563344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = UNKNOWN_ERROR;
4573344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
4583344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
4593344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mExtraField[mExtraFieldLength] = '\0';
4603344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
4613344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4623344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianbail:
4633344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return result;
4643344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
4653344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4663344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
4673344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Write a local file header.
4683344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
4693344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianstatus_t ZipEntry::LocalFileHeader::write(FILE* fp)
4703344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
4713344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    unsigned char buf[kLFHLen];
4723344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4733344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x00], kSignature);
4743344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x04], mVersionToExtract);
4753344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x06], mGPBitFlag);
4763344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x08], mCompressionMethod);
4773344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x0a], mLastModFileTime);
4783344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x0c], mLastModFileDate);
4793344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x0e], mCRC32);
4803344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x12], mCompressedSize);
4813344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x16], mUncompressedSize);
4823344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x1a], mFileNameLength);
4833344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x1c], mExtraFieldLength);
4843344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4853344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (fwrite(buf, 1, kLFHLen, fp) != kLFHLen)
4863344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return UNKNOWN_ERROR;
4873344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4883344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* write filename */
4893344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileNameLength != 0) {
4903344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength)
4913344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return UNKNOWN_ERROR;
4923344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
4933344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
4943344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* write "extra field" */
4953344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mExtraFieldLength != 0) {
4963344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength)
4973344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return UNKNOWN_ERROR;
4983344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
4993344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5003344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return NO_ERROR;
5013344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
5023344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5033344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5043344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
5053344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Dump the contents of a LocalFileHeader object.
5063344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
5073344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianvoid ZipEntry::LocalFileHeader::dump(void) const
5083344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
50915fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD(" LocalFileHeader contents:\n");
51015fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  versToExt=%u gpBits=0x%04x compression=%u\n",
5113344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mVersionToExtract, mGPBitFlag, mCompressionMethod);
51215fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n",
5133344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLastModFileTime, mLastModFileDate, mCRC32);
51415fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  compressedSize=%lu uncompressedSize=%lu\n",
5153344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCompressedSize, mUncompressedSize);
51615fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  filenameLen=%u extraLen=%u\n",
5173344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mFileNameLength, mExtraFieldLength);
5183344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileName != NULL)
51915fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        ALOGD("  filename: '%s'\n", mFileName);
5203344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
5213344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5223344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5233344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
5243344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * ===========================================================================
5253344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *      ZipEntry::CentralDirEntry
5263344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * ===========================================================================
5273344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
5283344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5293344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
5303344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Read the central dir entry that appears next in the file.
5313344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian *
5323344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * On entry, "fp" should be positioned on the signature bytes for the
5333344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * entry.  On exit, "fp" will point at the signature word for the next
5343344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * entry or for the EOCD.
5353344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
5363344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianstatus_t ZipEntry::CentralDirEntry::read(FILE* fp)
5373344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
5383344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    status_t result = NO_ERROR;
5393344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    unsigned char buf[kCDELen];
5403344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5413344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* no re-use */
5423344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    assert(mFileName == NULL);
5433344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    assert(mExtraField == NULL);
5443344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    assert(mFileComment == NULL);
5453344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5463344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (fread(buf, 1, kCDELen, fp) != kCDELen) {
5473344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        result = UNKNOWN_ERROR;
5483344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        goto bail;
5493344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
5503344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5513344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) {
55215fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        ALOGD("Whoops: didn't find expected signature\n");
5533344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        result = UNKNOWN_ERROR;
5543344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        goto bail;
5553344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
5563344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5573344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mVersionMadeBy = ZipEntry::getShortLE(&buf[0x04]);
5583344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mVersionToExtract = ZipEntry::getShortLE(&buf[0x06]);
5593344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mGPBitFlag = ZipEntry::getShortLE(&buf[0x08]);
5603344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCompressionMethod = ZipEntry::getShortLE(&buf[0x0a]);
5613344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLastModFileTime = ZipEntry::getShortLE(&buf[0x0c]);
5623344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLastModFileDate = ZipEntry::getShortLE(&buf[0x0e]);
5633344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCRC32 = ZipEntry::getLongLE(&buf[0x10]);
5643344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mCompressedSize = ZipEntry::getLongLE(&buf[0x14]);
5653344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mUncompressedSize = ZipEntry::getLongLE(&buf[0x18]);
5663344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mFileNameLength = ZipEntry::getShortLE(&buf[0x1c]);
5673344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1e]);
5683344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mFileCommentLength = ZipEntry::getShortLE(&buf[0x20]);
5693344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mDiskNumberStart = ZipEntry::getShortLE(&buf[0x22]);
5703344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mInternalAttrs = ZipEntry::getShortLE(&buf[0x24]);
5713344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mExternalAttrs = ZipEntry::getLongLE(&buf[0x26]);
5723344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    mLocalHeaderRelOffset = ZipEntry::getLongLE(&buf[0x2a]);
5733344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5743344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    // TODO: validate sizes and offsets
5753344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5763344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* grab filename */
5773344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileNameLength != 0) {
5783344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mFileName = new unsigned char[mFileNameLength+1];
5793344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mFileName == NULL) {
5803344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = NO_MEMORY;
5813344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
5823344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
5833344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) {
5843344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = UNKNOWN_ERROR;
5853344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
5863344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
5873344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mFileName[mFileNameLength] = '\0';
5883344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
5893344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
5903344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* read "extra field" */
5913344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mExtraFieldLength != 0) {
5923344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mExtraField = new unsigned char[mExtraFieldLength+1];
5933344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mExtraField == NULL) {
5943344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = NO_MEMORY;
5953344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
5963344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
5973344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) {
5983344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = UNKNOWN_ERROR;
5993344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
6003344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
6013344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mExtraField[mExtraFieldLength] = '\0';
6023344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
6033344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6043344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6053344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* grab comment, if any */
6063344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileCommentLength != 0) {
6073344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mFileComment = new unsigned char[mFileCommentLength+1];
6083344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (mFileComment == NULL) {
6093344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = NO_MEMORY;
6103344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
6113344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
6123344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fread(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength)
6133344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        {
6143344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            result = UNKNOWN_ERROR;
6153344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            goto bail;
6163344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        }
6173344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mFileComment[mFileCommentLength] = '\0';
6183344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
6193344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6203344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianbail:
6213344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return result;
6223344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
6233344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6243344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
6253344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Write a central dir entry.
6263344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
6273344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianstatus_t ZipEntry::CentralDirEntry::write(FILE* fp)
6283344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
6293344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    unsigned char buf[kCDELen];
6303344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6313344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x00], kSignature);
6323344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x04], mVersionMadeBy);
6333344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x06], mVersionToExtract);
6343344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x08], mGPBitFlag);
6353344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x0a], mCompressionMethod);
6363344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x0c], mLastModFileTime);
6373344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x0e], mLastModFileDate);
6383344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x10], mCRC32);
6393344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x14], mCompressedSize);
6403344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x18], mUncompressedSize);
6413344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x1c], mFileNameLength);
6423344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x1e], mExtraFieldLength);
6433344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x20], mFileCommentLength);
6443344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x22], mDiskNumberStart);
6453344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putShortLE(&buf[0x24], mInternalAttrs);
6463344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x26], mExternalAttrs);
6473344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    ZipEntry::putLongLE(&buf[0x2a], mLocalHeaderRelOffset);
6483344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6493344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (fwrite(buf, 1, kCDELen, fp) != kCDELen)
6503344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        return UNKNOWN_ERROR;
6513344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6523344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* write filename */
6533344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileNameLength != 0) {
6543344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength)
6553344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return UNKNOWN_ERROR;
6563344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
6573344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6583344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* write "extra field" */
6593344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mExtraFieldLength != 0) {
6603344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength)
6613344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return UNKNOWN_ERROR;
6623344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
6633344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6643344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    /* write comment */
6653344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileCommentLength != 0) {
6663344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        if (fwrite(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength)
6673344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian            return UNKNOWN_ERROR;
6683344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    }
6693344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6703344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    return NO_ERROR;
6713344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
6723344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6733344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian/*
6743344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian * Dump the contents of a CentralDirEntry object.
6753344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian */
6763344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopianvoid ZipEntry::CentralDirEntry::dump(void) const
6773344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian{
67815fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD(" CentralDirEntry contents:\n");
67915fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n",
6803344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mVersionMadeBy, mVersionToExtract, mGPBitFlag, mCompressionMethod);
68115fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n",
6823344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLastModFileTime, mLastModFileDate, mCRC32);
68315fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  compressedSize=%lu uncompressedSize=%lu\n",
6843344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mCompressedSize, mUncompressedSize);
68515fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  filenameLen=%u extraLen=%u commentLen=%u\n",
6863344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mFileNameLength, mExtraFieldLength, mFileCommentLength);
68715fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block    ALOGD("  diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n",
6883344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mDiskNumberStart, mInternalAttrs, mExternalAttrs,
6893344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian        mLocalHeaderRelOffset);
6903344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
6913344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileName != NULL)
69215fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        ALOGD("  filename: '%s'\n", mFileName);
6933344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian    if (mFileComment != NULL)
69415fab1aa8c1ac4d92222dba349c473a8edd7ce99Steve Block        ALOGD("  comment: '%s'\n", mFileComment);
6953344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian}
6963344b2e9b27466111524dfcfb64d7258153e0cb7Mathias Agopian
697