1 /*
2 zip_source_deflate.c -- deflate (de)compressoin routines
3 Copyright (C) 2009 Dieter Baron and Thomas Klausner
4
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <libzip@nih.at>
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in
15 the documentation and/or other materials provided with the
16 distribution.
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
19 written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "zipint.h"
40
41 struct deflate {
42 int e[2];
43
44 int eof;
45 int mem_level;
46 zip_uint64_t size;
47 char buffer[BUFSIZE];
48 z_stream zstr;
49 };
50
51 static zip_int64_t compress_read(struct zip_source *, struct deflate *,
52 void *, zip_uint64_t);
53 static zip_int64_t decompress_read(struct zip_source *, struct deflate *,
54 void *, zip_uint64_t);
55 static zip_int64_t deflate_compress(struct zip_source *, void *, void *,
56 zip_uint64_t, enum zip_source_cmd);
57 static zip_int64_t deflate_decompress(struct zip_source *, void *, void *,
58 zip_uint64_t, enum zip_source_cmd);
59 static void deflate_free(struct deflate *);
60
61
62
63 ZIP_EXTERN(struct zip_source *)
zip_source_deflate(struct zip * za,struct zip_source * src,zip_uint16_t cm,int flags)64 zip_source_deflate(struct zip *za, struct zip_source *src,
65 zip_uint16_t cm, int flags)
66 {
67 struct deflate *ctx;
68 struct zip_source *s2;
69
70 if (src == NULL || cm != ZIP_CM_DEFLATE) {
71 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
72 return NULL;
73 }
74
75 if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) {
76 _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
77 return NULL;
78 }
79
80 ctx->e[0] = ctx->e[1] = 0;
81 ctx->eof = 0;
82 if (flags & ZIP_CODEC_ENCODE) {
83 if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
84 ctx->mem_level = TORRENT_MEM_LEVEL;
85 else
86 ctx->mem_level = MAX_MEM_LEVEL;
87 }
88
89 if ((s2=zip_source_layered(za, src,
90 ((flags & ZIP_CODEC_ENCODE)
91 ? deflate_compress : deflate_decompress),
92 ctx)) == NULL) {
93 deflate_free(ctx);
94 return NULL;
95 }
96
97 return s2;
98 }
99
100
101
102 static zip_int64_t
compress_read(struct zip_source * src,struct deflate * ctx,void * data,zip_uint64_t len)103 compress_read(struct zip_source *src, struct deflate *ctx,
104 void *data, zip_uint64_t len)
105 {
106 int end, ret;
107 zip_int64_t n;
108
109 if (ctx->e[0] != 0)
110 return -1;
111
112 if (len == 0)
113 return 0;
114
115 ctx->zstr.next_out = (Bytef *)data;
116 ctx->zstr.avail_out = len;
117
118 end = 0;
119 while (!end) {
120 ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);
121
122 switch (ret) {
123 case Z_OK:
124 case Z_STREAM_END:
125 /* all ok */
126
127 if (ctx->zstr.avail_out == 0
128 || (ctx->eof && ctx->zstr.avail_in == 0))
129 end = 1;
130 break;
131
132 case Z_BUF_ERROR:
133 if (ctx->zstr.avail_in == 0) {
134 if (ctx->eof) {
135 end = 1;
136 break;
137 }
138
139 if ((n=zip_source_read(src, ctx->buffer,
140 sizeof(ctx->buffer))) < 0) {
141 zip_source_error(src, ctx->e, ctx->e+1);
142 end = 1;
143 break;
144 }
145 else if (n == 0) {
146 ctx->eof = 1;
147 ctx->size = ctx->zstr.total_in;
148 /* XXX: check against stat of src? */
149 }
150 else {
151 ctx->zstr.next_in = (Bytef *)ctx->buffer;
152 ctx->zstr.avail_in = n;
153 }
154 continue;
155 }
156 /* fallthrough */
157 case Z_NEED_DICT:
158 case Z_DATA_ERROR:
159 case Z_STREAM_ERROR:
160 case Z_MEM_ERROR:
161 ctx->e[0] = ZIP_ER_ZLIB;
162 ctx->e[1] = ret;
163
164 end = 1;
165 break;
166 }
167 }
168
169 if (ctx->zstr.avail_out < len)
170 return len - ctx->zstr.avail_out;
171
172 return (ctx->e[0] == 0) ? 0 : -1;
173 }
174
175
176
177 static zip_int64_t
decompress_read(struct zip_source * src,struct deflate * ctx,void * data,zip_uint64_t len)178 decompress_read(struct zip_source *src, struct deflate *ctx,
179 void *data, zip_uint64_t len)
180 {
181 int end, ret;
182 zip_int64_t n;
183
184 if (ctx->e[0] != 0)
185 return -1;
186
187 if (len == 0)
188 return 0;
189
190 ctx->zstr.next_out = (Bytef *)data;
191 ctx->zstr.avail_out = len;
192
193 end = 0;
194 while (!end && ctx->zstr.avail_out) {
195 ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
196
197 switch (ret) {
198 case Z_OK:
199 break;
200
201 case Z_STREAM_END:
202 ctx->eof = 1;
203 end = 1;
204 break;
205
206 case Z_BUF_ERROR:
207 if (ctx->zstr.avail_in == 0) {
208 if (ctx->eof) {
209 end = 1;
210 break;
211 }
212
213 if ((n=zip_source_read(src, ctx->buffer,
214 sizeof(ctx->buffer))) < 0) {
215 zip_source_error(src, ctx->e, ctx->e+1);
216 end = 1;
217 break;
218 }
219 else if (n == 0)
220 ctx->eof = 1;
221 else {
222 ctx->zstr.next_in = (Bytef *)ctx->buffer;
223 ctx->zstr.avail_in = n;
224 }
225 continue;
226 }
227 /* fallthrough */
228 case Z_NEED_DICT:
229 case Z_DATA_ERROR:
230 case Z_STREAM_ERROR:
231 case Z_MEM_ERROR:
232 ctx->e[0] = ZIP_ER_ZLIB;
233 ctx->e[1] = ret;
234 end = 1;
235 break;
236 }
237 }
238
239 if (ctx->zstr.avail_out < len)
240 return len - ctx->zstr.avail_out;
241
242 return (ctx->e[0] == 0) ? 0 : -1;
243 }
244
245
246
247 static zip_int64_t
deflate_compress(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)248 deflate_compress(struct zip_source *src, void *ud, void *data,
249 zip_uint64_t len, enum zip_source_cmd cmd)
250 {
251 struct deflate *ctx;
252 int ret;
253
254 ctx = (struct deflate *)ud;
255
256 switch (cmd) {
257 case ZIP_SOURCE_OPEN:
258 ctx->zstr.zalloc = Z_NULL;
259 ctx->zstr.zfree = Z_NULL;
260 ctx->zstr.opaque = NULL;
261 ctx->zstr.avail_in = 0;
262 ctx->zstr.next_in = NULL;
263 ctx->zstr.avail_out = 0;
264 ctx->zstr.next_out = NULL;
265
266 /* negative value to tell zlib not to write a header */
267 if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED,
268 -MAX_WBITS, ctx->mem_level,
269 Z_DEFAULT_STRATEGY)) != Z_OK) {
270 ctx->e[0] = ZIP_ER_ZLIB;
271 ctx->e[1] = ret;
272 return -1;
273 }
274
275 return 0;
276
277 case ZIP_SOURCE_READ:
278 return compress_read(src, ctx, data, len);
279
280 case ZIP_SOURCE_CLOSE:
281 deflateEnd(&ctx->zstr);
282 return 0;
283
284 case ZIP_SOURCE_STAT:
285 {
286 struct zip_stat *st;
287
288 st = (struct zip_stat *)data;
289
290 st->comp_method = ZIP_CM_DEFLATE;
291 st->valid |= ZIP_STAT_COMP_METHOD;
292 if (ctx->eof) {
293 st->comp_size = ctx->size;
294 st->valid |= ZIP_STAT_COMP_SIZE;
295 }
296 else
297 st->valid &= ~ZIP_STAT_COMP_SIZE;
298 }
299 return 0;
300
301 case ZIP_SOURCE_ERROR:
302 memcpy(data, ctx->e, sizeof(int)*2);
303 return sizeof(int)*2;
304
305 case ZIP_SOURCE_FREE:
306 deflate_free(ctx);
307 return 0;
308
309 default:
310 ctx->e[0] = ZIP_ER_INVAL;
311 ctx->e[1] = 0;
312 return -1;
313 }
314 }
315
316
317
318 static zip_int64_t
deflate_decompress(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)319 deflate_decompress(struct zip_source *src, void *ud, void *data,
320 zip_uint64_t len, enum zip_source_cmd cmd)
321 {
322 struct deflate *ctx;
323 zip_int64_t n;
324 int ret;
325
326 ctx = (struct deflate *)ud;
327
328 switch (cmd) {
329 case ZIP_SOURCE_OPEN:
330 if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0)
331 return ZIP_SOURCE_ERR_LOWER;
332
333 ctx->zstr.zalloc = Z_NULL;
334 ctx->zstr.zfree = Z_NULL;
335 ctx->zstr.opaque = NULL;
336 ctx->zstr.next_in = (Bytef *)ctx->buffer;
337 ctx->zstr.avail_in = n;
338
339 /* negative value to tell zlib that there is no header */
340 if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
341 ctx->e[0] = ZIP_ER_ZLIB;
342 ctx->e[1] = ret;
343
344 return -1;
345 }
346 return 0;
347
348 case ZIP_SOURCE_READ:
349 return decompress_read(src, ctx, data, len);
350
351 case ZIP_SOURCE_CLOSE:
352 inflateEnd(&ctx->zstr);
353 return 0;
354
355 case ZIP_SOURCE_STAT:
356 {
357 struct zip_stat *st;
358
359 st = (struct zip_stat *)data;
360
361 st->comp_method = ZIP_CM_STORE;
362 if (st->comp_size > 0 && st->size > 0)
363 st->comp_size = st->size;
364 }
365 return 0;
366
367 case ZIP_SOURCE_ERROR:
368 if (len < sizeof(int)*2)
369 return -1;
370
371 memcpy(data, ctx->e, sizeof(int)*2);
372 return sizeof(int)*2;
373
374 case ZIP_SOURCE_FREE:
375 /* XXX: inflateEnd if close was not called */
376 free(ctx);
377 return 0;
378
379 default:
380 ctx->e[0] = ZIP_ER_INVAL;
381 ctx->e[1] = 0;
382 return -1;
383 }
384
385 }
386
387
388
389 static void
deflate_free(struct deflate * ctx)390 deflate_free(struct deflate *ctx)
391 {
392 /* XXX: deflateEnd if close was not called */
393 free(ctx);
394 }
395