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 struct zip_source *
zip_source_deflate(struct zip * za,struct zip_source * src,zip_int32_t cm,int flags)64 zip_source_deflate(struct zip *za, struct zip_source *src,
65 zip_int32_t cm, int flags)
66 {
67 struct deflate *ctx;
68 struct zip_source *s2;
69
70 if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) {
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 = (uInt)len; /* TODO: check for overflow */
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, sizeof(ctx->buffer))) < 0) {
140 zip_source_error(src, ctx->e, ctx->e+1);
141 end = 1;
142 break;
143 }
144 else if (n == 0) {
145 ctx->eof = 1;
146 ctx->size = ctx->zstr.total_in;
147 /* TODO: check against stat of src? */
148 }
149 else {
150 ctx->zstr.next_in = (Bytef *)ctx->buffer;
151 ctx->zstr.avail_in = (uInt)n;
152 }
153 continue;
154 }
155 /* fallthrough */
156 case Z_NEED_DICT:
157 case Z_DATA_ERROR:
158 case Z_STREAM_ERROR:
159 case Z_MEM_ERROR:
160 ctx->e[0] = ZIP_ER_ZLIB;
161 ctx->e[1] = ret;
162
163 end = 1;
164 break;
165 }
166 }
167
168 if (ctx->zstr.avail_out < len)
169 return (zip_int64_t)(len - ctx->zstr.avail_out);
170
171 return (ctx->e[0] == 0) ? 0 : -1;
172 }
173
174
175
176 static zip_int64_t
decompress_read(struct zip_source * src,struct deflate * ctx,void * data,zip_uint64_t len)177 decompress_read(struct zip_source *src, struct deflate *ctx,
178 void *data, zip_uint64_t len)
179 {
180 int end, ret;
181 zip_int64_t n;
182
183 if (ctx->e[0] != 0)
184 return -1;
185
186 if (len == 0)
187 return 0;
188
189 ctx->zstr.next_out = (Bytef *)data;
190 ctx->zstr.avail_out = (uInt)len; /* TODO: check for overflow */
191
192 end = 0;
193 while (!end && ctx->zstr.avail_out) {
194 ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
195
196 switch (ret) {
197 case Z_OK:
198 break;
199
200 case Z_STREAM_END:
201 ctx->eof = 1;
202 end = 1;
203 break;
204
205 case Z_BUF_ERROR:
206 if (ctx->zstr.avail_in == 0) {
207 if (ctx->eof) {
208 end = 1;
209 break;
210 }
211
212 if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
213 zip_source_error(src, ctx->e, ctx->e+1);
214 end = 1;
215 break;
216 }
217 else if (n == 0)
218 ctx->eof = 1;
219 else {
220 ctx->zstr.next_in = (Bytef *)ctx->buffer;
221 ctx->zstr.avail_in = (uInt)n;
222 }
223 continue;
224 }
225 /* fallthrough */
226 case Z_NEED_DICT:
227 case Z_DATA_ERROR:
228 case Z_STREAM_ERROR:
229 case Z_MEM_ERROR:
230 ctx->e[0] = ZIP_ER_ZLIB;
231 ctx->e[1] = ret;
232 end = 1;
233 break;
234 }
235 }
236
237 if (ctx->zstr.avail_out < len)
238 return (zip_int64_t)(len - ctx->zstr.avail_out);
239
240 return (ctx->e[0] == 0) ? 0 : -1;
241 }
242
243
244
245 static zip_int64_t
deflate_compress(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)246 deflate_compress(struct zip_source *src, void *ud, void *data,
247 zip_uint64_t len, enum zip_source_cmd cmd)
248 {
249 struct deflate *ctx;
250 int ret;
251
252 ctx = (struct deflate *)ud;
253
254 switch (cmd) {
255 case ZIP_SOURCE_OPEN:
256 ctx->zstr.zalloc = Z_NULL;
257 ctx->zstr.zfree = Z_NULL;
258 ctx->zstr.opaque = NULL;
259 ctx->zstr.avail_in = 0;
260 ctx->zstr.next_in = NULL;
261 ctx->zstr.avail_out = 0;
262 ctx->zstr.next_out = NULL;
263
264 /* negative value to tell zlib not to write a header */
265 if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED,
266 -MAX_WBITS, ctx->mem_level,
267 Z_DEFAULT_STRATEGY)) != Z_OK) {
268 ctx->e[0] = ZIP_ER_ZLIB;
269 ctx->e[1] = ret;
270 return -1;
271 }
272
273 return 0;
274
275 case ZIP_SOURCE_READ:
276 return compress_read(src, ctx, data, len);
277
278 case ZIP_SOURCE_CLOSE:
279 deflateEnd(&ctx->zstr);
280 return 0;
281
282 case ZIP_SOURCE_STAT:
283 {
284 struct zip_stat *st;
285
286 st = (struct zip_stat *)data;
287
288 st->comp_method = ZIP_CM_DEFLATE;
289 st->valid |= ZIP_STAT_COMP_METHOD;
290 if (ctx->eof) {
291 st->comp_size = ctx->size;
292 st->valid |= ZIP_STAT_COMP_SIZE;
293 }
294 else
295 st->valid &= ~ZIP_STAT_COMP_SIZE;
296 }
297 return 0;
298
299 case ZIP_SOURCE_ERROR:
300 memcpy(data, ctx->e, sizeof(int)*2);
301 return sizeof(int)*2;
302
303 case ZIP_SOURCE_FREE:
304 deflate_free(ctx);
305 return 0;
306
307 default:
308 ctx->e[0] = ZIP_ER_INVAL;
309 ctx->e[1] = 0;
310 return -1;
311 }
312 }
313
314
315
316 static zip_int64_t
deflate_decompress(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)317 deflate_decompress(struct zip_source *src, void *ud, void *data,
318 zip_uint64_t len, enum zip_source_cmd cmd)
319 {
320 struct deflate *ctx;
321 zip_int64_t n;
322 int ret;
323
324 ctx = (struct deflate *)ud;
325
326 switch (cmd) {
327 case ZIP_SOURCE_OPEN:
328 if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0)
329 return ZIP_SOURCE_ERR_LOWER;
330
331 ctx->zstr.zalloc = Z_NULL;
332 ctx->zstr.zfree = Z_NULL;
333 ctx->zstr.opaque = NULL;
334 ctx->zstr.next_in = (Bytef *)ctx->buffer;
335 ctx->zstr.avail_in = (uInt)n /* TODO: check for overflow */;
336
337 /* negative value to tell zlib that there is no header */
338 if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
339 ctx->e[0] = ZIP_ER_ZLIB;
340 ctx->e[1] = ret;
341
342 return -1;
343 }
344 return 0;
345
346 case ZIP_SOURCE_READ:
347 return decompress_read(src, ctx, data, len);
348
349 case ZIP_SOURCE_CLOSE:
350 inflateEnd(&ctx->zstr);
351 return 0;
352
353 case ZIP_SOURCE_STAT:
354 {
355 struct zip_stat *st;
356
357 st = (struct zip_stat *)data;
358
359 st->comp_method = ZIP_CM_STORE;
360 if (st->comp_size > 0 && st->size > 0)
361 st->comp_size = st->size;
362 }
363 return 0;
364
365 case ZIP_SOURCE_ERROR:
366 if (len < sizeof(int)*2)
367 return -1;
368
369 memcpy(data, ctx->e, sizeof(int)*2);
370 return sizeof(int)*2;
371
372 case ZIP_SOURCE_FREE:
373 /* TODO: inflateEnd if close was not called */
374 free(ctx);
375 return 0;
376
377 default:
378 ctx->e[0] = ZIP_ER_INVAL;
379 ctx->e[1] = 0;
380 return -1;
381 }
382
383 }
384
385
386
387 static void
deflate_free(struct deflate * ctx)388 deflate_free(struct deflate *ctx)
389 {
390 /* TODO: deflateEnd if close was not called */
391 free(ctx);
392 }
393