platform_system_core/libzipfile/zipfile.c
Doug Zongker 287c71ca84 fix decompression bug in fastboot
fastboot passes the *uncompressed* length of the file as the length of
the input to the inflate() call, which happens to work unless the
compressed data is actually larger than the uncompressed data (which
it can be for very small files).  Fix this to pass the correct
compressed length down to the inflate call.
2009-06-16 17:36:04 -07:00

160 lines
3.4 KiB
C

#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;
}
}