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