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 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 *
  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
 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
 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
 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
 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
 388 deflate_free(struct deflate *ctx)
 389 {
 390     /* TODO: deflateEnd if close was not called */
 391     free(ctx);
 392 }

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