Home | History | Annotate | Download | only in libzipfile
      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