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; 82 unsigned long crc; 83 int err = 0; 84 int zerr; 85 86 memset(&zstream, 0, sizeof(zstream)); 87 zstream.zalloc = Z_NULL; 88 zstream.zfree = Z_NULL; 89 zstream.opaque = Z_NULL; 90 zstream.next_in = (void*)in; 91 zstream.avail_in = clen; 92 zstream.next_out = (Bytef*) out; 93 zstream.avail_out = unlen; 94 zstream.data_type = Z_UNKNOWN; 95 96 // Use the undocumented "negative window bits" feature to tell zlib 97 // that there's no zlib header waiting for it. 98 zerr = inflateInit2(&zstream, -MAX_WBITS); 99 if (zerr != Z_OK) { 100 return -1; 101 } 102 103 // uncompress the data 104 zerr = inflate(&zstream, Z_FINISH); 105 if (zerr != Z_STREAM_END) { 106 fprintf(stderr, "zerr=%d Z_STREAM_END=%d total_out=%lu\n", zerr, Z_STREAM_END, 107 zstream.total_out); 108 err = -1; 109 } 110 111 inflateEnd(&zstream); 112 return err; 113 } 114 115 int 116 decompress_zipentry(zipentry_t e, void* buf, int bufsize) 117 { 118 Zipentry* entry = (Zipentry*)e; 119 switch (entry->compressionMethod) 120 { 121 case STORED: 122 memcpy(buf, entry->data, entry->uncompressedSize); 123 return 0; 124 case DEFLATED: 125 return uninflate(buf, bufsize, entry->data, entry->compressedSize); 126 default: 127 return -1; 128 } 129 } 130 131 void 132 dump_zipfile(FILE* to, zipfile_t file) 133 { 134 Zipfile* zip = (Zipfile*)file; 135 Zipentry* entry = zip->entries; 136 int i; 137 138 fprintf(to, "entryCount=%d\n", zip->entryCount); 139 for (i=0; i<zip->entryCount; i++) { 140 fprintf(to, " file \""); 141 fwrite(entry->fileName, entry->fileNameLength, 1, to); 142 fprintf(to, "\"\n"); 143 entry = entry->next; 144 } 145 } 146 147 zipentry_t 148 iterate_zipfile(zipfile_t file, void** cookie) 149 { 150 Zipentry* entry = (Zipentry*)*cookie; 151 if (entry == NULL) { 152 Zipfile* zip = (Zipfile*)file; 153 *cookie = zip->entries; 154 return *cookie; 155 } else { 156 entry = entry->next; 157 *cookie = entry; 158 return entry; 159 } 160 } 161