4
|
1 /* |
|
2 zip_source_deflate.c -- deflate (de)compressoin routines |
|
3 Copyright (C) 2009-2015 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 #include <stdlib.h> |
|
35 #include <string.h> |
|
36 #include <limits.h> |
|
37 |
|
38 #include "zipint.h" |
|
39 |
|
40 struct deflate { |
|
41 zip_error_t error; |
|
42 |
|
43 bool eof; |
|
44 bool can_store; |
|
45 bool is_stored; |
|
46 int mem_level; |
|
47 zip_uint64_t size; |
|
48 zip_uint8_t buffer[BUFSIZE]; |
|
49 z_stream zstr; |
|
50 }; |
|
51 |
|
52 static zip_int64_t compress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t); |
|
53 static zip_int64_t decompress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t); |
|
54 static zip_int64_t deflate_compress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); |
|
55 static zip_int64_t deflate_decompress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); |
|
56 static void deflate_free(struct deflate *); |
|
57 |
|
58 |
|
59 zip_source_t * |
|
60 zip_source_deflate(zip_t *za, zip_source_t *src, zip_int32_t cm, int flags) |
|
61 { |
|
62 struct deflate *ctx; |
|
63 zip_source_t *s2; |
|
64 |
|
65 if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) { |
|
66 zip_error_set(&za->error, ZIP_ER_INVAL, 0); |
|
67 return NULL; |
|
68 } |
|
69 |
|
70 if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) { |
|
71 zip_error_set(&za->error, ZIP_ER_MEMORY, 0); |
|
72 return NULL; |
|
73 } |
|
74 |
|
75 zip_error_init(&ctx->error); |
|
76 ctx->eof = false; |
|
77 ctx->is_stored = false; |
|
78 ctx->can_store = ZIP_CM_IS_DEFAULT(cm); |
|
79 if (flags & ZIP_CODEC_ENCODE) { |
|
80 ctx->mem_level = MAX_MEM_LEVEL; |
|
81 } |
|
82 |
|
83 if ((s2=zip_source_layered(za, src, |
|
84 ((flags & ZIP_CODEC_ENCODE) |
|
85 ? deflate_compress : deflate_decompress), |
|
86 ctx)) == NULL) { |
|
87 deflate_free(ctx); |
|
88 return NULL; |
|
89 } |
|
90 |
|
91 return s2; |
|
92 } |
|
93 |
|
94 |
|
95 static zip_int64_t |
|
96 compress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len) |
|
97 { |
|
98 int end, ret; |
|
99 zip_int64_t n; |
|
100 zip_uint64_t out_offset; |
|
101 uInt out_len; |
|
102 |
|
103 if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) |
|
104 return -1; |
|
105 |
|
106 if (len == 0 || ctx->is_stored) { |
|
107 return 0; |
|
108 } |
|
109 |
|
110 out_offset = 0; |
|
111 out_len = (uInt)ZIP_MIN(UINT_MAX, len); |
|
112 ctx->zstr.next_out = (Bytef *)data; |
|
113 ctx->zstr.avail_out = out_len; |
|
114 |
|
115 end = 0; |
|
116 while (!end) { |
|
117 ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0); |
|
118 |
|
119 switch (ret) { |
|
120 case Z_STREAM_END: |
|
121 if (ctx->can_store && ctx->zstr.total_in <= ctx->zstr.total_out) { |
|
122 ctx->is_stored = true; |
|
123 ctx->size = ctx->zstr.total_in; |
|
124 memcpy(data, ctx->buffer, ctx->size); |
|
125 return (zip_int64_t)ctx->size; |
|
126 } |
|
127 /* fallthrough */ |
|
128 case Z_OK: |
|
129 /* all ok */ |
|
130 |
|
131 if (ctx->zstr.avail_out == 0) { |
|
132 out_offset += out_len; |
|
133 if (out_offset < len) { |
|
134 out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset); |
|
135 ctx->zstr.next_out = (Bytef *)data+out_offset; |
|
136 ctx->zstr.avail_out = out_len; |
|
137 } |
|
138 else { |
|
139 ctx->can_store = false; |
|
140 end = 1; |
|
141 } |
|
142 } |
|
143 else if (ctx->eof && ctx->zstr.avail_in == 0) |
|
144 end = 1; |
|
145 break; |
|
146 |
|
147 case Z_BUF_ERROR: |
|
148 if (ctx->zstr.avail_in == 0) { |
|
149 if (ctx->eof) { |
|
150 end = 1; |
|
151 break; |
|
152 } |
|
153 |
|
154 if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { |
|
155 _zip_error_set_from_source(&ctx->error, src); |
|
156 end = 1; |
|
157 break; |
|
158 } |
|
159 else if (n == 0) { |
|
160 ctx->eof = true; |
|
161 /* TODO: check against stat of src? */ |
|
162 ctx->size = ctx->zstr.total_in; |
|
163 } |
|
164 else { |
|
165 if (ctx->zstr.total_in > 0) { |
|
166 /* we overwrote a previously filled ctx->buffer */ |
|
167 ctx->can_store = false; |
|
168 } |
|
169 ctx->zstr.next_in = (Bytef *)ctx->buffer; |
|
170 ctx->zstr.avail_in = (uInt)n; |
|
171 } |
|
172 continue; |
|
173 } |
|
174 /* fallthrough */ |
|
175 case Z_NEED_DICT: |
|
176 case Z_DATA_ERROR: |
|
177 case Z_STREAM_ERROR: |
|
178 case Z_MEM_ERROR: |
|
179 zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); |
|
180 |
|
181 end = 1; |
|
182 break; |
|
183 } |
|
184 } |
|
185 |
|
186 if (ctx->zstr.avail_out < len) { |
|
187 ctx->can_store = false; |
|
188 return (zip_int64_t)(len - ctx->zstr.avail_out); |
|
189 } |
|
190 |
|
191 return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; |
|
192 } |
|
193 |
|
194 |
|
195 static zip_int64_t |
|
196 decompress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len) |
|
197 { |
|
198 int end, ret; |
|
199 zip_int64_t n; |
|
200 zip_uint64_t out_offset; |
|
201 uInt out_len; |
|
202 |
|
203 if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) |
|
204 return -1; |
|
205 |
|
206 if (len == 0) |
|
207 return 0; |
|
208 |
|
209 out_offset = 0; |
|
210 out_len = (uInt)ZIP_MIN(UINT_MAX, len); |
|
211 ctx->zstr.next_out = (Bytef *)data; |
|
212 ctx->zstr.avail_out = out_len; |
|
213 |
|
214 end = 0; |
|
215 while (!end) { |
|
216 ret = inflate(&ctx->zstr, Z_SYNC_FLUSH); |
|
217 |
|
218 switch (ret) { |
|
219 case Z_OK: |
|
220 if (ctx->zstr.avail_out == 0) { |
|
221 out_offset += out_len; |
|
222 if (out_offset < len) { |
|
223 out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset); |
|
224 ctx->zstr.next_out = (Bytef *)data+out_offset; |
|
225 ctx->zstr.avail_out = out_len; |
|
226 } |
|
227 else { |
|
228 end = 1; |
|
229 } |
|
230 } |
|
231 break; |
|
232 |
|
233 case Z_STREAM_END: |
|
234 ctx->eof = 1; |
|
235 end = 1; |
|
236 break; |
|
237 |
|
238 case Z_BUF_ERROR: |
|
239 if (ctx->zstr.avail_in == 0) { |
|
240 if (ctx->eof) { |
|
241 end = 1; |
|
242 break; |
|
243 } |
|
244 |
|
245 if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { |
|
246 _zip_error_set_from_source(&ctx->error, src); |
|
247 end = 1; |
|
248 break; |
|
249 } |
|
250 else if (n == 0) { |
|
251 ctx->eof = 1; |
|
252 } |
|
253 else { |
|
254 ctx->zstr.next_in = (Bytef *)ctx->buffer; |
|
255 ctx->zstr.avail_in = (uInt)n; |
|
256 } |
|
257 continue; |
|
258 } |
|
259 /* fallthrough */ |
|
260 case Z_NEED_DICT: |
|
261 case Z_DATA_ERROR: |
|
262 case Z_STREAM_ERROR: |
|
263 case Z_MEM_ERROR: |
|
264 zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); |
|
265 end = 1; |
|
266 break; |
|
267 } |
|
268 } |
|
269 |
|
270 if (ctx->zstr.avail_out < len) |
|
271 return (zip_int64_t)(len - ctx->zstr.avail_out); |
|
272 |
|
273 return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; |
|
274 } |
|
275 |
|
276 |
|
277 static zip_int64_t |
|
278 deflate_compress(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) |
|
279 { |
|
280 struct deflate *ctx; |
|
281 int ret; |
|
282 |
|
283 ctx = (struct deflate *)ud; |
|
284 |
|
285 switch (cmd) { |
|
286 case ZIP_SOURCE_OPEN: |
|
287 ctx->zstr.zalloc = Z_NULL; |
|
288 ctx->zstr.zfree = Z_NULL; |
|
289 ctx->zstr.opaque = NULL; |
|
290 ctx->zstr.avail_in = 0; |
|
291 ctx->zstr.next_in = NULL; |
|
292 ctx->zstr.avail_out = 0; |
|
293 ctx->zstr.next_out = NULL; |
|
294 |
|
295 /* negative value to tell zlib not to write a header */ |
|
296 if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY)) != Z_OK) { |
|
297 zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); |
|
298 return -1; |
|
299 } |
|
300 |
|
301 return 0; |
|
302 |
|
303 case ZIP_SOURCE_READ: |
|
304 return compress_read(src, ctx, data, len); |
|
305 |
|
306 case ZIP_SOURCE_CLOSE: |
|
307 deflateEnd(&ctx->zstr); |
|
308 return 0; |
|
309 |
|
310 case ZIP_SOURCE_STAT: |
|
311 { |
|
312 zip_stat_t *st; |
|
313 |
|
314 st = (zip_stat_t *)data; |
|
315 |
|
316 st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_DEFLATE; |
|
317 st->valid |= ZIP_STAT_COMP_METHOD; |
|
318 if (ctx->eof) { |
|
319 st->comp_size = ctx->size; |
|
320 st->valid |= ZIP_STAT_COMP_SIZE; |
|
321 } |
|
322 else |
|
323 st->valid &= ~ZIP_STAT_COMP_SIZE; |
|
324 } |
|
325 return 0; |
|
326 |
|
327 case ZIP_SOURCE_ERROR: |
|
328 return zip_error_to_data(&ctx->error, data, len); |
|
329 |
|
330 case ZIP_SOURCE_FREE: |
|
331 deflate_free(ctx); |
|
332 return 0; |
|
333 |
|
334 case ZIP_SOURCE_SUPPORTS: |
|
335 return ZIP_SOURCE_SUPPORTS_READABLE; |
|
336 |
|
337 default: |
|
338 zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); |
|
339 return -1; |
|
340 } |
|
341 } |
|
342 |
|
343 |
|
344 static zip_int64_t |
|
345 deflate_decompress(zip_source_t *src, void *ud, void *data, |
|
346 zip_uint64_t len, zip_source_cmd_t cmd) |
|
347 { |
|
348 struct deflate *ctx; |
|
349 zip_int64_t n; |
|
350 int ret; |
|
351 |
|
352 ctx = (struct deflate *)ud; |
|
353 |
|
354 switch (cmd) { |
|
355 case ZIP_SOURCE_OPEN: |
|
356 if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { |
|
357 _zip_error_set_from_source(&ctx->error, src); |
|
358 return -1; |
|
359 } |
|
360 |
|
361 ctx->zstr.zalloc = Z_NULL; |
|
362 ctx->zstr.zfree = Z_NULL; |
|
363 ctx->zstr.opaque = NULL; |
|
364 ctx->zstr.next_in = (Bytef *)ctx->buffer; |
|
365 ctx->zstr.avail_in = (uInt)n; |
|
366 |
|
367 /* negative value to tell zlib that there is no header */ |
|
368 if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) { |
|
369 zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); |
|
370 return -1; |
|
371 } |
|
372 return 0; |
|
373 |
|
374 case ZIP_SOURCE_READ: |
|
375 return decompress_read(src, ctx, data, len); |
|
376 |
|
377 case ZIP_SOURCE_CLOSE: |
|
378 inflateEnd(&ctx->zstr); |
|
379 return 0; |
|
380 |
|
381 case ZIP_SOURCE_STAT: |
|
382 { |
|
383 zip_stat_t *st; |
|
384 |
|
385 st = (zip_stat_t *)data; |
|
386 |
|
387 st->comp_method = ZIP_CM_STORE; |
|
388 if (st->comp_size > 0 && st->size > 0) |
|
389 st->comp_size = st->size; |
|
390 |
|
391 return 0; |
|
392 } |
|
393 |
|
394 case ZIP_SOURCE_ERROR: |
|
395 return zip_error_to_data(&ctx->error, data, len); |
|
396 |
|
397 case ZIP_SOURCE_FREE: |
|
398 free(ctx); |
|
399 return 0; |
|
400 |
|
401 case ZIP_SOURCE_SUPPORTS: |
|
402 return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); |
|
403 |
|
404 default: |
|
405 zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); |
|
406 return -1; |
|
407 } |
|
408 } |
|
409 |
|
410 |
|
411 static void |
|
412 deflate_free(struct deflate *ctx) |
|
413 { |
|
414 free(ctx); |
|
415 } |