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