1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <zipfile/zipfile.h> 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "private.h" 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <zlib.h> 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DEF_MEM_LEVEL 8 // normally in zutil.h? 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectzipfile_t 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinit_zipfile(const void* data, size_t size) 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err; 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipfile *file = malloc(sizeof(Zipfile)); 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (file == NULL) return NULL; 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(file, 0, sizeof(Zipfile)); 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->buf = data; 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project file->bufsize = size; 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = read_central_dir(file); 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err != 0) goto fail; 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return file; 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail: 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(file); 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectrelease_zipfile(zipfile_t f) 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipfile* file = (Zipfile*)f; 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipentry* entry = file->entries; 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (entry) { 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipentry* next = entry->next; 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(entry); 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry = next; 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(file); 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectzipentry_t 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectlookup_zipentry(zipfile_t f, const char* entryName) 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipfile* file = (Zipfile*)f; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipentry* entry = file->entries; 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (entry) { 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (0 == memcmp(entryName, entry->fileName, entry->fileNameLength)) { 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return entry; 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry = entry->next; 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectsize_t 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectget_zipentry_size(zipentry_t entry) 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ((Zipentry*)entry)->uncompressedSize; 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectchar* 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectget_zipentry_name(zipentry_t entry) 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipentry* e = (Zipentry*)entry; 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int l = e->fileNameLength; 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char* s = malloc(l+1); 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(s, e->fileName, l); 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project s[l] = '\0'; 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return s; 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectenum { 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project STORED = 0, 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DEFLATED = 8 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectuninflate(unsigned char* out, int unlen, const unsigned char* in, int clen) 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project z_stream zstream; 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned long crc; 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int err = 0; 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int zerr; 85287c71ca84533da008e9cc240224910a9d05139eDoug Zongker 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&zstream, 0, sizeof(zstream)); 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zstream.zalloc = Z_NULL; 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zstream.zfree = Z_NULL; 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zstream.opaque = Z_NULL; 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zstream.next_in = (void*)in; 91287c71ca84533da008e9cc240224910a9d05139eDoug Zongker zstream.avail_in = clen; 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zstream.next_out = (Bytef*) out; 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zstream.avail_out = unlen; 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zstream.data_type = Z_UNKNOWN; 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Use the undocumented "negative window bits" feature to tell zlib 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // that there's no zlib header waiting for it. 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zerr = inflateInit2(&zstream, -MAX_WBITS); 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (zerr != Z_OK) { 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 102287c71ca84533da008e9cc240224910a9d05139eDoug Zongker 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // uncompress the data 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zerr = inflate(&zstream, Z_FINISH); 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (zerr != Z_STREAM_END) { 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "zerr=%d Z_STREAM_END=%d total_out=%lu\n", zerr, Z_STREAM_END, 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project zstream.total_out); 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = -1; 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 110287c71ca84533da008e9cc240224910a9d05139eDoug Zongker 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project inflateEnd(&zstream); 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return err; 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdecompress_zipentry(zipentry_t e, void* buf, int bufsize) 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipentry* entry = (Zipentry*)e; 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch (entry->compressionMethod) 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project { 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case STORED: 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(buf, entry->data, entry->uncompressedSize); 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case DEFLATED: 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return uninflate(buf, bufsize, entry->data, entry->compressedSize); 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdump_zipfile(FILE* to, zipfile_t file) 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipfile* zip = (Zipfile*)file; 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipentry* entry = zip->entries; 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i; 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(to, "entryCount=%d\n", zip->entryCount); 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (i=0; i<zip->entryCount; i++) { 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(to, " file \""); 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fwrite(entry->fileName, entry->fileNameLength, 1, to); 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(to, "\"\n"); 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry = entry->next; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectzipentry_t 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectiterate_zipfile(zipfile_t file, void** cookie) 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipentry* entry = (Zipentry*)*cookie; 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (entry == NULL) { 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Zipfile* zip = (Zipfile*)file; 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *cookie = zip->entries; 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return *cookie; 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project entry = entry->next; 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *cookie = entry; 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return entry; 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 161