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
;
124 log_debug("begin bzDecompress: avail_in=%u, avail_out=%u, inbuf=%u\n",
125 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
,
126 (unsigned)zfx
->inbufsize
);
129 if( bzs
->avail_in
< zfx
->inbufsize
&& refill
)
133 bzs
->next_in
= zfx
->inbuf
;
134 count
= zfx
->inbufsize
- n
;
135 nread
= iobuf_read( a
, zfx
->inbuf
+ n
, count
);
148 log_debug("enter bzDecompress: avail_in=%u, avail_out=%u\n",
149 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
);
151 zrc
=BZ2_bzDecompress(bzs
);
153 log_debug("leave bzDecompress: avail_in=%u, avail_out=%u, zrc=%d\n",
154 (unsigned)bzs
->avail_in
, (unsigned)bzs
->avail_out
, zrc
);
155 if( zrc
== BZ_STREAM_END
)
157 else if( zrc
!= BZ_OK
&& zrc
!= BZ_PARAM_ERROR
)
158 log_fatal("bz2lib inflate problem: rc=%d\n", zrc
);
159 else if (zrc
== BZ_OK
&& eofseen
160 && !bzs
->avail_in
&& bzs
->avail_out
> 0)
162 log_error ("unexpected EOF in bz2lib\n");
163 rc
= GPG_ERR_BAD_DATA
;
167 while( bzs
->avail_out
&& zrc
!= BZ_STREAM_END
&& zrc
!= BZ_PARAM_ERROR
);
169 /* I'm not completely happy with the two uses of BZ_PARAM_ERROR
170 here. The corresponding zlib function is Z_BUF_ERROR, which
171 covers a narrower scope than BZ_PARAM_ERROR. -dshaw */
173 *ret_len
= zfx
->outbufsize
- bzs
->avail_out
;
175 log_debug("do_uncompress: returning %u bytes\n", (unsigned)*ret_len
);
180 compress_filter_bz2( void *opaque
, int control
,
181 IOBUF a
, byte
*buf
, size_t *ret_len
)
183 size_t size
= *ret_len
;
184 compress_filter_context_t
*zfx
= opaque
;
185 bz_stream
*bzs
= zfx
->opaque
;
188 if( control
== IOBUFCTRL_UNDERFLOW
)
192 bzs
= zfx
->opaque
= xmalloc_clear( sizeof *bzs
);
193 init_uncompress( zfx
, bzs
);
198 bzs
->avail_out
= size
;
199 zfx
->outbufsize
= size
; /* needed only for calculation */
200 rc
= do_uncompress( zfx
, bzs
, a
, ret_len
);
202 else if( control
== IOBUFCTRL_FLUSH
)
209 if( zfx
->algo
!= COMPRESS_ALGO_BZIP2
)
211 memset( &cd
, 0, sizeof cd
);
213 cd
.algorithm
= zfx
->algo
;
215 pkt
.pkttype
= PKT_COMPRESSED
;
216 pkt
.pkt
.compressed
= &cd
;
217 if( build_packet( a
, &pkt
))
218 log_bug("build_packet(PKT_COMPRESSED) failed\n");
219 bzs
= zfx
->opaque
= xmalloc_clear( sizeof *bzs
);
220 init_compress( zfx
, bzs
);
225 bzs
->avail_in
= size
;
226 rc
= do_compress( zfx
, bzs
, BZ_RUN
, a
);
228 else if( control
== IOBUFCTRL_FREE
)
230 if( zfx
->status
== 1 )
232 BZ2_bzDecompressEnd(bzs
);
235 xfree(zfx
->outbuf
); zfx
->outbuf
= NULL
;
237 else if( zfx
->status
== 2 )
241 do_compress( zfx
, bzs
, BZ_FINISH
, a
);
242 BZ2_bzCompressEnd(bzs
);
245 xfree(zfx
->outbuf
); zfx
->outbuf
= NULL
;
250 else if( control
== IOBUFCTRL_DESC
)
251 *(char**)buf
= "compress_filter";