LCOV - code coverage report
Current view: top level - g10 - compress.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 134 165 81.2 %
Date: 2015-11-05 17:10:59 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* compress.c - compress filter
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
       3             :  *               2003, 2006, 2010 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : /* Note that the code in compress-bz2.c is nearly identical to the
      22             :    code here, so if you fix a bug here, look there to see if a
      23             :    matching bug needs to be fixed.  I tried to have one set of
      24             :    functions that could do ZIP, ZLIB, and BZIP2, but it became
      25             :    dangerously unreadable with #ifdefs and if(algo) -dshaw */
      26             : 
      27             : #include <config.h>
      28             : #include <stdio.h>
      29             : #include <stdlib.h>
      30             : #include <string.h>
      31             : #include <unistd.h>
      32             : #include <assert.h>
      33             : #include <errno.h>
      34             : #ifdef HAVE_ZIP
      35             : # include <zlib.h>
      36             : # if defined(__riscos__) && defined(USE_ZLIBRISCOS)
      37             : #  include "zlib-riscos.h"
      38             : # endif
      39             : #endif
      40             : 
      41             : #include "gpg.h"
      42             : #include "util.h"
      43             : #include "packet.h"
      44             : #include "filter.h"
      45             : #include "main.h"
      46             : #include "options.h"
      47             : 
      48             : 
      49             : #ifdef __riscos__
      50             : #define BYTEF_CAST(a) ((Bytef *)(a))
      51             : #else
      52             : #define BYTEF_CAST(a) (a)
      53             : #endif
      54             : 
      55             : 
      56             : 
      57             : int compress_filter_bz2( void *opaque, int control,
      58             :                          IOBUF a, byte *buf, size_t *ret_len);
      59             : 
      60             : #ifdef HAVE_ZIP
      61             : static void
      62         510 : init_compress( compress_filter_context_t *zfx, z_stream *zs )
      63             : {
      64             :     int rc;
      65             :     int level;
      66             : 
      67             : #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
      68             :     static int zlib_initialized = 0;
      69             : 
      70             :     if (!zlib_initialized)
      71             :         zlib_initialized = riscos_load_module("ZLib", zlib_path, 1);
      72             : #endif
      73             : 
      74         510 :     if( opt.compress_level >= 1 && opt.compress_level <= 9 )
      75           0 :         level = opt.compress_level;
      76         510 :     else if( opt.compress_level == -1 )
      77         510 :         level = Z_DEFAULT_COMPRESSION;
      78             :     else {
      79           0 :         log_error("invalid compression level; using default level\n");
      80           0 :         level = Z_DEFAULT_COMPRESSION;
      81             :     }
      82             : 
      83        1020 :     if( (rc = zfx->algo == 1? deflateInit2( zs, level, Z_DEFLATED,
      84             :                                             -13, 8, Z_DEFAULT_STRATEGY)
      85         510 :                             : deflateInit( zs, level )
      86             :                             ) != Z_OK ) {
      87           0 :         log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
      88           0 :                                rc == Z_MEM_ERROR ? "out of core" :
      89           0 :                                rc == Z_VERSION_ERROR ? "invalid lib version" :
      90             :                                                        "unknown error" );
      91             :     }
      92             : 
      93         510 :     zfx->outbufsize = 8192;
      94         510 :     zfx->outbuf = xmalloc( zfx->outbufsize );
      95         510 : }
      96             : 
      97             : static int
      98        2124 : do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
      99             : {
     100             :     int rc;
     101             :     int zrc;
     102             :     unsigned n;
     103             : 
     104             :     do {
     105        2124 :         zs->next_out = BYTEF_CAST (zfx->outbuf);
     106        2124 :         zs->avail_out = zfx->outbufsize;
     107        2124 :         if( DBG_FILTER )
     108           0 :             log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
     109             :                     (unsigned)zs->avail_in, (unsigned)zs->avail_out, flush );
     110        2124 :         zrc = deflate( zs, flush );
     111        2124 :         if( zrc == Z_STREAM_END && flush == Z_FINISH )
     112             :             ;
     113        1614 :         else if( zrc != Z_OK ) {
     114           0 :             if( zs->msg )
     115           0 :                 log_fatal("zlib deflate problem: %s\n", zs->msg );
     116             :             else
     117           0 :                 log_fatal("zlib deflate problem: rc=%d\n", zrc );
     118             :         }
     119        2124 :         n = zfx->outbufsize - zs->avail_out;
     120        2124 :         if( DBG_FILTER )
     121           0 :             log_debug("leave deflate: "
     122             :                       "avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
     123             :                 (unsigned)zs->avail_in, (unsigned)zs->avail_out,
     124             :                                                (unsigned)n, zrc );
     125             : 
     126        2124 :         if( (rc=iobuf_write( a, zfx->outbuf, n )) ) {
     127           0 :             log_debug("deflate: iobuf_write failed\n");
     128           0 :             return rc;
     129             :         }
     130        2124 :     } while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
     131        1714 :     return 0;
     132             : }
     133             : 
     134             : static void
     135         539 : init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
     136             : {
     137             :     int rc;
     138             : 
     139             :     /****************
     140             :      * PGP uses a windowsize of 13 bits. Using a negative value for
     141             :      * it forces zlib not to expect a zlib header.  This is a
     142             :      * undocumented feature Peter Gutmann told me about.
     143             :      *
     144             :      * We must use 15 bits for the inflator because CryptoEx uses 15
     145             :      * bits thus the output would get scrambled w/o error indication
     146             :      * if we would use 13 bits.  For the uncompressing this does not
     147             :      * matter at all.
     148             :      */
     149        1078 :     if( (rc = zfx->algo == 1? inflateInit2( zs, -15)
     150         539 :                             : inflateInit( zs )) != Z_OK ) {
     151           0 :         log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
     152           0 :                                rc == Z_MEM_ERROR ? "out of core" :
     153           0 :                                rc == Z_VERSION_ERROR ? "invalid lib version" :
     154             :                                                        "unknown error" );
     155             :     }
     156             : 
     157         539 :     zfx->inbufsize = 2048;
     158         539 :     zfx->inbuf = xmalloc( zfx->inbufsize );
     159         539 :     zs->avail_in = 0;
     160         539 : }
     161             : 
     162             : static int
     163        1254 : do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
     164             :                IOBUF a, size_t *ret_len )
     165             : {
     166             :     int zrc;
     167        1254 :     int rc = 0;
     168        1254 :     int leave = 0;
     169             :     size_t n;
     170             :     int nread, count;
     171        1254 :     int refill = !zs->avail_in;
     172             : 
     173        1254 :     if( DBG_FILTER )
     174           0 :         log_debug("begin inflate: avail_in=%u, avail_out=%u, inbuf=%u\n",
     175             :                 (unsigned)zs->avail_in, (unsigned)zs->avail_out,
     176             :                 (unsigned)zfx->inbufsize );
     177             :     do {
     178        4317 :         if( zs->avail_in < zfx->inbufsize && refill ) {
     179        3602 :             n = zs->avail_in;
     180        3602 :             if( !n )
     181        3602 :             zs->next_in = BYTEF_CAST (zfx->inbuf);
     182        3602 :             count = zfx->inbufsize - n;
     183        3602 :             nread = iobuf_read( a, zfx->inbuf + n, count );
     184        3602 :             if( nread == -1 ) nread = 0;
     185        3602 :             n += nread;
     186             :             /* Algo 1 has no zlib header which requires us to to give
     187             :              * inflate an extra dummy byte to read. To be on the safe
     188             :              * side we allow for up to 4 ff bytes.  */
     189        3602 :             if( nread < count && zfx->algo == 1 && zfx->algo1hack < 4) {
     190         381 :                 *(zfx->inbuf + n) = 0xFF;
     191         381 :                 zfx->algo1hack++;
     192         381 :                 n++;
     193         381 :                 leave = 1;
     194             :             }
     195        3602 :             zs->avail_in = n;
     196             :         }
     197        4317 :         refill = 1;
     198        4317 :         if( DBG_FILTER )
     199           0 :             log_debug("enter inflate: avail_in=%u, avail_out=%u\n",
     200             :                     (unsigned)zs->avail_in, (unsigned)zs->avail_out);
     201        4317 :         zrc = inflate ( zs, Z_SYNC_FLUSH );
     202        4317 :         if( DBG_FILTER )
     203           0 :             log_debug("leave inflate: avail_in=%u, avail_out=%u, zrc=%d\n",
     204             :                    (unsigned)zs->avail_in, (unsigned)zs->avail_out, zrc);
     205        4317 :         if( zrc == Z_STREAM_END )
     206         539 :             rc = -1; /* eof */
     207        3778 :         else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
     208           0 :             if( zs->msg )
     209           0 :                 log_fatal("zlib inflate problem: %s\n", zs->msg );
     210             :             else
     211           0 :                 log_fatal("zlib inflate problem: rc=%d\n", zrc );
     212             :         }
     213        7919 :     } while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR
     214        7380 :              && !leave);
     215             : 
     216        1254 :     *ret_len = zfx->outbufsize - zs->avail_out;
     217        1254 :     if( DBG_FILTER )
     218           0 :         log_debug("do_uncompress: returning %u bytes (%u ignored)\n",
     219           0 :                   (unsigned int)*ret_len, (unsigned int)zs->avail_in );
     220        1254 :     return rc;
     221             : }
     222             : 
     223             : static int
     224        4556 : compress_filter( void *opaque, int control,
     225             :                  IOBUF a, byte *buf, size_t *ret_len)
     226             : {
     227        4556 :     size_t size = *ret_len;
     228        4556 :     compress_filter_context_t *zfx = opaque;
     229        4556 :     z_stream *zs = zfx->opaque;
     230        4556 :     int rc=0;
     231             : 
     232        4556 :     if( control == IOBUFCTRL_UNDERFLOW ) {
     233        1254 :         if( !zfx->status ) {
     234         539 :             zs = zfx->opaque = xmalloc_clear( sizeof *zs );
     235         539 :             init_uncompress( zfx, zs );
     236         539 :             zfx->status = 1;
     237             :         }
     238             : 
     239        1254 :         zs->next_out = BYTEF_CAST (buf);
     240        1254 :         zs->avail_out = size;
     241        1254 :         zfx->outbufsize = size; /* needed only for calculation */
     242        1254 :         rc = do_uncompress( zfx, zs, a, ret_len );
     243             :     }
     244        3302 :     else if( control == IOBUFCTRL_FLUSH ) {
     245        1204 :         if( !zfx->status ) {
     246             :             PACKET pkt;
     247             :             PKT_compressed cd;
     248         510 :             if(zfx->algo != COMPRESS_ALGO_ZIP
     249         143 :                && zfx->algo != COMPRESS_ALGO_ZLIB)
     250           0 :               BUG();
     251         510 :             memset( &cd, 0, sizeof cd );
     252         510 :             cd.len = 0;
     253         510 :             cd.algorithm = zfx->algo;
     254             :             /* Fixme: We should force a new CTB here:
     255             :                cd.new_ctb = zfx->new_ctb;
     256             :             */
     257         510 :             init_packet( &pkt );
     258         510 :             pkt.pkttype = PKT_COMPRESSED;
     259         510 :             pkt.pkt.compressed = &cd;
     260         510 :             if( build_packet( a, &pkt ))
     261           0 :                 log_bug("build_packet(PKT_COMPRESSED) failed\n");
     262         510 :             zs = zfx->opaque = xmalloc_clear( sizeof *zs );
     263         510 :             init_compress( zfx, zs );
     264         510 :             zfx->status = 2;
     265             :         }
     266             : 
     267        1204 :         zs->next_in = BYTEF_CAST (buf);
     268        1204 :         zs->avail_in = size;
     269        1204 :         rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
     270             :     }
     271        2098 :     else if( control == IOBUFCTRL_FREE ) {
     272        1049 :         if( zfx->status == 1 ) {
     273         539 :             inflateEnd(zs);
     274         539 :             xfree(zs);
     275         539 :             zfx->opaque = NULL;
     276         539 :             xfree(zfx->outbuf); zfx->outbuf = NULL;
     277             :         }
     278         510 :         else if( zfx->status == 2 ) {
     279         510 :             zs->next_in = BYTEF_CAST (buf);
     280         510 :             zs->avail_in = 0;
     281         510 :             do_compress( zfx, zs, Z_FINISH, a );
     282         510 :             deflateEnd(zs);
     283         510 :             xfree(zs);
     284         510 :             zfx->opaque = NULL;
     285         510 :             xfree(zfx->outbuf); zfx->outbuf = NULL;
     286             :         }
     287        1049 :         if (zfx->release)
     288         539 :           zfx->release (zfx);
     289             :     }
     290        1049 :     else if( control == IOBUFCTRL_DESC )
     291           0 :         *(char**)buf = "compress_filter";
     292        4556 :     return rc;
     293             : }
     294             : #endif /*HAVE_ZIP*/
     295             : 
     296             : static void
     297         540 : release_context (compress_filter_context_t *ctx)
     298             : {
     299         540 :   xfree (ctx);
     300         540 : }
     301             : 
     302             : /****************
     303             :  * Handle a compressed packet
     304             :  */
     305             : int
     306         540 : handle_compressed (ctrl_t ctrl, void *procctx, PKT_compressed *cd,
     307             :                    int (*callback)(IOBUF, void *), void *passthru )
     308             : {
     309             :     compress_filter_context_t *cfx;
     310             :     int rc;
     311             : 
     312         540 :     if(check_compress_algo(cd->algorithm))
     313           0 :       return GPG_ERR_COMPR_ALGO;
     314         540 :     cfx = xmalloc_clear (sizeof *cfx);
     315         540 :     cfx->release = release_context;
     316         540 :     cfx->algo = cd->algorithm;
     317         540 :     push_compress_filter(cd->buf,cfx,cd->algorithm);
     318         540 :     if( callback )
     319          10 :         rc = callback(cd->buf, passthru );
     320             :     else
     321         530 :       rc = proc_packets (ctrl,procctx, cd->buf);
     322         540 :     cd->buf = NULL;
     323         540 :     return rc;
     324             : }
     325             : 
     326             : void
     327        1050 : push_compress_filter(IOBUF out,compress_filter_context_t *zfx,int algo)
     328             : {
     329        1050 :   push_compress_filter2(out,zfx,algo,0);
     330        1050 : }
     331             : 
     332             : void
     333        1050 : push_compress_filter2(IOBUF out,compress_filter_context_t *zfx,
     334             :                       int algo,int rel)
     335             : {
     336        1050 :   if(algo>=0)
     337        1050 :     zfx->algo=algo;
     338             :   else
     339           0 :     zfx->algo=DEFAULT_COMPRESS_ALGO;
     340             : 
     341        1050 :   switch(zfx->algo)
     342             :     {
     343             :     case COMPRESS_ALGO_NONE:
     344           0 :       break;
     345             : 
     346             : #ifdef HAVE_ZIP
     347             :     case COMPRESS_ALGO_ZIP:
     348             :     case COMPRESS_ALGO_ZLIB:
     349        1049 :       iobuf_push_filter2(out,compress_filter,zfx,rel);
     350        1049 :       break;
     351             : #endif
     352             : 
     353             : #ifdef HAVE_BZIP2
     354             :     case COMPRESS_ALGO_BZIP2:
     355           1 :       iobuf_push_filter2(out,compress_filter_bz2,zfx,rel);
     356           1 :       break;
     357             : #endif
     358             : 
     359             :     default:
     360           0 :       BUG();
     361             :     }
     362        1050 : }

Generated by: LCOV version 1.11