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 int err = 0; 83 int zerr; 84 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; 90 zstream.avail_in = clen; 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 } 101 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 } 109 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 } 160