148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen/*
248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * Copyright (C) 2006 The Android Open Source Project
348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *
448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * Licensed under the Apache License, Version 2.0 (the "License");
548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * you may not use this file except in compliance with the License.
648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * You may obtain a copy of the License at
748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *
848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *      http://www.apache.org/licenses/LICENSE-2.0
948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *
1048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * Unless required by applicable law or agreed to in writing, software
1148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * distributed under the License is distributed on an "AS IS" BASIS,
1248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * See the License for the specific language governing permissions and
1448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * limitations under the License.
1548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen */
1648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
1748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen//
1848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen// Access to Zip archives.
1948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen//
2048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
2148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen#include "ZipFile.h"
2248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
2348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen#include <memory.h>
2448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen#include <sys/stat.h>
2548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen#include <errno.h>
2648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen#include <assert.h>
2741bc424c323f86806f04acd22304d4d149bc5dbeDan Willemsen#include <inttypes.h>
2848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
2948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsenusing namespace android;
3048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
3148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen#define LOG(...) fprintf(stderr, __VA_ARGS__)
3248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
3348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen/*
3448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * Open a file and rewrite the headers
3548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen */
3648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsenstatus_t ZipFile::rewrite(const char* zipFileName)
3748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen{
3848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    assert(mZipFp == NULL);     // no reopen
3948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
4048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /* open the file */
4148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    mZipFp = fopen(zipFileName, "r+b");
4248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (mZipFp == NULL) {
4348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        int err = errno;
4448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("fopen failed: %d\n", err);
4548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        return -1;
4648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
4748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
4848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /*
4948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * Load the central directory.  If that fails, then this probably
5048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * isn't a Zip archive.
5148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     */
5248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    return rewriteCentralDir();
5348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen}
5448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
5548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen/*
5648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * Find the central directory, read and rewrite the contents.
5748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *
5848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * The fun thing about ZIP archives is that they may or may not be
5948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * readable from start to end.  In some cases, notably for archives
6048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * that were written to stdout, the only length information is in the
6148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * central directory at the end of the file.
6248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *
6348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * Of course, the central directory can be followed by a variable-length
6448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * comment field, so we have to scan through it backwards.  The comment
6548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff
6648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * itself, plus apparently sometimes people throw random junk on the end
6748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * just for the fun of it.
6848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *
6948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * This is all a little wobbly.  If the wrong value ends up in the EOCD
7048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * area, we're hosed.  This appears to be the way that everbody handles
7148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * it though, so we're in pretty good company if this fails.
7248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen */
7348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsenstatus_t ZipFile::rewriteCentralDir(void)
7448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen{
7548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    status_t result = 0;
7641bc424c323f86806f04acd22304d4d149bc5dbeDan Willemsen    uint8_t* buf = NULL;
7748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    off_t fileLength, seekStart;
7848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    long readAmount;
7948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    int i;
8048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
8148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    fseek(mZipFp, 0, SEEK_END);
8248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    fileLength = ftell(mZipFp);
8348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    rewind(mZipFp);
8448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
8548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /* too small to be a ZIP archive? */
8648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (fileLength < EndOfCentralDir::kEOCDLen) {
8748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("Length is %ld -- too small\n", (long)fileLength);
8848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = -1;
8948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
9048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
9148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
9241bc424c323f86806f04acd22304d4d149bc5dbeDan Willemsen    buf = new uint8_t[EndOfCentralDir::kMaxEOCDSearch];
9348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (buf == NULL) {
9448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("Failure allocating %d bytes for EOCD search",
9548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen             EndOfCentralDir::kMaxEOCDSearch);
9648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = -1;
9748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
9848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
9948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
10048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (fileLength > EndOfCentralDir::kMaxEOCDSearch) {
10148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        seekStart = fileLength - EndOfCentralDir::kMaxEOCDSearch;
10248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        readAmount = EndOfCentralDir::kMaxEOCDSearch;
10348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    } else {
10448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        seekStart = 0;
10548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        readAmount = (long) fileLength;
10648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
10748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (fseek(mZipFp, seekStart, SEEK_SET) != 0) {
10848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("Failure seeking to end of zip at %ld", (long) seekStart);
10948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = -1;
11048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
11148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
11248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
11348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /* read the last part of the file into the buffer */
11448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (fread(buf, 1, readAmount, mZipFp) != (size_t) readAmount) {
11548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("short file? wanted %ld\n", readAmount);
11648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = -1;
11748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
11848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
11948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
12048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /* find the end-of-central-dir magic */
12148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    for (i = readAmount - 4; i >= 0; i--) {
12248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        if (buf[i] == 0x50 &&
12348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen            ZipEntry::getLongLE(&buf[i]) == EndOfCentralDir::kSignature)
12448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        {
12548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen            break;
12648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        }
12748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
12848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (i < 0) {
12948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("EOCD not found, not Zip\n");
13048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = -1;
13148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
13248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
13348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
13448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /* extract eocd values */
13548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    result = mEOCD.readBuf(buf + i, readAmount - i);
13648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (result != 0) {
13748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("Failure reading %ld bytes of EOCD values", readAmount - i);
13848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
13948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
14048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
14148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /*
14248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * So far so good.  "mCentralDirSize" is the size in bytes of the
14348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * central directory, so we can just seek back that far to find it.
14448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * We can also seek forward mCentralDirOffset bytes from the
14548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * start of the file.
14648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     *
14748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * We're not guaranteed to have the rest of the central dir in the
14848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * buffer, nor are we guaranteed that the central dir will have any
14948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * sort of convenient size.  We need to skip to the start of it and
15048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * read the header, then the other goodies.
15148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     *
15248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * The only thing we really need right now is the file comment, which
15348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * we're hoping to preserve.
15448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     */
15548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) {
15641bc424c323f86806f04acd22304d4d149bc5dbeDan Willemsen        LOG("Failure seeking to central dir offset %" PRIu32 "\n",
15748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen             mEOCD.mCentralDirOffset);
15848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = -1;
15948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
16048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
16148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
16248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /*
16348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * Loop through and read the central dir entries.
16448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     */
16548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    int entry;
16648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    for (entry = 0; entry < mEOCD.mTotalNumEntries; entry++) {
16748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        ZipEntry* pEntry = new ZipEntry;
16848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
16948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = pEntry->initAndRewriteFromCDE(mZipFp);
17048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        if (result != 0) {
17148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen            LOG("initFromCDE failed\n");
17248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen            delete pEntry;
17348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen            goto bail;
17448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        }
17548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
17648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        delete pEntry;
17748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
17848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
17948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
18048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /*
18148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     * If all went well, we should now be back at the EOCD.
18248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen     */
18341bc424c323f86806f04acd22304d4d149bc5dbeDan Willemsen    uint8_t checkBuf[4];
18448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (fread(checkBuf, 1, 4, mZipFp) != 4) {
18548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("EOCD check read failed\n");
18648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = -1;
18748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
18848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
18948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (ZipEntry::getLongLE(checkBuf) != EndOfCentralDir::kSignature) {
19048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("EOCD read check failed\n");
19148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        result = -1;
19248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        goto bail;
19348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
19448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
19548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsenbail:
19648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    delete[] buf;
19748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    return result;
19848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen}
19948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
20048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen/*
20148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * ===========================================================================
20248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *      ZipFile::EndOfCentralDir
20348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * ===========================================================================
20448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen */
20548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
20648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen/*
20748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * Read the end-of-central-dir fields.
20848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen *
20948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * "buf" should be positioned at the EOCD signature, and should contain
21048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen * the entire EOCD area including the comment.
21148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen */
21241bc424c323f86806f04acd22304d4d149bc5dbeDan Willemsenstatus_t ZipFile::EndOfCentralDir::readBuf(const uint8_t* buf, int len)
21348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen{
21441bc424c323f86806f04acd22304d4d149bc5dbeDan Willemsen    uint16_t diskNumber, diskWithCentralDir, numEntries;
21548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
21648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (len < kEOCDLen) {
21748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        /* looks like ZIP file got truncated */
21848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG(" Zip EOCD: expected >= %d bytes, found %d\n",
21948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen            kEOCDLen, len);
22048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        return -1;
22148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
22248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
22348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    /* this should probably be an assert() */
22448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (ZipEntry::getLongLE(&buf[0x00]) != kSignature)
22548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        return -1;
22648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
22748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    diskNumber = ZipEntry::getShortLE(&buf[0x04]);
22848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    diskWithCentralDir = ZipEntry::getShortLE(&buf[0x06]);
22948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    numEntries = ZipEntry::getShortLE(&buf[0x08]);
23048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    mTotalNumEntries = ZipEntry::getShortLE(&buf[0x0a]);
23148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    mCentralDirOffset = ZipEntry::getLongLE(&buf[0x10]);
23248a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
23348a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    if (diskNumber != 0 || diskWithCentralDir != 0 ||
23448a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        numEntries != mTotalNumEntries)
23548a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    {
23648a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        LOG("Archive spanning not supported\n");
23748a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen        return -1;
23848a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    }
23948a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen
24048a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen    return 0;
24148a621c2779c74cba3555c96e3fbc7b1989ac90bDan Willemsen}
242