Imported Upstream version 2.1.11
[platform/upstream/gpg2.git] / g10 / compress.c
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 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     if( opt.compress_level >= 1 && opt.compress_level <= 9 )
75         level = opt.compress_level;
76     else if( opt.compress_level == -1 )
77         level = Z_DEFAULT_COMPRESSION;
78     else {
79         log_error("invalid compression level; using default level\n");
80         level = Z_DEFAULT_COMPRESSION;
81     }
82
83     if( (rc = zfx->algo == 1? deflateInit2( zs, level, Z_DEFLATED,
84                                             -13, 8, Z_DEFAULT_STRATEGY)
85                             : deflateInit( zs, level )
86                             ) != Z_OK ) {
87         log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
88                                rc == Z_MEM_ERROR ? "out of core" :
89                                rc == Z_VERSION_ERROR ? "invalid lib version" :
90                                                        "unknown error" );
91     }
92
93     zfx->outbufsize = 8192;
94     zfx->outbuf = xmalloc( zfx->outbufsize );
95 }
96
97 static int
98 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         zs->next_out = BYTEF_CAST (zfx->outbuf);
106         zs->avail_out = zfx->outbufsize;
107         if( DBG_FILTER )
108             log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
109                     (unsigned)zs->avail_in, (unsigned)zs->avail_out, flush );
110         zrc = deflate( zs, flush );
111         if( zrc == Z_STREAM_END && flush == Z_FINISH )
112             ;
113         else if( zrc != Z_OK ) {
114             if( zs->msg )
115                 log_fatal("zlib deflate problem: %s\n", zs->msg );
116             else
117                 log_fatal("zlib deflate problem: rc=%d\n", zrc );
118         }
119         n = zfx->outbufsize - zs->avail_out;
120         if( DBG_FILTER )
121             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         if( (rc=iobuf_write( a, zfx->outbuf, n )) ) {
127             log_debug("deflate: iobuf_write failed\n");
128             return rc;
129         }
130     } while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
131     return 0;
132 }
133
134 static void
135 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     if( (rc = zfx->algo == 1? inflateInit2( zs, -15)
150                             : inflateInit( zs )) != Z_OK ) {
151         log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
152                                rc == Z_MEM_ERROR ? "out of core" :
153                                rc == Z_VERSION_ERROR ? "invalid lib version" :
154                                                        "unknown error" );
155     }
156
157     zfx->inbufsize = 2048;
158     zfx->inbuf = xmalloc( zfx->inbufsize );
159     zs->avail_in = 0;
160 }
161
162 static int
163 do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
164                IOBUF a, size_t *ret_len )
165 {
166     int zrc;
167     int rc = 0;
168     int leave = 0;
169     size_t n;
170     int nread, count;
171     int refill = !zs->avail_in;
172
173     if( DBG_FILTER )
174         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         if( zs->avail_in < zfx->inbufsize && refill ) {
179             n = zs->avail_in;
180             if( !n )
181             zs->next_in = BYTEF_CAST (zfx->inbuf);
182             count = zfx->inbufsize - n;
183             nread = iobuf_read( a, zfx->inbuf + n, count );
184             if( nread == -1 ) nread = 0;
185             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             if( nread < count && zfx->algo == 1 && zfx->algo1hack < 4) {
190                 *(zfx->inbuf + n) = 0xFF;
191                 zfx->algo1hack++;
192                 n++;
193                 leave = 1;
194             }
195             zs->avail_in = n;
196         }
197         refill = 1;
198         if( DBG_FILTER )
199             log_debug("enter inflate: avail_in=%u, avail_out=%u\n",
200                     (unsigned)zs->avail_in, (unsigned)zs->avail_out);
201         zrc = inflate ( zs, Z_SYNC_FLUSH );
202         if( DBG_FILTER )
203             log_debug("leave inflate: avail_in=%u, avail_out=%u, zrc=%d\n",
204                    (unsigned)zs->avail_in, (unsigned)zs->avail_out, zrc);
205         if( zrc == Z_STREAM_END )
206             rc = -1; /* eof */
207         else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
208             if( zs->msg )
209                 log_fatal("zlib inflate problem: %s\n", zs->msg );
210             else
211                 log_fatal("zlib inflate problem: rc=%d\n", zrc );
212         }
213     } while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR
214              && !leave);
215
216     *ret_len = zfx->outbufsize - zs->avail_out;
217     if( DBG_FILTER )
218         log_debug("do_uncompress: returning %u bytes (%u ignored)\n",
219                   (unsigned int)*ret_len, (unsigned int)zs->avail_in );
220     return rc;
221 }
222
223 static int
224 compress_filter( void *opaque, int control,
225                  IOBUF a, byte *buf, size_t *ret_len)
226 {
227     size_t size = *ret_len;
228     compress_filter_context_t *zfx = opaque;
229     z_stream *zs = zfx->opaque;
230     int rc=0;
231
232     if( control == IOBUFCTRL_UNDERFLOW ) {
233         if( !zfx->status ) {
234             zs = zfx->opaque = xmalloc_clear( sizeof *zs );
235             init_uncompress( zfx, zs );
236             zfx->status = 1;
237         }
238
239         zs->next_out = BYTEF_CAST (buf);
240         zs->avail_out = size;
241         zfx->outbufsize = size; /* needed only for calculation */
242         rc = do_uncompress( zfx, zs, a, ret_len );
243     }
244     else if( control == IOBUFCTRL_FLUSH ) {
245         if( !zfx->status ) {
246             PACKET pkt;
247             PKT_compressed cd;
248             if(zfx->algo != COMPRESS_ALGO_ZIP
249                && zfx->algo != COMPRESS_ALGO_ZLIB)
250               BUG();
251             memset( &cd, 0, sizeof cd );
252             cd.len = 0;
253             cd.algorithm = zfx->algo;
254             /* Fixme: We should force a new CTB here:
255                cd.new_ctb = zfx->new_ctb;
256             */
257             init_packet( &pkt );
258             pkt.pkttype = PKT_COMPRESSED;
259             pkt.pkt.compressed = &cd;
260             if( build_packet( a, &pkt ))
261                 log_bug("build_packet(PKT_COMPRESSED) failed\n");
262             zs = zfx->opaque = xmalloc_clear( sizeof *zs );
263             init_compress( zfx, zs );
264             zfx->status = 2;
265         }
266
267         zs->next_in = BYTEF_CAST (buf);
268         zs->avail_in = size;
269         rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
270     }
271     else if( control == IOBUFCTRL_FREE ) {
272         if( zfx->status == 1 ) {
273             inflateEnd(zs);
274             xfree(zs);
275             zfx->opaque = NULL;
276             xfree(zfx->outbuf); zfx->outbuf = NULL;
277         }
278         else if( zfx->status == 2 ) {
279             zs->next_in = BYTEF_CAST (buf);
280             zs->avail_in = 0;
281             do_compress( zfx, zs, Z_FINISH, a );
282             deflateEnd(zs);
283             xfree(zs);
284             zfx->opaque = NULL;
285             xfree(zfx->outbuf); zfx->outbuf = NULL;
286         }
287         if (zfx->release)
288           zfx->release (zfx);
289     }
290     else if( control == IOBUFCTRL_DESC )
291         mem2str (buf, "compress_filter", *ret_len);
292     return rc;
293 }
294 #endif /*HAVE_ZIP*/
295
296 static void
297 release_context (compress_filter_context_t *ctx)
298 {
299   xfree (ctx);
300 }
301
302 /****************
303  * Handle a compressed packet
304  */
305 int
306 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     if(check_compress_algo(cd->algorithm))
313       return GPG_ERR_COMPR_ALGO;
314     cfx = xmalloc_clear (sizeof *cfx);
315     cfx->release = release_context;
316     cfx->algo = cd->algorithm;
317     push_compress_filter(cd->buf,cfx,cd->algorithm);
318     if( callback )
319         rc = callback(cd->buf, passthru );
320     else
321       rc = proc_packets (ctrl,procctx, cd->buf);
322     cd->buf = NULL;
323     return rc;
324 }
325
326 void
327 push_compress_filter(IOBUF out,compress_filter_context_t *zfx,int algo)
328 {
329   push_compress_filter2(out,zfx,algo,0);
330 }
331
332 void
333 push_compress_filter2(IOBUF out,compress_filter_context_t *zfx,
334                       int algo,int rel)
335 {
336   if(algo>=0)
337     zfx->algo=algo;
338   else
339     zfx->algo=DEFAULT_COMPRESS_ALGO;
340
341   switch(zfx->algo)
342     {
343     case COMPRESS_ALGO_NONE:
344       break;
345
346 #ifdef HAVE_ZIP
347     case COMPRESS_ALGO_ZIP:
348     case COMPRESS_ALGO_ZLIB:
349       iobuf_push_filter2(out,compress_filter,zfx,rel);
350       break;
351 #endif
352
353 #ifdef HAVE_BZIP2
354     case COMPRESS_ALGO_BZIP2:
355       iobuf_push_filter2(out,compress_filter_bz2,zfx,rel);
356       break;
357 #endif
358
359     default:
360       BUG();
361     }
362 }