blob: b903fcf5af63f44aef57c19c4d8246e84994eba3 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001#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
9zipfile_t
10init_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;
24fail:
25 free(file);
26 return NULL;
27}
28
29void
30release_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
42zipentry_t
43lookup_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
56size_t
57get_zipentry_size(zipentry_t entry)
58{
59 return ((Zipentry*)entry)->uncompressedSize;
60}
61
62char*
63get_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
73enum {
74 STORED = 0,
75 DEFLATED = 8
76};
77
78static int
79uninflate(unsigned char* out, int unlen, const unsigned char* in, int clen)
80{
81 z_stream zstream;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080082 int err = 0;
83 int zerr;
Doug Zongker287c71c2009-06-16 17:36:04 -070084
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080085 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;
Doug Zongker287c71c2009-06-16 17:36:04 -070090 zstream.avail_in = clen;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080091 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 }
Doug Zongker287c71c2009-06-16 17:36:04 -0700101
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 // 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 }
Doug Zongker287c71c2009-06-16 17:36:04 -0700109
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800110 inflateEnd(&zstream);
111 return err;
112}
113
114int
115decompress_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
130void
131dump_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
146zipentry_t
147iterate_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}