Annotation of embedaddon/php/ext/zip/lib/zip_source_deflate.c, revision 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>