1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "private.h" 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectenum { 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // finding the directory 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project CD_SIGNATURE = 0x06054b50, 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project EOCD_LEN = 22, // EndOfCentralDir len, excl. comment 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project MAX_COMMENT_LEN = 65535, 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project MAX_EOCD_SEARCH = MAX_COMMENT_LEN + EOCD_LEN, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // central directory entries 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ENTRY_SIGNATURE = 0x02014b50, 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ENTRY_LEN = 46, // CentralDirEnt len, excl. var fields 16287c71ca84533da008e9cc240224910a9d05139eDoug Zongker 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // local file header 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LFH_SIZE = 30, 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunsigned int 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectread_le_int(const unsigned char* buf) 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunsigned int 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectread_le_short(const unsigned char* buf) 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return buf[0] | (buf[1] << 8); 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectread_central_dir_values(Zipfile* file, const unsigned char* buf, int len) 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (len < EOCD_LEN) { 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // looks like ZIP file got truncated 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, " Zip EOCD: expected >= %d bytes, found %d\n", 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project EOCD_LEN, len); 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->disknum = read_le_short(&buf[0x04]); 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->diskWithCentralDir = read_le_short(&buf[0x06]); 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->entryCount = read_le_short(&buf[0x08]); 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->totalEntryCount = read_le_short(&buf[0x0a]); 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->centralDirSize = read_le_int(&buf[0x0c]); 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->centralDirOffest = read_le_int(&buf[0x10]); 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->commentLen = read_le_short(&buf[0x14]); 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (file->commentLen > 0) { 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (EOCD_LEN + file->commentLen > len) { 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "EOCD(%d) + comment(%d) exceeds len (%d)\n", 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project EOCD_LEN, file->commentLen, len); 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->comment = buf + EOCD_LEN; 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectread_central_directory_entry(Zipfile* file, Zipentry* entry, 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const unsigned char** buf, ssize_t* len) 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const unsigned char* p; 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short versionMadeBy; 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short versionToExtract; 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short gpBitFlag; 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short compressionMethod; 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short lastModFileTime; 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short lastModFileDate; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned long crc32; 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short extraFieldLength; 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short fileCommentLength; 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short diskNumberStart; 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short internalAttrs; 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned long externalAttrs; 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned long localHeaderRelOffset; 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const unsigned char* extraField; 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const unsigned char* fileComment; 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned int dataOffset; 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short lfhExtraFieldSize; 86287c71ca84533da008e9cc240224910a9d05139eDoug Zongker 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p = *buf; 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (*len < ENTRY_LEN) { 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "cde entry not large enough\n"); 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (read_le_int(&p[0x00]) != ENTRY_SIGNATURE) { 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "Whoops: didn't find expected signature\n"); 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project versionMadeBy = read_le_short(&p[0x04]); 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project versionToExtract = read_le_short(&p[0x06]); 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project gpBitFlag = read_le_short(&p[0x08]); 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry->compressionMethod = read_le_short(&p[0x0a]); 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project lastModFileTime = read_le_short(&p[0x0c]); 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project lastModFileDate = read_le_short(&p[0x0e]); 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project crc32 = read_le_int(&p[0x10]); 107287c71ca84533da008e9cc240224910a9d05139eDoug Zongker entry->compressedSize = read_le_int(&p[0x14]); 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry->uncompressedSize = read_le_int(&p[0x18]); 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry->fileNameLength = read_le_short(&p[0x1c]); 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project extraFieldLength = read_le_short(&p[0x1e]); 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fileCommentLength = read_le_short(&p[0x20]); 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project diskNumberStart = read_le_short(&p[0x22]); 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project internalAttrs = read_le_short(&p[0x24]); 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project externalAttrs = read_le_int(&p[0x26]); 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localHeaderRelOffset = read_le_int(&p[0x2a]); 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p += ENTRY_LEN; 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // filename 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (entry->fileNameLength != 0) { 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry->fileName = p; 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry->fileName = NULL; 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p += entry->fileNameLength; 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // extra field 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (extraFieldLength != 0) { 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project extraField = p; 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project extraField = NULL; 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p += extraFieldLength; 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // comment, if any 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fileCommentLength != 0) { 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fileComment = p; 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fileComment = NULL; 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p += fileCommentLength; 142287c71ca84533da008e9cc240224910a9d05139eDoug Zongker 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *buf = p; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // the size of the extraField in the central dir is how much data there is, 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // but the one in the local file header also contains some padding. 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p = file->buf + localHeaderRelOffset; 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project extraFieldLength = read_le_short(&p[0x1c]); 149287c71ca84533da008e9cc240224910a9d05139eDoug Zongker 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dataOffset = localHeaderRelOffset + LFH_SIZE 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project + entry->fileNameLength + extraFieldLength; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry->data = file->buf + dataOffset; 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("file->buf=%p entry->data=%p dataOffset=%x localHeaderRelOffset=%d " 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project "entry->fileNameLength=%d extraFieldLength=%d\n", 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->buf, entry->data, dataOffset, localHeaderRelOffset, 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry->fileNameLength, extraFieldLength); 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Find the central directory and read the contents. 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The fun thing about ZIP archives is that they may or may not be 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * readable from start to end. In some cases, notably for archives 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * that were written to stdout, the only length information is in the 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * central directory at the end of the file. 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Of course, the central directory can be followed by a variable-length 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * comment field, so we have to scan through it backwards. The comment 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * itself, plus apparently sometimes people throw random junk on the end 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * just for the fun of it. 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * This is all a little wobbly. If the wrong value ends up in the EOCD 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * area, we're hosed. This appears to be the way that everbody handles 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * it though, so we're in pretty good company if this fails. 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectread_central_dir(Zipfile *file) 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err; 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const unsigned char* buf = file->buf; 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t bufsize = file->bufsize; 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const unsigned char* eocd; 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const unsigned char* p; 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const unsigned char* start; 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t len; 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i; 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // too small to be a ZIP archive? 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (bufsize < EOCD_LEN) { 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "Length is %d -- too small\n", bufsize); 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto bail; 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // find the end-of-central-dir magic 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (bufsize > MAX_EOCD_SEARCH) { 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project start = buf + bufsize - MAX_EOCD_SEARCH; 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project start = buf; 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p = buf + bufsize - 4; 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (p >= start) { 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (*p == 0x50 && read_le_int(p) == CD_SIGNATURE) { 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project eocd = p; 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p--; 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (p < start) { 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "EOCD not found, not Zip\n"); 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto bail; 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // extract eocd values 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = read_central_dir_values(file, eocd, (buf+bufsize)-eocd); 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err != 0) { 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto bail; 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (file->disknum != 0 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project || file->diskWithCentralDir != 0 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project || file->entryCount != file->totalEntryCount) { 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "Archive spanning not supported\n"); 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto bail; 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Loop through and read the central dir entries. 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project p = buf + file->centralDirOffest; 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len = (buf+bufsize)-p; 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (i=0; i < file->totalEntryCount; i++) { 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipentry* entry = malloc(sizeof(Zipentry)); 23690764cfc76d65ae67755a375eb8ef429e44b9822Elliott Hughes memset(entry, 0, sizeof(Zipentry)); 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = read_central_directory_entry(file, entry, &p, &len); 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err != 0) { 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "read_central_directory_entry failed\n"); 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(entry); 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto bail; 243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 244287c71ca84533da008e9cc240224910a9d05139eDoug Zongker 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // add it to our list 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry->next = file->entries; 247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->entries = entry; 248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectbail: 252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 254