1 /* compress.c - bzip2 compress filter
2 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
24 #include <stdio.h> /* Early versions of bzlib (1.0) require stdio.h */
34 /* Note that the code in compress.c is nearly identical to the code
35 here, so if you fix a bug here, look there to see if a matching bug
36 needs to be fixed. I tried to have one set of functions that could
37 do ZIP, ZLIB, and BZIP2, but it became dangerously unreadable with
38 #ifdefs and if(algo) -dshaw */
41 init_compress( compress_filter_context_t
*zfx
, bz_stream
*bzs
)
46 if( opt
.bz2_compress_level
>= 1 && opt
.bz2_compress_level
<= 9 )
47 level
= opt
.bz2_compress_level
;
48 else if( opt
.bz2_compress_level
== -1 )
49 level
= 6; /* no particular reason, but it seems reasonable */
52 log_error("invalid compression level; using default level\n");
56 if((rc
=BZ2_bzCompressInit(bzs
,level
,0,0))!=BZ_OK
)
57 log_fatal("bz2lib problem: %d\n",rc
);
59 zfx
->outbufsize
= 8192;
60 zfx
->outbuf
= xmalloc( zfx
->outbufsize
);
64 do_compress(compress_filter_context_t
*zfx
, bz_stream
*bzs
, int flush
, IOBUF a
)
72 bzs
->next_out
= zfx
->outbuf
;
73 bzs
->avail_out
= zfx
->outbufsize
;
75 log_debug("enter bzCompress: avail_in=%u, avail_out=%u, flush=%d\n",
76 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
, flush
);
77 zrc
= BZ2_bzCompress( bzs
, flush
);
78 if( zrc
== BZ_STREAM_END
&& flush
== BZ_FINISH
)
80 else if( zrc
!= BZ_RUN_OK
&& zrc
!= BZ_FINISH_OK
)
81 log_fatal("bz2lib deflate problem: rc=%d\n", zrc
);
83 n
= zfx
->outbufsize
- bzs
->avail_out
;
85 log_debug("leave bzCompress:"
86 " avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
87 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
,
90 if( (rc
=iobuf_write( a
, zfx
->outbuf
, n
)) )
92 log_debug("bzCompress: iobuf_write failed\n");
96 while( bzs
->avail_in
|| (flush
== BZ_FINISH
&& zrc
!= BZ_STREAM_END
) );
102 init_uncompress( compress_filter_context_t
*zfx
, bz_stream
*bzs
)
106 if((rc
=BZ2_bzDecompressInit(bzs
,0,opt
.bz2_decompress_lowmem
))!=BZ_OK
)
107 log_fatal("bz2lib problem: %d\n",rc
);
109 zfx
->inbufsize
= 2048;
110 zfx
->inbuf
= xmalloc( zfx
->inbufsize
);
115 do_uncompress( compress_filter_context_t
*zfx
, bz_stream
*bzs
,
116 IOBUF a
, size_t *ret_len
)
122 int refill
= !bzs
->avail_in
;
125 log_debug("begin bzDecompress: avail_in=%u, avail_out=%u, inbuf=%u\n",
126 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
,
127 (unsigned)zfx
->inbufsize
);
130 if( bzs
->avail_in
< zfx
->inbufsize
&& refill
)
134 bzs
->next_in
= zfx
->inbuf
;
135 count
= zfx
->inbufsize
- n
;
136 nread
= iobuf_read( a
, zfx
->inbuf
+ n
, count
);
137 if( nread
== -1 ) nread
= 0;
145 log_debug("enter bzDecompress: avail_in=%u, avail_out=%u\n",
146 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
);
148 zrc
=BZ2_bzDecompress(bzs
);
150 log_debug("leave bzDecompress: avail_in=%u, avail_out=%u, zrc=%d\n",
151 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
, zrc
);
152 if( zrc
== BZ_STREAM_END
)
154 else if( zrc
!= BZ_OK
&& zrc
!= BZ_PARAM_ERROR
)
155 log_fatal("bz2lib inflate problem: rc=%d\n", zrc
);
157 while( bzs
->avail_out
&& zrc
!= BZ_STREAM_END
&& zrc
!= BZ_PARAM_ERROR
);
159 /* I'm not completely happy with the two uses of BZ_PARAM_ERROR
160 here. The corresponding zlib function is Z_BUF_ERROR, which
161 covers a narrower scope than BZ_PARAM_ERROR. -dshaw */
163 *ret_len
= zfx
->outbufsize
- bzs
->avail_out
;
165 log_debug("do_uncompress: returning %u bytes\n", (unsigned)*ret_len
);
170 compress_filter_bz2( void *opaque
, int control
,
171 IOBUF a
, byte
*buf
, size_t *ret_len
)
173 size_t size
= *ret_len
;
174 compress_filter_context_t
*zfx
= opaque
;
175 bz_stream
*bzs
= zfx
->opaque
;
178 if( control
== IOBUFCTRL_UNDERFLOW
)
182 bzs
= zfx
->opaque
= xmalloc_clear( sizeof *bzs
);
183 init_uncompress( zfx
, bzs
);
188 bzs
->avail_out
= size
;
189 zfx
->outbufsize
= size
; /* needed only for calculation */
190 rc
= do_uncompress( zfx
, bzs
, a
, ret_len
);
192 else if( control
== IOBUFCTRL_FLUSH
)
199 if( zfx
->algo
!= COMPRESS_ALGO_BZIP2
)
201 memset( &cd
, 0, sizeof cd
);
203 cd
.algorithm
= zfx
->algo
;
205 pkt
.pkttype
= PKT_COMPRESSED
;
206 pkt
.pkt
.compressed
= &cd
;
207 if( build_packet( a
, &pkt
))
208 log_bug("build_packet(PKT_COMPRESSED) failed\n");
209 bzs
= zfx
->opaque
= xmalloc_clear( sizeof *bzs
);
210 init_compress( zfx
, bzs
);
215 bzs
->avail_in
= size
;
216 rc
= do_compress( zfx
, bzs
, BZ_RUN
, a
);
218 else if( control
== IOBUFCTRL_FREE
)
220 if( zfx
->status
== 1 )
222 BZ2_bzDecompressEnd(bzs
);
225 xfree(zfx
->outbuf
); zfx
->outbuf
= NULL
;
227 else if( zfx
->status
== 2 )
231 do_compress( zfx
, bzs
, BZ_FINISH
, a
);
232 BZ2_bzCompressEnd(bzs
);
235 xfree(zfx
->outbuf
); zfx
->outbuf
= NULL
;
240 else if( control
== IOBUFCTRL_DESC
)
241 *(char**)buf
= "compress_filter";