1 /* compress.c - compress filter
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3 * 2003, 2006 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
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.
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.
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/>.
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 */
35 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
36 # include "zlib-riscos.h"
48 #define BYTEF_CAST(a) ((Bytef *)(a))
50 #define BYTEF_CAST(a) (a)
55 int compress_filter_bz2( void *opaque
, int control
,
56 IOBUF a
, byte
*buf
, size_t *ret_len
);
59 init_compress( compress_filter_context_t
*zfx
, z_stream
*zs
)
64 #if defined(__riscos__) && defined(USE_ZLIBRISCOS)
65 static int zlib_initialized
= 0;
67 if (!zlib_initialized
)
68 zlib_initialized
= riscos_load_module("ZLib", zlib_path
, 1);
71 if( opt
.compress_level
>= 1 && opt
.compress_level
<= 9 )
72 level
= opt
.compress_level
;
73 else if( opt
.compress_level
== -1 )
74 level
= Z_DEFAULT_COMPRESSION
;
76 log_error("invalid compression level; using default level\n");
77 level
= Z_DEFAULT_COMPRESSION
;
80 if( (rc
= zfx
->algo
== 1? deflateInit2( zs
, level
, Z_DEFLATED
,
81 -13, 8, Z_DEFAULT_STRATEGY
)
82 : deflateInit( zs
, level
)
84 log_fatal("zlib problem: %s\n", zs
->msg
? zs
->msg
:
85 rc
== Z_MEM_ERROR
? "out of core" :
86 rc
== Z_VERSION_ERROR
? "invalid lib version" :
90 zfx
->outbufsize
= 8192;
91 zfx
->outbuf
= xmalloc( zfx
->outbufsize
);
95 do_compress( compress_filter_context_t
*zfx
, z_stream
*zs
, int flush
, IOBUF a
)
102 zs
->next_out
= BYTEF_CAST (zfx
->outbuf
);
103 zs
->avail_out
= zfx
->outbufsize
;
105 log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
106 (unsigned)zs
->avail_in
, (unsigned)zs
->avail_out
, flush
);
107 zrc
= deflate( zs
, flush
);
108 if( zrc
== Z_STREAM_END
&& flush
== Z_FINISH
)
110 else if( zrc
!= Z_OK
) {
112 log_fatal("zlib deflate problem: %s\n", zs
->msg
);
114 log_fatal("zlib deflate problem: rc=%d\n", zrc
);
116 n
= zfx
->outbufsize
- zs
->avail_out
;
118 log_debug("leave deflate: "
119 "avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
120 (unsigned)zs
->avail_in
, (unsigned)zs
->avail_out
,
123 if( (rc
=iobuf_write( a
, zfx
->outbuf
, n
)) ) {
124 log_debug("deflate: iobuf_write failed\n");
127 } while( zs
->avail_in
|| (flush
== Z_FINISH
&& zrc
!= Z_STREAM_END
) );
132 init_uncompress( compress_filter_context_t
*zfx
, z_stream
*zs
)
137 * PGP uses a windowsize of 13 bits. Using a negative value for
138 * it forces zlib not to expect a zlib header. This is a
139 * undocumented feature Peter Gutmann told me about.
141 * We must use 15 bits for the inflator because CryptoEx uses 15
142 * bits thus the output would get scrambled w/o error indication
143 * if we would use 13 bits. For the uncompressing this does not
146 if( (rc
= zfx
->algo
== 1? inflateInit2( zs
, -15)
147 : inflateInit( zs
)) != Z_OK
) {
148 log_fatal("zlib problem: %s\n", zs
->msg
? zs
->msg
:
149 rc
== Z_MEM_ERROR
? "out of core" :
150 rc
== Z_VERSION_ERROR
? "invalid lib version" :
154 zfx
->inbufsize
= 2048;
155 zfx
->inbuf
= xmalloc( zfx
->inbufsize
);
160 do_uncompress( compress_filter_context_t
*zfx
, z_stream
*zs
,
161 IOBUF a
, size_t *ret_len
)
167 int refill
= !zs
->avail_in
;
170 log_debug("begin inflate: avail_in=%u, avail_out=%u, inbuf=%u\n",
171 (unsigned)zs
->avail_in
, (unsigned)zs
->avail_out
,
172 (unsigned)zfx
->inbufsize
);
174 if( zs
->avail_in
< zfx
->inbufsize
&& refill
) {
177 zs
->next_in
= BYTEF_CAST (zfx
->inbuf
);
178 count
= zfx
->inbufsize
- n
;
179 nread
= iobuf_read( a
, zfx
->inbuf
+ n
, count
);
180 if( nread
== -1 ) nread
= 0;
182 /* If we use the undocumented feature to suppress
183 * the zlib header, we have to give inflate an
184 * extra dummy byte to read */
185 if( nread
< count
&& zfx
->algo
== 1 ) {
186 *(zfx
->inbuf
+ n
) = 0xFF; /* is it really needed ? */
194 log_debug("enter inflate: avail_in=%u, avail_out=%u\n",
195 (unsigned)zs
->avail_in
, (unsigned)zs
->avail_out
);
196 zrc
= inflate ( zs
, Z_SYNC_FLUSH
);
198 log_debug("leave inflate: avail_in=%u, avail_out=%u, zrc=%d\n",
199 (unsigned)zs
->avail_in
, (unsigned)zs
->avail_out
, zrc
);
200 if( zrc
== Z_STREAM_END
)
202 else if( zrc
!= Z_OK
&& zrc
!= Z_BUF_ERROR
) {
204 log_fatal("zlib inflate problem: %s\n", zs
->msg
);
206 log_fatal("zlib inflate problem: rc=%d\n", zrc
);
208 } while( zs
->avail_out
&& zrc
!= Z_STREAM_END
&& zrc
!= Z_BUF_ERROR
);
210 *ret_len
= zfx
->outbufsize
- zs
->avail_out
;
212 log_debug("do_uncompress: returning %u bytes (%u ignored)\n",
213 (unsigned int)*ret_len
, (unsigned int)zs
->avail_in
);
218 compress_filter( void *opaque
, int control
,
219 IOBUF a
, byte
*buf
, size_t *ret_len
)
221 size_t size
= *ret_len
;
222 compress_filter_context_t
*zfx
= opaque
;
223 z_stream
*zs
= zfx
->opaque
;
226 if( control
== IOBUFCTRL_UNDERFLOW
) {
228 zs
= zfx
->opaque
= xmalloc_clear( sizeof *zs
);
229 init_uncompress( zfx
, zs
);
233 zs
->next_out
= BYTEF_CAST (buf
);
234 zs
->avail_out
= size
;
235 zfx
->outbufsize
= size
; /* needed only for calculation */
236 rc
= do_uncompress( zfx
, zs
, a
, ret_len
);
238 else if( control
== IOBUFCTRL_FLUSH
) {
242 if(zfx
->algo
!= COMPRESS_ALGO_ZIP
243 && zfx
->algo
!= COMPRESS_ALGO_ZLIB
)
245 memset( &cd
, 0, sizeof cd
);
247 cd
.algorithm
= zfx
->algo
;
249 pkt
.pkttype
= PKT_COMPRESSED
;
250 pkt
.pkt
.compressed
= &cd
;
251 if( build_packet( a
, &pkt
))
252 log_bug("build_packet(PKT_COMPRESSED) failed\n");
253 zs
= zfx
->opaque
= xmalloc_clear( sizeof *zs
);
254 init_compress( zfx
, zs
);
258 zs
->next_in
= BYTEF_CAST (buf
);
260 rc
= do_compress( zfx
, zs
, Z_NO_FLUSH
, a
);
262 else if( control
== IOBUFCTRL_FREE
) {
263 if( zfx
->status
== 1 ) {
267 xfree(zfx
->outbuf
); zfx
->outbuf
= NULL
;
269 else if( zfx
->status
== 2 ) {
270 zs
->next_in
= BYTEF_CAST (buf
);
272 do_compress( zfx
, zs
, Z_FINISH
, a
);
276 xfree(zfx
->outbuf
); zfx
->outbuf
= NULL
;
281 else if( control
== IOBUFCTRL_DESC
)
282 *(char**)buf
= "compress_filter";
288 release_context (compress_filter_context_t
*ctx
)
294 * Handle a compressed packet
297 handle_compressed( void *procctx
, PKT_compressed
*cd
,
298 int (*callback
)(IOBUF
, void *), void *passthru
)
300 compress_filter_context_t
*cfx
;
303 if(check_compress_algo(cd
->algorithm
))
304 return G10ERR_COMPR_ALGO
;
305 cfx
= xmalloc_clear (sizeof *cfx
);
306 cfx
->release
= release_context
;
307 cfx
->algo
= cd
->algorithm
;
308 push_compress_filter(cd
->buf
,cfx
,cd
->algorithm
);
310 rc
= callback(cd
->buf
, passthru
);
312 rc
= proc_packets(procctx
, cd
->buf
);
318 push_compress_filter(IOBUF out
,compress_filter_context_t
*zfx
,int algo
)
320 push_compress_filter2(out
,zfx
,algo
,0);
324 push_compress_filter2(IOBUF out
,compress_filter_context_t
*zfx
,
330 zfx
->algo
=DEFAULT_COMPRESS_ALGO
;
334 case COMPRESS_ALGO_NONE
:
337 case COMPRESS_ALGO_ZIP
:
338 case COMPRESS_ALGO_ZLIB
:
339 iobuf_push_filter2(out
,compress_filter
,zfx
,rel
);
343 case COMPRESS_ALGO_BZIP2
:
344 iobuf_push_filter2(out
,compress_filter_bz2
,zfx
,rel
);