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 3 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, see <http://www.gnu.org/licenses/>.
22 #include <stdio.h> /* Early versions of bzlib (1.0) require stdio.h */
32 /* Note that the code in compress.c is nearly identical to the code
33 here, so if you fix a bug here, look there to see if a matching bug
34 needs to be fixed. I tried to have one set of functions that could
35 do ZIP, ZLIB, and BZIP2, but it became dangerously unreadable with
36 #ifdefs and if(algo) -dshaw */
39 init_compress( compress_filter_context_t
*zfx
, bz_stream
*bzs
)
44 if( opt
.bz2_compress_level
>= 1 && opt
.bz2_compress_level
<= 9 )
45 level
= opt
.bz2_compress_level
;
46 else if( opt
.bz2_compress_level
== -1 )
47 level
= 6; /* no particular reason, but it seems reasonable */
50 log_error("invalid compression level; using default level\n");
54 if((rc
=BZ2_bzCompressInit(bzs
,level
,0,0))!=BZ_OK
)
55 log_fatal("bz2lib problem: %d\n",rc
);
57 zfx
->outbufsize
= 8192;
58 zfx
->outbuf
= xmalloc( zfx
->outbufsize
);
62 do_compress(compress_filter_context_t
*zfx
, bz_stream
*bzs
, int flush
, IOBUF a
)
70 bzs
->next_out
= zfx
->outbuf
;
71 bzs
->avail_out
= zfx
->outbufsize
;
73 log_debug("enter bzCompress: avail_in=%u, avail_out=%u, flush=%d\n",
74 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
, flush
);
75 zrc
= BZ2_bzCompress( bzs
, flush
);
76 if( zrc
== BZ_STREAM_END
&& flush
== BZ_FINISH
)
78 else if( zrc
!= BZ_RUN_OK
&& zrc
!= BZ_FINISH_OK
)
79 log_fatal("bz2lib deflate problem: rc=%d\n", zrc
);
81 n
= zfx
->outbufsize
- bzs
->avail_out
;
83 log_debug("leave bzCompress:"
84 " avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
85 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
,
88 if( (rc
=iobuf_write( a
, zfx
->outbuf
, n
)) )
90 log_debug("bzCompress: iobuf_write failed\n");
94 while( bzs
->avail_in
|| (flush
== BZ_FINISH
&& zrc
!= BZ_STREAM_END
) );
100 init_uncompress( compress_filter_context_t
*zfx
, bz_stream
*bzs
)
104 if((rc
=BZ2_bzDecompressInit(bzs
,0,opt
.bz2_decompress_lowmem
))!=BZ_OK
)
105 log_fatal("bz2lib problem: %d\n",rc
);
107 zfx
->inbufsize
= 2048;
108 zfx
->inbuf
= xmalloc( zfx
->inbufsize
);
113 do_uncompress( compress_filter_context_t
*zfx
, bz_stream
*bzs
,
114 IOBUF a
, size_t *ret_len
)
120 int refill
= !bzs
->avail_in
;
123 log_debug("begin bzDecompress: avail_in=%u, avail_out=%u, inbuf=%u\n",
124 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
,
125 (unsigned)zfx
->inbufsize
);
128 if( bzs
->avail_in
< zfx
->inbufsize
&& refill
)
132 bzs
->next_in
= zfx
->inbuf
;
133 count
= zfx
->inbufsize
- n
;
134 nread
= iobuf_read( a
, zfx
->inbuf
+ n
, count
);
135 if( nread
== -1 ) nread
= 0;
143 log_debug("enter bzDecompress: avail_in=%u, avail_out=%u\n",
144 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
);
146 zrc
=BZ2_bzDecompress(bzs
);
148 log_debug("leave bzDecompress: avail_in=%u, avail_out=%u, zrc=%d\n",
149 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
, zrc
);
150 if( zrc
== BZ_STREAM_END
)
152 else if( zrc
!= BZ_OK
&& zrc
!= BZ_PARAM_ERROR
)
153 log_fatal("bz2lib inflate problem: rc=%d\n", zrc
);
155 while( bzs
->avail_out
&& zrc
!= BZ_STREAM_END
&& zrc
!= BZ_PARAM_ERROR
);
157 /* I'm not completely happy with the two uses of BZ_PARAM_ERROR
158 here. The corresponding zlib function is Z_BUF_ERROR, which
159 covers a narrower scope than BZ_PARAM_ERROR. -dshaw */
161 *ret_len
= zfx
->outbufsize
- bzs
->avail_out
;
163 log_debug("do_uncompress: returning %u bytes\n", (unsigned)*ret_len
);
168 compress_filter_bz2( void *opaque
, int control
,
169 IOBUF a
, byte
*buf
, size_t *ret_len
)
171 size_t size
= *ret_len
;
172 compress_filter_context_t
*zfx
= opaque
;
173 bz_stream
*bzs
= zfx
->opaque
;
176 if( control
== IOBUFCTRL_UNDERFLOW
)
180 bzs
= zfx
->opaque
= xmalloc_clear( sizeof *bzs
);
181 init_uncompress( zfx
, bzs
);
186 bzs
->avail_out
= size
;
187 zfx
->outbufsize
= size
; /* needed only for calculation */
188 rc
= do_uncompress( zfx
, bzs
, a
, ret_len
);
190 else if( control
== IOBUFCTRL_FLUSH
)
197 if( zfx
->algo
!= COMPRESS_ALGO_BZIP2
)
199 memset( &cd
, 0, sizeof cd
);
201 cd
.algorithm
= zfx
->algo
;
203 pkt
.pkttype
= PKT_COMPRESSED
;
204 pkt
.pkt
.compressed
= &cd
;
205 if( build_packet( a
, &pkt
))
206 log_bug("build_packet(PKT_COMPRESSED) failed\n");
207 bzs
= zfx
->opaque
= xmalloc_clear( sizeof *bzs
);
208 init_compress( zfx
, bzs
);
213 bzs
->avail_in
= size
;
214 rc
= do_compress( zfx
, bzs
, BZ_RUN
, a
);
216 else if( control
== IOBUFCTRL_FREE
)
218 if( zfx
->status
== 1 )
220 BZ2_bzDecompressEnd(bzs
);
223 xfree(zfx
->outbuf
); zfx
->outbuf
= NULL
;
225 else if( zfx
->status
== 2 )
229 do_compress( zfx
, bzs
, BZ_FINISH
, a
);
230 BZ2_bzCompressEnd(bzs
);
233 xfree(zfx
->outbuf
); zfx
->outbuf
= NULL
;
238 else if( control
== IOBUFCTRL_DESC
)
239 *(char**)buf
= "compress_filter";