root/ext/zip/lib/zip_source_deflate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zip_source_deflate
  2. compress_read
  3. decompress_read
  4. deflate_compress
  5. deflate_decompress
  6. deflate_free

   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 }

/* [<][>][^][v][top][bottom][index][help] */