1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <stdint.h>
15#include "memdisk.h"
16#include "conio.h"
17
18#undef DEBUG
19
20
21
22
23
24#define OF(args) args
25#define STATIC static
26
27#define memzero(s, n) memset ((s), 0, (n))
28
29typedef uint8_t uch;
30typedef uint16_t ush;
31typedef uint32_t ulg;
32
33#define WSIZE 0x8000
34
35
36static uch *inbuf;
37static uch window[WSIZE];
38
39static unsigned insize;
40static unsigned inbytes;
41static unsigned outcnt;
42
43
44#define ASCII_FLAG 0x01
45#define CONTINUATION 0x02
46#define EXTRA_FIELD 0x04
47#define ORIG_NAME 0x08
48#define COMMENT 0x10
49#define ENCRYPTED 0x20
50#define RESERVED 0xC0
51
52
53#ifdef DEBUG
54# define Assert(cond,msg) {if(!(cond)) error(msg);}
55# define Trace(x) fprintf x
56# define Tracev(x) {if (verbose) fprintf x ;}
57# define Tracevv(x) {if (verbose>1) fprintf x ;}
58# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
59# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
60#else
61# define Assert(cond,msg)
62# define Trace(x)
63# define Tracev(x)
64# define Tracevv(x)
65# define Tracec(c,x)
66# define Tracecv(c,x)
67#endif
68
69static int fill_inbuf(void);
70static void flush_window(void);
71static void error(char *m);
72static void gzip_mark(void **);
73static void gzip_release(void **);
74
75static ulg crc_32_tab[256];
76
77
78static inline uch get_byte(void)
79{
80 if (inbytes) {
81 uch b = *inbuf++;
82 inbytes--;
83 return b;
84 } else {
85 return fill_inbuf();
86 }
87}
88
89
90static inline void unget_byte(void)
91{
92 inbytes++;
93 inbuf--;
94}
95
96static ulg bytes_out = 0;
97static uch *output_data;
98static ulg output_size;
99
100static void *malloc(int size);
101static void free(void *where);
102
103static ulg free_mem_ptr, free_mem_end_ptr;
104
105#include "inflate.c"
106
107static void *malloc(int size)
108{
109 void *p;
110
111 if (size < 0)
112 error("malloc error");
113
114 free_mem_ptr = (free_mem_ptr + 3) & ~3;
115
116 p = (void *)free_mem_ptr;
117 free_mem_ptr += size;
118
119 if (free_mem_ptr >= free_mem_end_ptr)
120 error("out of memory");
121
122 return p;
123}
124
125static void free(void *where)
126{
127
128 (void)where;
129}
130
131static void gzip_mark(void **ptr)
132{
133 *ptr = (void *)free_mem_ptr;
134}
135
136static void gzip_release(void **ptr)
137{
138 free_mem_ptr = (long)*ptr;
139}
140
141
142
143
144
145static int fill_inbuf(void)
146{
147
148
149 die("failed\nDecompression error: ran out of input data\n");
150}
151
152
153
154
155
156static void flush_window(void)
157{
158 ulg c = crc;
159 unsigned n;
160 uch *in, *out, ch;
161
162 if (bytes_out + outcnt > output_size)
163 error("output buffer overrun");
164
165 in = window;
166 out = output_data;
167 for (n = 0; n < outcnt; n++) {
168 ch = *out++ = *in++;
169 c = crc_32_tab[(c ^ ch) & 0xff] ^ (c >> 8);
170 }
171 crc = c;
172 output_data = out;
173 bytes_out += (ulg) outcnt;
174 outcnt = 0;
175}
176
177static void error(char *x)
178{
179 die("failed\nDecompression error: %s\n", x);
180}
181
182
183struct gzip_header {
184 uint16_t magic;
185 uint8_t method;
186 uint8_t flags;
187 uint32_t timestamp;
188 uint8_t extra_flags;
189 uint8_t os_type;
190} __attribute__ ((packed));
191
192
193
194struct gzip_trailer {
195 uint32_t crc;
196 uint32_t dbytes;
197} __attribute__ ((packed));
198
199
200
201
202struct pkzip_header {
203 uint32_t magic;
204 uint16_t version;
205 uint16_t flags;
206 uint16_t method;
207 uint16_t modified_time;
208 uint16_t modified_date;
209 uint32_t crc;
210 uint32_t zbytes;
211 uint32_t dbytes;
212 uint16_t filename_len;
213 uint16_t extra_len;
214} __attribute__ ((packed));
215
216
217
218
219#define ASCII_FLAG 0x01
220#define CONTINUATION 0x02
221#define EXTRA_FIELD 0x04
222#define ORIG_NAME 0x08
223#define COMMENT 0x10
224#define ENCRYPTED 0x20
225#define RESERVED 0xC0
226
227
228#define PK_ENCRYPTED 0x01
229#define PK_DATADESC 0x08
230
231#define PK_UNSUPPORTED 0xFFF0
232
233
234
235
236
237
238int check_zip(void *indata, uint32_t size, uint32_t * zbytes_p,
239 uint32_t * dbytes_p, uint32_t * orig_crc, uint32_t * offset_p)
240{
241 struct gzip_header *gzh = (struct gzip_header *)indata;
242 struct pkzip_header *pkzh = (struct pkzip_header *)indata;
243 uint32_t offset;
244
245 if (gzh->magic == 0x8b1f) {
246 struct gzip_trailer *gzt = indata + size - sizeof(struct gzip_trailer);
247
248 if (gzh->method != 8) {
249 error("gzip file uses invalid method");
250 return -1;
251 }
252 if (gzh->flags & ENCRYPTED) {
253 error("gzip file is encrypted; not supported");
254 return -1;
255 }
256 if (gzh->flags & CONTINUATION) {
257 error("gzip file is a continuation file; not supported");
258 return -1;
259 }
260 if (gzh->flags & RESERVED) {
261 error("gzip file has unsupported flags");
262 return -1;
263 }
264 offset = sizeof(*gzh);
265 if (gzh->flags & EXTRA_FIELD) {
266
267 unsigned len = *(unsigned *)(indata + offset);
268 offset += 2 + len;
269 }
270 if (gzh->flags & ORIG_NAME) {
271
272 uint8_t *p = indata;
273 while (p[offset] != 0 && offset < size) {
274 offset++;
275 }
276 offset++;
277 }
278
279 if (gzh->flags & COMMENT) {
280
281 uint8_t *p = indata;
282 while (p[offset] != 0 && offset < size) {
283 offset++;
284 }
285 offset++;
286 }
287
288 if (offset > size) {
289 error("gzip file corrupt");
290 return -1;
291 }
292 *zbytes_p = size - offset - sizeof(struct gzip_trailer);
293 *dbytes_p = gzt->dbytes;
294 *orig_crc = gzt->crc;
295 *offset_p = offset;
296 return 0;
297 } else if (pkzh->magic == 0x04034b50UL) {
298
299
300 offset = sizeof(*pkzh);
301 if (pkzh->flags & PK_ENCRYPTED) {
302 error("pkzip file is encrypted; not supported");
303 return -1;
304 }
305 if (pkzh->flags & PK_DATADESC) {
306 error("pkzip file uses data_descriptor field; not supported");
307 return -1;
308 }
309 if (pkzh->flags & PK_UNSUPPORTED) {
310 error("pkzip file has unsupported flags");
311 return -1;
312 }
313
314
315 if (pkzh->method != 8) {
316 error("pkzip file uses invalid method");
317 return -1;
318 }
319
320 offset = sizeof(*pkzh);
321
322 offset += pkzh->filename_len;
323
324 offset += pkzh->extra_len;
325
326 if (offset + pkzh->zbytes > size) {
327 error("pkzip file corrupt");
328 return -1;
329 }
330
331 *zbytes_p = pkzh->zbytes;
332 *dbytes_p = pkzh->dbytes;
333 *orig_crc = pkzh->crc;
334 *offset_p = offset;
335 return 0;
336 } else {
337
338 return -1;
339 }
340
341 error("Internal error in check_zip");
342 return -1;
343}
344
345
346
347
348
349
350extern void _end;
351
352static char heap[65536];
353
354void *unzip(void *indata, uint32_t zbytes, uint32_t dbytes,
355 uint32_t orig_crc, void *target)
356{
357
358 free_mem_ptr = (size_t)heap;
359 free_mem_end_ptr = (size_t)heap + sizeof heap;
360
361
362 inbuf = indata;
363
364
365
366 insize = inbytes = zbytes + 4;
367
368
369 outcnt = 0;
370 output_data = target;
371 output_size = dbytes;
372 bytes_out = 0;
373
374 makecrc();
375 gunzip();
376
377
378 if (inbytes != 4)
379 error("compressed data length error");
380
381
382 if (bytes_out != dbytes)
383 error("uncompressed data length error");
384
385 if (orig_crc != CRC_VALUE)
386 error("crc error");
387
388 puts("ok\n");
389
390 return target;
391}
392