Annotation of embedaddon/php/ext/zip/lib/zip_source_deflate.c, revision 1.1.1.1
1.1 misho 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 *)
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
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
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
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
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
390: deflate_free(struct deflate *ctx)
391: {
392: /* XXX: deflateEnd if close was not called */
393: free(ctx);
394: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>